Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Баг fscanf()  (Прочитано 7700 раз)
0 Пользователей и 1 Гость смотрят эту тему.
acc15
Гость
« : 19-12-2005 01:09 » 

Проблемма в следующем....

Цитата
Return Value
Each of these functions returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. If an error occurs, or if the end of the file stream is reached before the first conversion, the return value is EOF for fscanf and fwscanf.

Если ни одного поля не было заполнено и не возникло ошибки в потоке то fscanf должна вернуть 0 и сдвинуть указатель файла на новую строку. Но указатель файла не сдвигается, мало того он после этого случая не сдвигается вообще дальнейшими fscanfами. соотвественно EOF'a не будет никогда. В мсдн про данную вещь умалкивают...

Вот как проверял
Содержимое файла 1.txt
123
4
5
f
5
7

когда fscanf доходит до строки "f", то всё, дальше указатель файла двигать он отказывается... можно конечно для этого использовать fgets - вообще глупо, создавать строковый буфер, только для того чтобы сдвинуть указатель файла... данные fscanf ведь прочитал, поэтому и указатель сдвинуть должен, а не хочет...

Пишу вот так
Код:
int res;
while ((res=fscanf(f1,"%d",&a))!=EOF)
{
if (res>0)
s+=a;
}
« Последнее редактирование: 15-12-2007 21:57 от Алексей1153++ » Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 19-12-2005 05:33 » 

всё правильно, он доходит до не десятичной цифры и не двигается. Сделай так :

если не конец файла, но прочитался ноль, пробуй читать "%x", а если и это не сдвинет - то "%s"
Записан

npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 19-12-2005 10:46 » 

Вот ссылка на определение fscanf в Posix http://www.opengroup.org/onlinepubs/009695399/functions/fscanf.html

Где написано, что fscanf должен сдвигать указатель позиции в потоке?

Я попробовал пример на Windows, Linux, FreeBSD -- везде одно и тоже, fscanf блокируется на строке без цифры.

Можно воспользоваться fgetc, чтобы добраться до конца строки

Код:
    while ((res=fscanf(f1,"%d",&a))!=EOF)
    {
        if (res>0)
        {
            printf("Read %d\n", a);
        }
        else
        {
            int chr;
            do
            {
                chr = fgetc(f1);
            } while ((chr != EOF) && (chr != '\n'));
        }
    }
« Последнее редактирование: 15-12-2007 21:58 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
acc15
Гость
« Ответ #3 : 19-12-2005 13:13 » 

Цитата
но прочитался ноль, пробуй читать "%x", а если и это не сдвинет - то "%s"
%x тоже самое что и %d, не катит... %s - создание левого буфера... лишние затраты памяти...


Цитата
           
Код:
int chr;
            do
            {
                chr = fgetc(f1);
            } while ((chr != EOF) && (chr != '\n'));
лишние затраты времени... тогда уж fgets НО тогда нужен буфер под строку...
Цитата
Где написано, что fscanf должен сдвигать указатель позиции в потоке?
Там также не написано что он сдвигает указатель при правильных значениях, а ведь сдвигает.

Да и вообще я не понимаю зачем перечитывать строку заново, когда она уже была считана fscanfом... просто надо сдвинуть указатель на то кол-во символов которое он считал, но не смог конвертировать...
« Последнее редактирование: 15-12-2007 21:59 от Алексей1153++ » Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 19-12-2005 13:17 » 

ну если всё так трагично Улыбаюсь , то спроецируй файл в память и парси сам Улыбаюсь

я бы сразу так и сделал...
Записан

acc15
Гость
« Ответ #5 : 19-12-2005 13:57 » 

а это одна глобальная затрата времени и памяти в одном флаконе  Улыбаюсь

про %x. ты не понял читать надо только числа 10-ного вида. вместо "f" может быть любая строка...
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 19-12-2005 15:30 » 

А какие у вас требования к производительности и затратам памяти?

Почему вы думаете, что fgets будет работать быстрее, чем цикл fgetc? 

Я считаю, что самый быстрый вариант -- это самому сканировать memory mapped file.  Быстрее, чем mmf, механизмов доступа к диску из пользовательского приложения нет.  fscanf устроен довольно сложно внутри, поэтому для того, чтобы избежать накладных расходов на разбор формата, проверки операций с символами, блокировками файла, существованием файла, можно реализовать собственный алгоритм преобразования строк в числа.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
acc15
Гость
« Ответ #7 : 19-12-2005 15:54 » 

Про время я имел ввиду время которое уйдёт на реализацию всего этого. К этому относится и fgets, т.е. я не говорю что fgets будет быстрее цикла fgetc, просто зачем реализовывать уже реализованное?? Ведь fgets это и есть ни что иное как цикл  _getc_lk(что и использует fgetc).
Ммф, зачем... память под файл будет лишней, т.к. в программе содержится только одно обращение к конкретному файлу, к тому же программа пишется для Виндовс, которая потом подлежит перекомпиляции под платформу ДОС, так что про ммф лучше забыть, только CRT и собственные функции.

Требований к производительности нет никаких вообще, просто хочется более грамотно сделать поставленную задачу.
« Последнее редактирование: 19-12-2005 16:03 от acc15 » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines