Изменение строк C в цикле, экранирование символов

#c #c-strings

#c #c-строки

Вопрос:

Я немного новичок в C, и мне нужно изменить программу, которую мне дали. Он выводит строку, но я должен изменить эту строку, убедившись, что она правильно экранирует специальные символы CSV. Я бы знал, как это сделать с помощью Python, потому что это простой способ поиска и замены, но я борюсь со строками в C.

Вот что у меня получилось на данный момент:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>

void escape_csv(const char * src) {
    printf("Input: %sn", src);
    
    char escapes[] = {',', '"', 'n', 'r', ''};
    int needs_quoting = !!src[strcspn(src, escapes)];

    char buf[strlen(src) * 2];

    int pos = 0;

    if (needs_quoting) {
        buf[pos] = '"';
        pos  ;
    }
        

    for (int i = 0; i < strlen(src); i  )
    {
        if (src[i] == '"') {
            buf[pos] = '"';
            pos  ;
        }
        buf[pos] = src[i];
        pos  ;
    }
    if (needs_quoting) {
        buf[pos] = '"';
        pos  ;
    }
        
    printf("Output: %sn", buf);
}

int main() {
    escape_csv("Test");
    escape_csv("Te"st");
    escape_csv("Te,st");
}
 

Это каким-то образом работает, но не совсем. Когда я запускаю его, он показывает:

 Input: Test
Output: Test
Input: Te"st
Output: "Te""st"�}(
Input: Te,st
Output: "Te,st
 

По какой-то причине во втором примере он показывает странные символы, а в последнем отсутствует заключительная цитата.

Что я здесь делаю не так? Есть ли другой способ улучшить это, просто получить экранированную строку в конце функции?

Комментарии:

1. Вам не хватает нулевого терминатора.

2. char buf[strlen(src) * 2]; слишком маленький (для наихудшего случая)

Ответ №1:

Строки в C заканчиваются нулем, '' . buf у него его нет, поэтому при его печати он будет продолжать считывать мусор, пока не увидит нулевой байт.

Добавьте a buf[pos] = ''; в конце алгоритма.

Комментарии:

1. Это делает трюк, спасибо. Я предположил, что он будет инициализирован как все нули. Должен ли я делать что-то, связанное с выделением или освобождением памяти в моей функции, если это часть более крупной программы?

2. @user13907 C не инициализирует память для вас, поэтому вы получаете любой мусор, который там был, если вы не выполните инициализацию. char buf[100] = {0} будет инициализировать каждый элемент равным 0, но вы не можете сделать это с массивом переменного размера. memset(buf, '', bufsize); сделал бы это, но это больше работы, чем вам нужно. Если вы хотите вернуть buf , вам нужно выделить его динамически malloc (или calloc обнулить память), чтобы он не освобождался автоматически при выходе из функции. Затем вызывающий абонент освободит память.