Получить scanf для выхода, когда он читает новую строку?

Если я нахожу 5 5 на терминале, нажмите enter и снова нажмите Enter, я хочу выйти из цикла.

 int readCoefficents(double complex *c){ int i = 0; double real; double img; while(scanf("%f %f", &real, &img) == 2) c[i++] = real + img * I; c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1 return i; } 

Очевидно, что этот код не выполняет эту работу для меня (и, да, я знаю, что произойдет переполнение буфера).

scanf не будет scanf , если я не наберу букву (или некоторую нечисловую, а не простую строку). Как заставить scanf завершить работу после чтения пустой строки?

Используйте fgets для чтения ввода в консоль:

  int res = 2; while (res == 2) { char buf[100]; fgets(buf, sizeof(buf), stdin); res = sscanf(buf, "%f %f", &real, &img); if (res == 2) c[i++] = real + img * I; } c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1 return i; 

Конкретная проблема, с которой вы сталкиваетесь, заключается в том, что строка формата scanf %f пропускает пробел ( включая символы новой строки), пока не найдет фактический символ для сканирования. Из стандарта c99:

Спецификация преобразования выполняется в следующих шагах:
– Входные символы пробела (как указано в функции isspace ) пропускаются, если спецификация не включает спецификатор '[' , 'c' или 'n' .

и, в другом месте, описывая isspace() :

Стандартными символами пробела являются: space ' ' , form feed '\f' , new-line '\n' , возврат каретки '\r' , горизонтальная вкладка '\t' и вертикальная вкладка '\v' ,

Лучше всего использовать fgets для получения строки (и это можно легко защитить от переполнения буфера), а затем использовать sscanf в результирующей строке.

Функция scanf является одной из тех, над которыми вы должны смотреть очень осторожно. Следующий fragment кода – это тот, который я часто использую для обработки ввода строки:

 #include  #include  #define OK 0 #define NO_INPUT 1 #define TOO_LONG 2 static int getLine (char *prmpt, char *buff, size_t sz) { int ch, extra; // Get line with buffer overrun protection. if (prmpt != NULL) { printf ("%s", prmpt); fflush (stdout); } if (fgets (buff, sz, stdin) == NULL) return NO_INPUT; // If it was too long, there'll be no newline. In that case, we flush // to end of line so that excess doesn't affect the next call. if (buff[strlen(buff)-1] != '\n') { extra = 0; while (((ch = getchar()) != '\n') && (ch != EOF)) extra = 1; return (extra == 1) ? TOO_LONG : OK; } // Otherwise remove newline and give string back to caller. buff[strlen(buff)-1] = '\0'; return OK; } 

 // Test program for getLine(). int main (void) { int rc; char buff[10]; rc = getLine ("Enter string> ", buff, sizeof(buff)); if (rc == NO_INPUT) { // Extra NL since my system doesn't output that on EOF. printf ("\nNo input\n"); return 1; } if (rc == TOO_LONG) { printf ("Input too long [%s]\n", buff); return 1; } printf ("OK [%s]\n", buff); return 0; } 

Тестирование с помощью различных комбинаций:

 pax> ./prog Enter string>[CTRL-D] No input pax> ./prog Enter string> a OK [a] pax> ./prog Enter string> hello OK [hello] pax> ./prog Enter string> hello there Input too long [hello the] pax> ./prog Enter string> i am pax OK [i am pax] 

Я бы сделал это, чтобы использовать эту функцию, чтобы безопасно получить строку, а затем просто используйте:

 sscanf (buffer, "%f %f", &real, &img) 

для получения фактических значений (и проверки счетчика).


