Выделить память на основе размера файла имеет неправильный номер? - PullRequest
0 голосов
/ 14 апреля 2019

Я хочу сохранить содержимое моего файла в виде динамического строкового указателя.Вот мой код:

    char *strPtr = NULL;
    char tmpChar = "";
    inputFile = fopen(input_file, "r");

    fseek(inputFile, 0, SEEK_END);   // seek to end of file
    fileSize = ftell(inputFile);    // get current file pointer
    rewind(inputFile);
    strPtr = (char*) realloc(strPtr, fileSize * sizeof(char));
    int counter = 0;

    while ((tmpChar = fgetc(inputFile)) != EOF)
    {
        strPtr[counter] = tmpChar;
        counter++;
        if (counter == fileSize)
            printf("OK!");
    }
    printf("Filesize: %d, Counter: %d", fileSize,counter);

Теперь к моей проблеме ... С последним printf я получаю 2 разных значения, например: Размер файла 127 и Счетчик 118. Дополнительно в конце моей переменной strPtr естьнеправильный ввод, как "ÍÍÍÍÍÍÍÍÍýýýýüe".

Notepad ++ также говорит в конце файла, что я нахожусь в позиции 127, так в чем же проблема с 118?

1 Ответ

2 голосов
/ 14 апреля 2019

Если вы откроете файл в текстовом режиме (по умолчанию) в Windows, функции файла CRT преобразуют любые значения \r\n в \n.В результате каждая читаемая строка будет на 1 байт короче оригинала с \ r \ n.

. Чтобы предотвратить такие преобразования, используйте двоичный режим, добавив модификатор режима «b», например:"rb".

inputFile = fopen("example.txt", "rb")

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=vs-2019

В текстовом режиме комбинации перевода строки и перевода строки переводятся в однострочный перевод при вводе, а символы перевода строки переводятся в возврат каретки.-linefeed комбинации на выходе.

while ((tmpChar = fgetc(inputFile)) != EOF)
{
    strPtr[counter] = tmpChar;
    counter++;
    if (counter == fileSize)
        printf("OK!");
}

Кроме того, этот цикл, предполагая, что файл не содержит любые значения NULL, не будет нулевым завершить вашу строку,Если позднее вы будете использовать strPtr таким образом, чтобы он ожидался (например, printf, strcmp и т. Д.), Он прочитает за допустимый диапазон.

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

realloc(strPtr, (fileSize + 1) * sizeof(char));
while (...
strPtr[counter] = '\0'; // Add null terminator at end.

Для обработки файлов / строк, которые могут содержать нули, вы не можете использовать строки с нулевым окончанием вообще (например, используйте memcmp сразмер вместо strcmp).

...