2016-12-15 13 views
3

Я беру учебный курс на «C» и сталкиваюсь с проблемой. Трудно объяснить, поэтому я отправлю код. Это тренировочный синтаксис, поэтому не спрашивайте меня, почему так оно и было. Когда оба этих блока сегмента запускаются в main(), второй блок не ведет себя так, как если бы он существовал один в main(). Я попробовал несколько IDE, думая, что это может быть ошибка.Не могу понять, почему getchar() собирает новую строку для первого появления в C

/* First Segment Block */ 
int c; 
printf("Type a letter: "); 
c = getchar(); 
printf("You typed '%c'\n",c); 

/* OR - outputs the same, to demonstrate putchar */ 

printf("You typed '"); 
putchar(c); 
printf("'\n\n"); 

/* Second Segment Block */ 
int a,b,d; 
printf("Type two letters: "); 
a = getchar(); 
b = getchar(); 
d = getchar(); 
printf("You typed '"); 
putchar(a); 
printf("' and '"); 
putchar(b); 
printf("' and '"); 
putchar(d); 
printf("'\n"); 

Во втором сегменте блока я добавил третью переменную, чтобы проверить свою теорию. Когда вы вводите запрошенные 2 буквы, первый getchar() берет новую строку, а второй getchar() берет первую букву. Третий getchar() берет второе письмо. Если вы закомментируете весь блок первого сегмента, то он ведет себя правильно, подбирая первую букву первой getchar() и вторую букву вторым getchar(), отображая результат как ожидалось.

Вот результат, когда оба работают вместе.

Type a letter: k 
You typed (k) 
You typed 'k' 

Type two letters: lk 
You typed ' 
' and 'l' and 'k' 

RUN SUCCESSFUL (total time: 9s) 

Когда они запускаются индивидуально, выход ниже.

Первый вывод сегмента.

Type a letter: k 
You typed (k) 
You typed 'k' 

RUN SUCCESSFUL (total time: 5s) 

Второй сегментный выход.

Type two letters: rf 
You typed 'r' and 'f' and ' 
' 

RUN SUCCESSFUL (total time: 5s) 

3-GetChar() является новой строки, и, как ожидается.

Может ли кто-нибудь объяснить, почему, когда оба сегмента выполняются в одном и том же main(), поведение отличается от того, когда вы выполняете раздельную работу?

Спасибо заранее, Daniel N. (C начинающий язык)

+1

Вы нажали return после ответа на первое приглашение? Эта новая строка считывается следующим 'getchar()'. – Barmar

+2

Когда вы набрали первую букву, вы также нажмете return, который отображается как новая строка. Второй 'getchar()' читает новую строку, а затем считываются две буквы (и во входной строке есть непрочитанная новая строка). Это ожидаемое поведение. Если бы вы набрали «abc» и вернулись, все будет вести себя так же, как вы ожидали ... кроме того, что лишние вызовы 'getchar() будут возвращаться, если вы не набрали ничего больше. –

+1

Newline ('' \ n'') является 'char' тоже .. – chux

ответ

3

На первой строке вы печатаете что-то вроде Введите, так что ваш входной поток содержит символы 'a', '\n'. Первый вызов getchar считывает a и оставляет строку новой строки во входном потоке.

В ответ на вторую строку, вы набираете бсВведите, так что ваш входной поток теперь содержит '\n', 'b', 'c', '\n'.

Возможно, вы можете выяснить, что происходит отсюда - следующий вызов getchar считывает символ новой строки из входного потока.

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

do 
{ 
    a = getchar(); 
} while (a == '\n'); // or while(isspace(a)), if you want to reject 
         // any whitespace character. 

Другой не использовать getchar; вместо этого, используйте scanf с спецификатором преобразования %c и пробел в строке формата:

scanf(" %c", &c); // you will need to change the types of your 
...     // variables from int to char for this. 
scanf(" %c", &a); 
scanf(" %c", &b); 
scanf(" %c", &c); 

Ведущее место в строке формата говорит scanf игнорировать любые ведущие пробелы, так что вы не подберут символ новой строки ,

+0

Обучение, которое я беру, создает новый файл для каждого сегмента, который он объясняет, я просто добавляю его в конец, пока переменные уникальны. Я думаю, что «С» нужно сказать, как обращаться с каждым персонажем, даже когда нажата физическая клавиша «Ввод», которая полностью невидима. – DNadler

+1

@DNadler: новые строки не невидимы; они похожи на любого другого. У них нет глифа, связанного с ними, но они влияют на отображение. –

0

И 'пространство' и '\ п (новая линия)' являются символы, а также. Итак, getchar() получает каждый вводимый вами символ. Например, если вы нажмете 'a (введите) b', он будет читать a = 'a', b = '\ n', d = 'b'.

0

Это происходит потому, что ваш терминал буферизирован в строке, поэтому он ждет, пока вы нажмете Enter перед передачей любых символов, которые вы набрали в своей программе. Когда вы нажмете Enter, ваша программа получит все символы, которые вы набрали, , включая символ новой строки (\n), созданный клавишей Enter.

Реальная последовательность событий выглядит следующим образом:

  1. Ваша программа печатает первую строку.
  2. Ваша программа вызывает getchar(), которая пытается прочитать символ из стандартного входного потока. Поскольку поток в настоящее время пуст, он приостанавливает вашу программу до тех пор, пока не поступит некоторая информация.
  3. Вы увидите приглашение и нажмите клавишу (скажем, X). Поскольку ваш терминал буферизирован в строке, ваша программа еще не видит его, и поэтому остается приостановленной.
  4. Вы нажимаете Enter. Теперь ваш терминал отправляет персонажи, введенные вами (X и \n) в вашу программу.
  5. getchar() возвращает первый символ, доступный вашей программе на стандартный вход, то есть X.
  6. Ваш код теперь распечатывает второе приглашение и снова вызывает getchar(). getchar() видит, что есть еще один символ (\n), который все еще ждет стандартного ввода и сразу же возвращает его.
+0

Новая строка от первого ответа - это пустая строка между двумя выходами, правильно? Поэтому в буфере не должно быть ничего ожидающего второго ответа.он уже выведен на экран – DNadler

+0

Мой плохой ... Я не думал о физическом нажатии «Enter» на клавиатуре. – DNadler

0

Так поступают потоки ввода. , когда первый сегмент работает и для ввода первого символа, нажмите клавишу ввода. Он в основном воспринимается как символ во входном потоке. поэтому, если вы введете 'a' и нажмите enter, это будет как 'a \ n' в потоке ввода. Теперь с помощью getchar вы читаете один символ из входного потока в свою переменную, которая является «а» здесь. При подаче вам «входной поток» остается «\ n». В следующий раз, когда вы получите getchar, вы получите '\ n' в качестве символа. даже если вы вводите новые символы, он всегда будет первым в потоке, т. е. '\ nabc ....'

'\ n' это просто для объяснения нового символа линии.