Чтение файла в C, случайная ошибка - PullRequest
1 голос
/ 05 апреля 2011

Спасибо всем за ваш вклад и советы!

Дополнительно:

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

End Add

Hello,

У меня естьочень необычная проблема [пожалуйста, прочтите это полностью: это важно] (компилятор Code :: Blocks, Windows Vista Home) [нет тиражируемого кода] с функциями чтения файлов C (fread, fgetc).Теперь, как правило, функции чтения файлов корректно загружают данные в самораспределяющуюся и самораспределяющуюся строку (и это не проблема строки), но это то место, где оно становится странным (и где квантовая физика подходит):

Оператор перехвата ошибок сообщает, что EOF произошел слишком рано (IE находится в разделе комментариев в начале загружаемого текстового файла).Распечатка строки [после ее загрузки] сообщает, что она действительно слишком короткая (24 символа) (но у нее достаточно места для ее размещения [~ 400] и нет проблем с выделением).Итератор цикла fgetc сообщает, что он завершается всего за 24 (файл имеет длину около 300 символов) с EOF: Это то место, где он идет странно :

Временная проверка Read -> _ base сообщаетцелые (~ 300) символы загружены - без EOF в 24. Озадачен, [учитывая, что это цикл fgetc] Я добавил printf для отображения каждого символа [как% d, чтобы я мог определить -1 EOF] на каждом шаге, поэтому ямог видеть, что он делает, и изменил его так, чтобы это был один символ.Он зацикливается, достигая отметки ~ 300 вместо 24 - но мгновенно зависает случайно.НО, когда я удалил printf, он снова завершился на 24 и был пойман ошибочным оператором.

Сводка : Итак, в основном: у меня есть ошибка, на которую влияет 'Эффект наблюдателя вне квантовой физики: когда я пытаюсь наблюдать символы, которые я получаю от fgetc через printf, проблема (раннее завершение EOF в 24) исчезает, но когда я прекращаю его просматривать, оператор catch-catch сообщает о досрочном завершении.1025 *

Более странно то, что это происходит не впервые.У Fread была похожая проблема, и я не смог выяснить почему, и заменил ее на цикл fgetc.

[Код не может быть предоставлен, так как база кода имеет размер 5 заголовков].

Фрагмент:

int X = 0; 
int C = 0; 
int I = 0;

while(Copy.Array[X] != EOF)
{
    //Copy.Array[X] = fgetc(Read);
    C = fgetc(Read);
    Copy.Array[X] = C;
    printf("%d %c\n",C,C); //Remove/add this as necessary
    if(C == EOF){break;}
    X++;
}

Примечание: разбив его на простейший формат, ошибка не воспроизводится.

Ответы [ 5 ]

5 голосов
/ 05 апреля 2011

Это самая старая ошибка в книге, вроде.

Нельзя использовать переменную типа char для чтения символов (!), Поскольку константа EOF не подходит.

Вам нужно:

int C;

Кроме того, условие while выглядит страшно, вы увеличиваете X в цикле, затем проверяете (новую) позицию, это правильно инициализировано? Вы не показываете, как настроен Copy.Array перед началом цикла.

Я бы предложил вообще удалить это, это очень странный код.

На самом деле, я вообще не понимаю, почему вы зацикливаете чтение отдельных символов, почему бы просто не использовать fread() для чтения столько, сколько вам нужно?

1 голос
/ 05 апреля 2011

Во-первых, ответ отмотки - верный момент, хотя я не уверен, объясняет ли он проблемы, которые вы видите.

Во-вторых,

printf("%d %c\n",C,C); //Remove/add this as necessary

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


Я думаю, что проблема в следующем:

Как вы размещаете Copy.Array?Вы убедитесь, что все его элементы обнулены, прежде чем начать?Если вы используете malloc (malloc просто оставляет тот мусор, который был в памяти, который он возвращает) и элемент просто содержит 0xFF, ваш цикл преждевременно завершится, потому что ваше условие while проверяет Copy.Array [X] перед тем, как поместить символв этом месте.

Это один из немногих случаев, когда я позволяю себе помещать назначение в условие, потому что шаблон

int c;
while ((c = fgetc(fileStream)) != EOF)
{
    doSomethingWithC(c);
}

действительно распространен


Редактировать

Просто прочитайте ваш комментарий "Дополнительно".Я думаю, что весьма вероятно, что вы превышаете выходной буфер.Я думаю, вы должны изменить свой код на что-то вроде:

    int X = 0; int C = 0; int I = 0;
    while(X < arraySize && (C = fgetc(Read)) != EOF)
    {
        Copy.Array[X] = C;
        printf("%d %c\n", (int)C, (int)C);
        X++;
    }
    printf("\n");

Обратите внимание, что я предполагаю, что у вас есть переменная с именем arraySize, которая установлена ​​на количество символов, которые вы можете записать в массив без перегрузкиЭто.Также обратите внимание, я не записываю EOF в ваш массив.

0 голосов
/ 05 апреля 2011

Хотя это не то, что я бы назвал «полным» ответом (поскольку ошибка остается), это действительно решает элемент «эффекта наблюдателя»: я обнаружил, что printf почему-то каким-то образом «исправлял» коди использование std :: cout, по-видимому (ну, я не могу сказать «исправить» проблему), предотвращает возникновение эффекта наблюдателя.То есть используйте std :: cout вместо printf (так как printf является источником эффекта наблюдателя).

Мне кажется, что printf что-то делает в памяти на более низком уровне, что кажется частично правильнымчто действительно кажется ошибкой выделения памяти.

0 голосов
/ 05 апреля 2011

Не уверен, что это ваша ошибка, но этот код:

C = fgetc(Read);
Copy.Array[X] = C;
if(C == EOF){break;}

Означает, что вы добавляете значение EOF в свой массив - я уверен, что вы не хотите этого делать,тем более что ваш массив предположительно равен char, а EOF равен int, поэтому вы на самом деле получите другое значение (которое может испортить последующие циклы и т. д.).

Вместо этого я предлагаювы меняете порядок так, что C помещается в массив только тогда, когда вы знаете, что это не EOF:

C = fgetc(Read);
if(C == EOF){break;}
Copy.Array[X] = C;
0 голосов
/ 05 апреля 2011

У вас, вероятно, происходит какое-то повреждение кучи.Не видя код, невозможно сказать.

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