Форум русскоязычного сообщества Ubuntu


Увидели сообщение с непонятной ссылкой, спам, непристойность или оскорбление?
Воспользуйтесь ссылкой «Сообщить модератору» рядом с сообщением!

Автор Тема: Небольшая проблема с программой на С  (Прочитано 2104 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн a1nt0pf

  • Новичок
  • *
  • Сообщений: 10
  • asus U24E
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #30 : 08 Апреля 2012, 02:05:57 »
Цитировать
Вопрос: в каком случае scanf возвращает EOF?
В том случае, когда есть конец файла (EOF - End Of File). Это работает для fscanf(), поскольку, нужно передать название нужного файла для чтения.

Оффлайн lukinfore

  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #31 : 08 Апреля 2012, 02:37:41 »
fscanf(), поскольку, нужно передать название нужного файла для чтения.
Код: (C) [Выделить]
(fscanf(stdin,"%d",&a)==1)^D в stdin это ли не EOF?

Оффлайн a1nt0pf

  • Новичок
  • *
  • Сообщений: 10
  • asus U24E
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #32 : 08 Апреля 2012, 12:02:16 »
По выводу - он самый.

Оффлайн lukinfore

  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #33 : 08 Апреля 2012, 20:30:26 »
Я, наверное, вновь выразился слишком лаконично.
При использовании
Код: (C) [Выделить]
(fscanf(stdin,"%d",&a)==1)
для условия цикла код работает так же, и EOF не возвращается. Так же.

Голословно.
. На самом деле возвращается-таки (и для fscanf, и для scanf), но только если до ^D не было ввода не-чисел. Все равно не понимаю, как это коррелируется с написанным в мануале
« Последнее редактирование: 08 Апреля 2012, 20:50:10 от lukinfore »

Оффлайн a1nt0pf

  • Новичок
  • *
  • Сообщений: 10
  • asus U24E
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #34 : 09 Апреля 2012, 01:28:01 »
Все там правильно написано. Scanf() выводит к-во считаных элементов из stdin. Если ты за раз прочитаешь 5 чисел, вне цикла, ф-я вернет число 5. Соответственно - в цикле ты читаешь по одному числу каждый раз, scanf() возвращает 1(к-во прочитанных числе за итерацию), следовательно выполняется условие цикла. Потом ты нажимаешь ^D в цикл передается EOF(т.е. -1) - условие цикла не выполняется, вытекает, что цикл заканчивает свою работу. А когда ты передаешь в scanf() символы это заведомо не подходит под шаблон чтения и ф-я заканчивает работу без EOF, а выводит 0. Если изменить условие ф-ции на !=EOF или != -1 будет подругому работать программа. Надеюсь я ответил на твой вопрос!
« Последнее редактирование: 09 Апреля 2012, 01:49:41 от a1nt0pf »

Оффлайн lukinfore

  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #35 : 10 Апреля 2012, 01:35:58 »
Выяснилось:
Код: (text) [Выделить]
lukinfore@:~/c_tests$gdb a.out
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/lukinfore/c_tests/a.out...done.
(gdb) list
1 #include <stdio.h>
2 int main(){
3 int r,a,max=0;
4 printf("Введите последовательность десятичных чисел\n");
5 while ((r=scanf("%d",&a))!=EOF)
6 if (a>max)
7 max=a;
8 printf("Максимальное число - %d\n",max);
9 }
(gdb) break 6
Breakpoint 1 at 0x8048483: file scandig.c, line 6.
(gdb) run
Starting program: /home/lukinfore/c_tests/a.out
Введите последовательность десятичных чисел
5

Breakpoint 1, main () at scandig.c:6
6 if (a>max)
(gdb) continue
Continuing.
2

Breakpoint 1, main () at scandig.c:6
6 if (a>max)
(gdb) continue
Continuing.
word

Breakpoint 1, main () at scandig.c:6
6 if (a>max)
(gdb) print a
$1 = 2
(gdb) print r
$2 = 0
(gdb) print max
$3 = 5
(gdb) continue
Continuing.

Breakpoint 1, main () at scandig.c:6
6 if (a>max)
(gdb) print a
$4 = 2
(gdb) print r
$5 = 0
(gdb) print max
$6 = 5
(gdb) continue
Continuing.

Breakpoint 1, main () at scandig.c:6
6 if (a>max)
(gdb) continue
Continuing.

Breakpoint 1, main () at scandig.c:6
6 if (a>max)
(gdb) print r
$7 = 0
(gdb)
и т.д. Для протокола - никакого ввода с клавиатуры между сontinue и брейкпойнтом не происходит. Т.е., не получив совпадения с %d scanf 1. возвращает 0 и срабатывает тело цикла 2.считывает что-то откуда-то, игнорируя stdin 3. goto 1 . Со стороны пользователя все выглядит нормально, ввод работает, но ^D программу не завершает, и съедается свободное время цпу. Вот эта, кхм, недокументированная особеннность и смущала. Или все же документированная, а я снова чего-то недопонял?

Оффлайн lukinfore

  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: Небольшая проблема с программой на С
« Ответ #36 : 23 Апреля 2012, 01:35:37 »
Вроде разобрался: scanf неформатный ввод оставляет в stdin на следующее чтение, поэтому цикл и замыкается. И ведь не скапитанил никто (
Но - как его правильно сбросить? Думал fflush-ем - не срабатывает
Код: (C) [Выделить]
#include <stdio.h>
int mflush(){
while(!isspace(getchar()));return 1;
}
int main(){
int r,a=0,max=0;
printf("Введите последовательность десятичных чисел\n");
while ((r=
scanf("%d",&a))>0 ||
((!r) &&
mflush() /*!fflush(stdin)*/ &&
puts("Не десятичное число. Завершить ввод?(y)") &&
getchar()!='y')) {
if (a>max)
max=a;
}
printf("Максимальное число - %d\n",max);
}
И можно ли цикл в уловие вставить, не заворачивая в функцию?

 

Страница сгенерирована за 0.038 секунд. Запросов: 26.