Строка C печатается из файла с неопределенным поведением - PullRequest
0 голосов
/ 06 июля 2019

Я создал программу на языке c, которая анализирует файл исходного кода на языке быстрого набора для извлечения определенных данных, которые мне понадобятся для документирования на работе. извлеченные данные сохраняются в CSV-файл, который затем форматируется в лист Excel.

Все работает, кроме этой функции, которую я поставил ниже. В некоторых сценариях я хотел удалить все пробелы и табуляции из строки, считываемой из файла, чтобы я мог сохранить инструкцию в виде строки в атрибуте struct.

Программа не аварийно завершает работу, но когда я печатаю ff () новую строку с удаленными пробелами, выводятся некоторые другие символы.

Пример "cmd.exe", "PowerShell \ v1.0 \ Modules", "igh \ AppData \ LocaloYSφo¡"

Если я делаю Printf("%s\n", currentLine); Он печатает нормально

Когда я использую printf("%s\n", removeWhiteSpace(currentLine));, я получаю неопределенное поведение.

Вот функция

/******************************************************************
*   Takes a string as input, returns it without tabs or spaces
*   Used to put whole line into the additional commands
*   Attribute
******************************************************************/
static char* removeWhiteSpace(char* string)
{
    int i;
    int j;
    int len = strlen(string);
    char ch;
    char* result = malloc(sizeof(char)*len+1);

    memset(result, 0, sizeof(*result));

    j=0;
    for (i=0; i<len; i++)
    {
        ch = string[i];
        if ((ch != ' ') && (ch != '\t'))
            {
                result[j] = ch;
                j++;
            }
    }

    result[strlen(result)] = '\0';

    return result;
}

Кроме того, я использую fgets () для получения строки из файла, а размер буфера равен 1000.

Нежелательные символы не существуют в текстовом файле, по крайней мере, не видны в любом случае.

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

Кроме того, я использую IDE кодовых блоков с помощью компилятора GCC, у меня нет ошибок или предупреждений при компиляции.

1 Ответ

2 голосов
/ 06 июля 2019

memset(result, 0, sizeof(*result));

Это неправильно.*result это то, на что result указывает.result равно char *, поэтому оно указывает на char, а размер char равен 1. Таким образом, этот оператор устанавливает один char в ноль.Он не устанавливает весь блок выделенной памяти на ноль.

Как мы увидим, он не нужен, поэтому просто удалите этот оператор.

result[strlen(result)] = '\0';

Это утверждение бесполезно.strlen работает путем нахождения первого нулевого (нулевого) символа в массиве.Так что strlen(result) сообщит, где находится первый нулевой символ.Тогда result[strlen(result)] = '\0'; установит этот символ на ноль.Но это уже ноль.Так что это утверждение никогда не сможет ничего сделать.Более того, однако, он не работает, потому что memset выше не удалось установить память в ноль, поэтому в выделенной памяти может не быть нулевого символа для поиска.В этом случае поведение не определяется стандартом C.

Однако нет необходимости использовать strlen, чтобы найти конец строки.Мы знаем, где должен быть конец строки.Объект j считал символы, записанные в result.Поэтому просто удалите эту строку и используйте:

result[j] = '\0';

Когда я использую printf("%s\n", removeWhiteSpace(currentLine));, я получаю неопределенное поведение.

Это не имеет никакого смысла.«Неопределенное поведение» - это не вещь.Это нехватка вещей.Сказать, что что-то имеет «неопределенное поведение», означает, что стандарт С не определяет, что такое поведение.Программа, которая имеет неопределенное поведение, может ничего не печатать, она может печатать желаемый результат, она может печатать нежелательный результат, она может печатать символы мусора, она может аварийно завершить работу и может зависать.

Сказать, что программа произвела неопределенноеповедение не говорит никому, что случилось.Вместо этого вы должны были написать конкретное описание поведения программы, например: «Программа напечатала ожидаемый текст, за которым следовали неожиданные символы». Копирование и вставка точного ввода и точного вывода было бы хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...