Nano Hash - криптовалюты, майнинг, программирование

Чтение файла в структуру иногда останавливается без причины

У меня есть следующий код:

int main() {    
    FILE *fp = fopen("inventory.txt", "r");
    if (fp == NULL) {
        printf("File Error");
        return 1;
    }

    while (1) {
        char *componentType = malloc(200);
        char *stockCode = malloc(20);
        int numberOfItems = 0;
        int price = 0;
        char *additionalInformation = malloc(20);

        int fileRead = fscanf(fp, "%[^,], %[^,], %i, %i, %[^,\r\n]", componentType, stockCode, &numberOfItems, &price,
                              additionalInformation);

        if (fileRead == EOF) {
            printf("End of file!\n");
            break;
        }

        printf("%s Read Record!\n", stockCode);

        free(componentType);
        free(stockCode); 
        free(additionalInformation);
    }

    printf("DONE!");
    fclose(fp);

}

Файл выглядит так:

resistor, RES_1R0, 41, 1, 1R0
resistor, RES_10R, 467, 1, 10R
resistor, RES_100R, 334, 1, 100R
resistor, RES_1K0, 500, 1, 1K0
resistor, RES_10K, 169, 1, 10K
resistor, RES_100K, 724, 1, 100K
resistor, RES_1M0, 478, 1, 1M0
diode, BY126, 118, 12
diode, BY127, 45, 12
transistor, AC125, 13, 35, PNP
transistor, AC126, 40, 37, PNP
....

Однако, когда я запускаю код, он иногда завершается следующим образом:

RES_1R0 Read Record!
RES_10R Read Record!
...
CF12 Read Record!
CF13 Read Record!
Done!

Но иногда он останавливается без причины, как это:

RES_1R0 Read Record!
RES_10R Read Record!
...
D12 Read Record!
D13 Read

Каждый раз он по-прежнему возвращает 0.

В чем проблема?

