Значение массива Char будет напечатано как пустое, если значение не будет напечатано при назначении - C - PullRequest
0 голосов
/ 18 сентября 2018

Я работаю с двумя функциями в моей программе на c, и у меня возникают проблемы с их взаимодействием.Моя первая функция перебирает файл csv и использует strtok () для разделения токенов на основе разделителя ','.Каждый токен сохраняется в массиве символов размера 3, и если конкретный токен не соответствует целевому токену, следующая строка ввода считывается, токенизируется, и массив символов перезаписывается новыми входными токенами.

Здесь используется глобальная переменная:

char * stateCityZip[3];

Вот код для первой функции:

int zipToCity(char * zip)
{
char line[1024];
char * tok = malloc(20 * sizeof(char));
FILE * file = fopen("cityzip.csv", "r");
while (fgets(line, sizeof(line), file))
{
    //State
    tok = strtok(line, ",");
    stateCityZip[0] = tok;
    //City
    tok = strtok(NULL, ",");
    stateCityZip[1] = tok;
    //Zip
    tok = strtok(NULL, ",");
    stateCityZip[2] = tok;

    if (strcmp(stateCityZip[2], newZip) == 0) {
        //printf("Found %s, %s\n", stateCityZip[0], stateCityZip[1]);
        strlen(stateCityZip[1]));
        return 1;
    }
}
return 0;
}

Моя вторая функция просто пытается напечатать значения stateCityZip.Однако, когда я печатаю эти значения, они отображаются как пустые.Единственный способ исправить это, я нашел, это раскомментировать строку

//printf("Found %s, %s\n", stateCityZip[0], stateCityZip[1]);

.

Вот код для моей второй функции:

int main() {
    printf("City: [%s]", stateCityZip[1]);
    printf("State: [%s]", stateCityZip[0]);

    return 0;
}

Вывод:

City: []
State: []

1 Ответ

0 голосов
/ 18 сентября 2018

strtok возвращает указатели на подстроки своего ввода.Таким образом, все ваши tok значения являются указателями на части line, который имеет автоматическую продолжительность хранения, и поэтому указатели в stateCityZip все становятся недействительными после возврата zipToCity.

(На самом деле, если естьЕсли в файле находится более одной строки, все указатели tok становятся недействительными, как только вы переходите к следующей строке, поскольку теперь они указывают на произвольные подстроки новой строки в буфере.)

ВместоВы должны использовать strdup, чтобы выделить копию токена в виде новой строки и сохранить указатель, возвращенный из strdup в stateCityZip.

Важное примечание: строки, выделенные strdupнужно освободить по free.Если stateCityZip является глобальным, то вы можете избежать освобождения их (последняя память будет освобождена при выходе из вашего процесса).Но если zipToCity когда-либо будет вызван снова, он перезапишет указатели в stateCityZip и пропустит соответствующие строки.Так что, вероятно, было бы безопаснее сначала free() любых строк в stateCityZip (если они равны NULL, тогда все в порядке, поскольку free(NULL) не используется) перед присвоением новых значений.

Вкл.тема выделения памяти: ваш пример кода имеет malloc вызов для tok, который является полностью лишним и который гарантированно будет утечкой, поскольку вы перезаписываете указатель, возвращенный из malloc, без free его.

И, на предмет хорошей практики кодирования: fopen может потерпеть неудачу.Вам нужно проверить, что возвращаемое FILE * не равно NULL.(Если он равен NULL, errno скажет вам, почему.) И вам также нужно fclose FILE *, чего вы, похоже, тоже не делаете.

В целом: ни один изэтот код, кажется, выполняет какую-либо проверку ошибок вообще.Каждый раз, когда вы вызываете любую стандартную библиотечную функцию (или вообще любую функцию, если на то пошло!), Вам нужно подумать о том, как эта функция может не выполнить то, что должна, как вы сможетескажи (обычно поведение при сбое хорошо документировано, поэтому обязательно прочитайте документы) и что вы хотите, чтобы ваша программа делала в случае сбоя.Что должно произойти, если файл не существует или не может быть прочитан?Если он содержит строку, которая не разделена запятыми или не содержит ожидаемого количества полей?Что должно произойти, если вам не хватает памяти на полпути при обработке файла, или если strdup не может скопировать строку, потому что у вас недостаточно динамической памяти?Если вы не думаете об этих проблемах или забыли заняться ими, вы можете сойти с рук в «счастливом случае», когда все работает, но рано или поздно он вернется и укусит вас - часто в худшем случаевозможное время.

...