у с умлаут в файле - PullRequest
       68

у с умлаут в файле

1 голос
/ 16 мая 2019

Я работаю над примером проблемы, где я должен перевернуть текст в текстовом файле, используя fseek () и ftell (). Я был успешным, но печатая тот же вывод в файл, у меня были странные результаты. Введенный мною текстовый файл был следующим:

redivider
* гоночный автомобиль 1004 * каяк
гражданский
уровень
см
Это все палиндромы

Результат в командной строке прекрасно работает. Однако в текстовом файле, который я создаю, я получаю следующее:

msemordnilap lla эра esehTT
referr
levell
civicc
kayakk
racecarr
переделить

Мне известно из ответа на этот вопрос говорит, что это соответствует версии EOF в текстовом файле на C. Я просто запутался, почему выходные данные командной строки и текстового файла различаются.

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

/**********************************
This program is designed to read in a text file and then reverse the order 
of the text.
The reversed text then gets output to a new file.
The new file is then opened and read.
**********************************/

int main()
{
    //Open our files and check for NULL
    FILE *fp = NULL;
    fp = fopen("mainText.txt","r");
    if (!fp)
        return -1;

    FILE *fnew = NULL;
    fnew = fopen("reversedText.txt","w+");
    if (!fnew)
        return -2;

    //Go to the end of the file so we can reverse it
    int i = 1;
    fseek(fp, 0, SEEK_END);
    int endNum = ftell(fp);
    while(i < endNum+1)
    {
        fseek(fp,-i,SEEK_END);
        printf("%c",fgetc(fp));
        fputc(fgetc(fp),fnew);
        i++;
    }

    fclose(fp);
    fclose(fnew);
    fp = NULL;
    fnew = NULL;

    return 0;
}

Нет ошибок, я просто хочу идентичные выходы.

Ответы [ 2 ]

3 голосов
/ 16 мая 2019

Выводы отличаются, потому что ваш цикл читает два символа из fp за итерацию.

Например, в первой итерации i равно 1, поэтому fseek устанавливает текущую позицию файла fp непосредственно перед последним байтом:

...
These are all palindromes
                        ^

Затем printf("%c",fgetc(fp)); читает байт (s) и выводит его на консоль. Прочитав s, позиция файла теперь

...
These are all palindromes
                         ^

т.е. мы находимся в конце файла.

Затем fputc(fgetc(fp),fnew); пытается прочитать другой байт из fp. Это не удается, и fgetc возвращает EOF (отрицательное значение, обычно -1). Тем не менее, ваш код не подготовлен к этому и слепо рассматривает -1 как код символа. Преобразованный в байт -1 соответствует 255, который является символьным кодом для ÿ в кодировке ISO-8859-1. Этот байт записан в ваш файл.

В следующей итерации цикла мы возвращаемся к e:

...
These are all palindromes
                       ^

Снова цикл читает два символа: e записывается в консоль, а s записывается в файл.

Это продолжается в обратном направлении, пока мы не достигнем начала входного файла:

redivider
^

И снова цикл читает два символа: r записывается в консоль, а e записывается в файл.

Это завершает цикл. Конечным результатом является то, что ваш выходной файл содержит один символ, который не существует (из попытки чтения после конца входного файла) и никогда не видит первый символ.

Исправление заключается в том, чтобы вызывать fgetc только один раз за цикл:

while(i < endNum+1)
{
    fseek(fp,-i,SEEK_END);
    int c = fgetc(fp);
    if (c == EOF) {
        perror("error reading from mainText.txt");
        exit(EXIT_FAILURE);
    }
    printf("%c", c);
    fputc(c, fnew);
    i++;
}
0 голосов
/ 16 мая 2019

В дополнение к @ melpomene исправлению об использовании только 1 fgetc() на петли, существуют другие проблемы.

fseek(questionable_offset)

fopen("mainText.txt","r"); открывает файл в режиме текст , а не в режиме двоичный .Таким образом, использование fseek(various_values) в качестве допустимого смещения в файле может привести к проблемам.Обычно не проблема в * nix системах.

У меня нет простой альтернативы.

ftell() тип возврата

ftell() returnlong.Используйте long вместо int i, endNum.(Не касается небольших файлов)

Проверить возвращаемые значения

ftell() и fseek() может произойти сбой.Проверка на наличие ошибок.

...