28.03.2016

  • Есть ли в вашем реальном коде утечка памяти, как в показанном примере? Или это просто для наглядности? И сколько строк содержит ваш входной файл, чтобы выяснить, сколько памяти вы фактически выделяете. Для начала проверьте все возвращаемые значения malloc, чтобы убедиться, что какое-либо распределение не работает. 28.03.2016
  • Да, он течет, как в примере выше. Однако я использовал ..., так как я, конечно, не мог показать их все. 299 записей! 28.03.2016
  • попробуйте %[^,\r\n] --› %[^,\r\n]%*c 28.03.2016
  • Также я проверил, возвращает ли какая-либо из строк NULL, и это не так! 28.03.2016
  • @BLUEPIXY что это делает? и это тоже не сработало. то же самое! 28.03.2016
  • Если ,\r\n присутствует, остается повлиять на ввод следующей строки. 28.03.2016
  • Попробуйте вставить строки free(componentType); free(stockCode); free(additionalInformation); вокруг строки 20 и посмотрите, сможете ли вы воспроизвести эту проблему. Я протестировал его с 10000 записей, и у меня не было таких проблем. 28.03.2016
  • Я предлагаю вам прочитать строки ввода, используя getline() или fgets(), а затем проанализировать полученную строку, используя sscanf() , strtok() или что-то еще. 28.03.2016
  • @DominikGebhart Пробовал (обновление ответа). Также попробуйте это с моим вводом: onedrive.live. com/ несколько раз! 28.03.2016
  • Я использовал ваш ввод, скопировал его, чтобы иметь 7600 строк, работает нормально, я думаю, что это просто Редактировать: визуальная проблема с вашей оболочкой, можете ли вы удалить печать добавления записи и просто сохранить Готово и проверьте, есть ли у вас случай, когда он не появляется? 28.03.2016
  • Либо tee вывод в файл, и смотреть в файл, когда терминал снова выдаст эту ошибку. то есть ./a.out | tee output.txt 28.03.2016
  • Обратите внимание, что после считывания диодной строки вы получаете 4 из fscanf() и в дополнительной информации нет ничего полезного (ничего не было изменено). Ввод останавливается с новой строкой, оставшейся в буфере (поскольку она не соответствует запятой после второго %i). Ваше следующее чтение включает новую строку в типе компонента следующей записи, потому что вы не включаете пробел в начале строки формата (и наборы сканирования %[…] не пропускают начальный пробел). Я предлагаю добавить пробел в начале, чтобы пропустить (необязательно) пробел. Однако это не приводит к периодическим сбоям в вашей программе. 28.03.2016
  • Вы должны стремиться сделать проблему воспроизводимой. Одна вещь, которая может помочь, - это печать прочитанных данных, а не просто «запись чтения». Блокируется каждый раз в одном и том же месте? Так как вы просто сканируете данные, не выделяйте поля динамически — не заблокируется ли программа? Вы проверили файл, чтобы убедиться, что поля не слишком длинные? Вытаптывание за пределы — это плохо. Пробовали ли вы использовать fgets() или POSIX getline(), чтобы прочитать строку… 28.03.2016
  • …а затем используйте sscanf() для его обработки. Пробовали ли вы добавить защиту в наборы сканирования для слишком длинных полей: %199[^,], %19[^,], %19[^,\r\n]? Это предотвратит повреждение памяти из-за слишком длинных полей. Вы проверили, что строки во входных данных постоянно имеют 3 или 4 запятых (tr -cd ',\n' < data.file | uniq -c может работать для этого)? Ошибка проверки каждой функции. 28.03.2016
  • @JonathanLeffler Он может блокироваться на разных записях. (и вы правы, мой ответ cmake был просто случайным) 28.03.2016
  • Почему он только иногда блокируется на одном и том же входе? Не имеет смысла для меня. Я просто запускал ./a.out; while [ $? == 0 ]; do ./a.out ; done; в течение 10 минут без каких-либо проблем. Если вы поймаете еще одно зависание, откройте другой терминал и проверьте, работает ли процесс, и echo $? (в той же оболочке, где вы запускали программу), чтобы увидеть код возврата, который он сделал. Я предполагаю, что он не работает, и вы получили 0, так как это может быть просто визуальная проблема с оболочкой. 28.03.2016
  • См. также Как использовать scanf() на нескольких строки для строки в C — тот же OP, тот же набор данных, более общая проблема (не прямой дубликат). 28.03.2016
  • На самом деле это был совсем другой вопрос. Тот же набор данных да, но вопрос заключался в том, как использовать scanf для чтения строк в строке. НЕ почему мой код просто останавливается без причины! Тем не менее я удалил этот вопрос, так как мне больше не нужен этот ответ. 28.03.2016
  • Понятно, что проблема в CLion. НЕ мой код C! 28.03.2016
  • Когда вы говорите, что проблема в CLion, а не в моем C-коде, что это значит? Я не знаю CLion, но… Когда вы компилируете и запускаете свою программу в командной строке, она работает без остановки, говорите? Что произойдет, если вы запустите тот же двоичный файл без его пересборки в CLion? Запускает ли CLion программу во вновь созданном окне терминала — или в окне, созданном им самим и находящимся под его управлением? Пробовали ли вы добавить один из приемов в стиле Windows — добавить getchar() в конце main() для ожидания ввода? Вы добавили новую строку в printf("DONE!\n"); — в противном случае вывод может появиться несвоевременно. 28.03.2016
  • Я также отмечаю, что ваш образец вывода говорит Read Record!, но формат говорит printf("%s Read Record!\n", stockCode);. При разумной номинальной стоимости вы никогда не читаете биржевой код (и вы пропустили начальный пробел в выводе, который вы цитируете). Вы уверены, что используете правильный код? Рассмотрите возможность добавления счетчика в программу и печати значения счетчика в файле read record line. И обязательно проверяйте внимательнее возвращаемое значение из fscanf() — не все хорошо, когда он возвращает значение 0, 1, 2 или 3, хотя вы можете жить и с 4, и с 5 (но инициализируйте additionalInfo). 28.03.2016
  • Я обновил код. Забыл также обновить вывод. Также я пришлю скриншот ide завтра. 28.03.2016

Ответы:


1

Поскольку этот вопрос сильно изменился с тех пор, как я впервые его задал (т.е. сначала я подумал, что это проблема с памятью/структурой, затем это стало проблемой с компилятором, затем я, наконец, понял, что это проблема с IDE), поэтому я решил создать вообще новый вопрос: вывод для CLion IDE иногда прерывается при выполнении программы.

Ответ на этот конкретный вопрос заключается в том, что это проблема с CLion IDE. Чтобы решить эту проблему, скомпилируйте и запустите код с помощью терминала, и вывод будет работать нормально.

Спасибо @Dominik Gebhar и @Jonathan Leffler за помощь!!!

28.03.2016

2

fscanf() возвращает количество прочитанных символов или ноль в конце файла, а fgetc(fp) возвращает символ или конец файла при достижении конца файла.

Вы смешиваете два метода обнаружения eof.

28.03.2016
  • scanf() возвращает ноль в конце файла. Действительно? справочная страница fscanf говорит: значение EOF возвращается, если достигнут конец ввода . 28.03.2016
  • fscanf() возвращает количество успешно обработанных спецификаций преобразования, число которых может быть равно 0 или больше; или он возвращает EOF, если он расположен в EOF (в файле больше нет данных) или если есть ошибка ввода-вывода. Он не возвращает количество прочитанных символов. Если строка формата имеет 6 спецификаций преобразования (%s или подобные) без подавления присваивания (не считая %*s), то ищите 6, которые будут возвращены; все, что меньше, указывает на проблему. 28.03.2016
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..