Фактически, вот полная программа, которая ближе к тому, что вы хотите:

 #include  #include  #define OK 0 #define NO_INPUT 1 #define TOO_LONG 2 static int getLine (char *prmpt, char *buff, size_t sz) { int ch, extra; // Get line with buffer overrun protection. if (prmpt != NULL) { printf ("%s", prmpt); fflush (stdout); } if (fgets (buff, sz, stdin) == NULL) return NO_INPUT; // If it was too long, there'll be no newline. In that case, we flush // to end of line so that excess doesn't affect the next call. if (buff[strlen(buff)-1] != '\n') { extra = 0; while (((ch = getchar()) != '\n') && (ch != EOF)) extra = 1; return (extra == 1) ? TOO_LONG : OK; } // Otherwise remove newline and give string back to caller. buff[strlen(buff)-1] = '\0'; return OK; } 

 int main (void) { int i = 1, rc; char prompt[50], buff[50]; float real, imag; while (1) { sprintf (prompt, "\nEnter real and imaginary for #%3d: ", i); rc = getLine (prompt, buff, sizeof(buff)); if (rc == NO_INPUT) break; if (*buff == '\0') break; if (rc == TOO_LONG) { printf ("** Input too long [%s]...\n", buff); } if (sscanf (buff, "%f %f", &real, &imag) == 2) { printf ("Values were %f and %f\n", real, imag); i++; } else { printf ("** Invalid input [%s]\n", buff); } } return 0; } 

наряду с тестовым прогоном:

 pax> ./testprog Enter real and imaginary for # 1: hello ** Invalid input [hello] Enter real and imaginary for # 1: hello there ** Invalid input [hello there] Enter real and imaginary for # 1: 1 ** Invalid input [1] Enter real and imaginary for # 1: 1.23 4.56 Values were 1.230000 and 4.560000 Enter real and imaginary for # 2: pax> _ 

Есть способ сделать то, что вы хотите, используя только scanf:

 int readCoefficents(double complex *c) { int i = 0; double real; double img; char buf[2]; while (scanf("%1[\n]", buf) == 0) { // loop until a blank line or EOF if (scanf("%lf %lf", &real, &img) == 2) // read two floats c[i++] = real + img * I; scanf("%*[^\n]"); // skip the rest of the line scanf("%*1[\n]"); // and the newline } c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1 return i; } 

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

re PAXDIABLO: он не работает должным образом с EMPTY-линией, введенной пользователем, поэтому эта строка должна быть добавлена ​​в вашу функцию getLine ()

 if (strlen(buff) <= 1) return NO_INPUT; 

после строки:

 if (fgets (buff, sz, stdin) == NULL) return NO_INPUT; 

Так оно и будет:

 ... if (strlen(buff) <= 1) return NO_INPUT; if (fgets (buff, sz, stdin) == NULL) return NO_INPUT; .... 
  • что такое эквивалент Java sscanf для синтаксического анализа значений из строки с использованием известного шаблона?
  • scanf игнорирование, бесконечный цикл
  • Как я могу прочитать строку ввода неизвестной длины?
  • Разница между scanf и scanf_s
  • scanf () оставляет новый символ строки в буфере
  • Почему scanf ("% d", ) не потребляет '\ n'? в то время как scanf («% c»)?
  • Scanf не будет выполняться во второй раз
  • Почему пространство в моей команде scanf имеет значение?
  • Чтение строки с помощью scanf
  • В чем разница между sscanf или atoi, чтобы преобразовать строку в целое число?
  • scanf не будет запрашивать ввод во второй раз
  • Interesting Posts

    Могу ли я исправить ошибку 0xc0000225 без переустановки Windows?

    Правило CSS на основе контента

    У меня есть PCI-карта с напряжением 3,3 вольта, работающая на 5-вольтном PCI-слоте. Как это возможно?

    Язык задания принтера -> PDF

    Поместите кнопки внизу экрана с помощью LinearLayout?

    System32 и SysWOW64 для Windows 7

    Excel для подсчета количества параллельных сеансов в зависимости от времени начала и окончания и имени ПК

    Как сопоставить несколько вхождений строки в строке с помощью reg ex

    Java: boolean in println (boolean? “Print true”: “print false”)

    Нужно приложение, которое сообщает о размерах файлов и папок

    Android скрывает / скрывает значок приложения программно

    Как скрыть результаты формулы до тех пор, пока не будут выполнены условия

    Как я могу получить путь к папке «Данные приложения» текущего пользователя?

    Запуск программ удаленно через SSH на Windows 7

    Половина установленной оперативной памяти – это аппаратное обеспечение

    Давайте будем гением компьютера.