C: для петли, действующей действительно странно с scanf - PullRequest
2 голосов
/ 22 марта 2012

Итак, я получил следующий код:

int q, x, y;
char l;
for (q = 0; q<10; q+=1) {
    printf("%d\n", q);
    if (3 == scanf("%c %d %d", &l, &x, &y)) {
        printf("%d\n", q);
    }
}

Я ожидал бы, что это запустит "scanf" 10 раз. Каждый раз он будет печатать «q», прежде чем я что-то введу, и еще раз после. Таким образом, ожидаемый результат должен быть таким (поправьте меня, если я ошибаюсь):

0
> a 1 1
0
1
> b 2 2
1
2
> c 3 3
2
...and so on.

Но я на самом деле понимаю.

0
> a 1 1
1
1
2
> a 2 2
3
3
4
> a 3 3
5
5
6
> a 4 4
7
7
8
> a 5 5
9
9

Если я отключу функцию scanf, она будет считаться от 0 до 9, как и ожидалось. Что происходит с функцией scanf, которая заставляет цикл for работать так странно? У меня есть некоторый опыт работы с Java / Python, но я совершенно новичок в C.

Редактирование кода на основе ваших комментариев к этому (извинения за странное форматирование):

for (q = 0; q<10; q+=1) {
        printf("%d: ", q);
        if (3 == scanf("%c %d %d ", &c, &x, &y)) printf("%d\n", q);
        else { printf("WTF %d\n", q); }
    }

половина решает проблему. Это работает для всех итераций, КРОМЕ первого. Как так:

0: a 0 0
WTF 0
1: b 1 1
1
2: c 2 2
2

Что там происходит? Над первой строкой есть другой выводимый код из другой части программы. Может ли это быть причиной?

Ответы [ 4 ]

4 голосов
/ 22 марта 2012

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

После ввода a 1 1 <Enter> содержимое входного потока будет {'a', '1', '1', '\n'}.Первый scanf потребляет a, 1 и 1, оставляя завершающий \n во входном потоке.scanf возвращает 3, и вы печатаете значение q.

Во второй раз в цикле scanf подбирает остаток \n и присваивает его l, но, поскольку во входном потоке больше ничего нет, он не назначает x или y, поэтому он возвращает значение 1, и ваша ветвь не занята.Затем цикл начинается снова.

Самый простой способ обойти эту проблему - поставить начальный пробел в строке формата перед спецификатором преобразования %c:

if (3 == scanf(" %c %d %d", &l, &x, &y))
  printf("%d\n", q);

Этот начальный пробел в формате вызовет scanfпропустить любой начальный пробел во входном потоке, чтобы вы случайно не подняли завершающий символ новой строки из предыдущей записи.Конечно, если вы хотите, чтобы подобрал какие-либо пробельные символы, вам придется сделать что-то другое.

4 голосов
/ 22 марта 2012

вы не использовали "\ n", getchar () будет его использовать:

if (3 == scanf("%c %d %d", &l, &x, &y)) {
    getchar();
    printf("%d\n", q);
}
2 голосов
/ 22 марта 2012

Почему бы вам не попробовать добавить оператор else и printf в ваши vars для отладки этого? Кажется, что для каждого времени (3 == ..) верно, есть другое время, когда оно ложно. Scanf может быть запущен дважды для символа новой строки, когда вы нажимаете Enter ...

0 голосов
/ 22 марта 2012

Функция scanf возвращает разные значения вместо 3 (три входа). Я не знаю точную причину, но я чувствую из-за пробелов в scanf ("% c space% d", & c, & i); Функция возвращает разные значения.

...