'fgets ()' в цикле 'for' запрашивает ввод только один раз [dубликат]

Кэш arp предоставляется в качестве стандарта в наборе доступных данных SNMP. Вы можете использовать SNMP4J для записи тривиального агента для запроса этих данных.

, например. из командной строки SNMP toolset

  snmpwalk $ {hostname} 1.3.6.1.2.1.4.22.1.2  

(эта огромная строка с разделителями периодов является OID или идентификатор кеша ARP в терминах SNMP, который будет работать для всех реализаций SNMP)

9
задан Vayn 7 May 2011 в 00:37
поделиться

7 ответов

scanf () читает именно то, что вы просили, оставив следующий \n с конца этой строки в буфере, где fgets () [ ! d2] прочитает его. Либо сделайте что-нибудь, чтобы использовать новую строку, или (мое предпочтительное решение) fgets () , а затем sscanf () из этой строки.

18
ответ дан geekosaur 16 August 2018 в 08:00
поделиться
  • 1
    Если я хочу использовать scanf () , как я могу использовать новую строку? Благодарю. – Vayn 7 May 2011 в 00:59
  • 2
    Используйте в конце формата что-то вроде % * [^ \n]% * c , чтобы пропустить любые символы в новой строке, а затем сама новая строка. – geekosaur 7 May 2011 в 01:07
  • 3
    Я не знаю эту грамматику раньше, спасибо вам большое! – Vayn 7 May 2011 в 01:11
  • 4
    @geekosaur: просто нажатие % * [^ \n]% * c в конце формата на самом деле не будет работать, если после предыдущего чтения и перед новой строкой нет символов, поскольку то % * [^ \n] не будет соответствовать, так что % * c будет пропущен, а новая строка останется на входе. Вам нужно сделать % * c в отдельном вызове scanf, чтобы он работал. – Chris Dodd 16 May 2016 в 01:59

Следующее работает, если fgets () «пропущен» после использования scanf ()

После того, как вы сказали:

  scanf ("% d", & amp; loops);   

Скажите:

  char мусор [100];  fgets (мусор, 100, STDIN);   

Это сохранит все оставленные на входном буфере в переменной мусора.

Это эффективно очистит входной буфер и позволит вам использовать fgets () после.

EDIT: Недавно я узнал, что есть более легкое решение, чем выше. Если вы скажете getchar () после scanf (), это позволит вам использовать fgets () без проблем. getchar () получит следующий символ во входном буфере, который в этом случае будет «\n». После удаления '\n' из входного буфера fgets должен работать нормально.

0
ответ дан Coder Typist 16 August 2018 в 08:00
поделиться

Vayn,

Geekoaur ответил на ваш вопрос хорошо, я просто указываю еще одну «проблему» с вашим кодом.

Строка s1 [strlen (s1)] = '\ 0'; является no-op , если s1 уже полностью нулевое завершение до того, как оно выполняется.

Но если s1 NOT allready должным образом завершен нулем до того, как эта строка выполняется (и вам не повезло), это приведет к:

Это потому, что strlen basicaly находит индекс существующего нуль-терминатора и возвращает его! Вот действительная, неоптимизированная реализация strlen:

  int strlen (char * string) {int i = 0;  while (string [i]! = '\ 0') {++ i;  } return i;  }  

Итак ... Если вы ДЕЙСТВИТЕЛЬНО беспокоитесь о том, что строки НЕ были завершены нулями, вы сделали бы что-то вроде:

  • string [sizeof (string)] = '\ 0'; на локальных автоматических строках (где компилятор «знает» размер строки);
  • или [SIZE_OF_STRING] для всех остальных строк, где SIZE_OF_STRING (чаще всего) a #define 'd константа или переменная, которую вы поддерживаете специально для хранения текущего SIZE (не длина) динамически выделенной строки.

И если вы ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО беспокоитесь о строках, (например, вы используете «грязные» методы libary (например, ATMI Tuxedo), вы также «очищаете» свои «строки возврата» перед передачей их методам подозрительной библиотеки с помощью:

  • before: memset (string, NULL, SIZE_OF_STRING);
  • invoke: DirtyFunction (/ * out * / string) ;
  • после: string [SIZE_OF_STRING] = '\ 0' [! ​​d15]

SIG11 - это полная привязка для поиска, потому что (если вы не «зацепите» их с помощью signal-processor и сказать иначе, они заставляют unix жестко завершать вашу программу, поэтому вы не можете ничего записывать (после факта), чтобы помочь выяснить, here-in-the-hell-do-that-come-from ... особенно учитывая, что во многих случаях строка кода, которая выбрасывает SIG11, не находится рядом с фактической причиной того, что строка теряет нулевой ограничитель.

Разве это имеет для вас смысл?

Cheers mate. Keith.

PS: ПРЕДУПРЕЖДЕНИЕ: strncpy НЕ все пустил нуль ... вы, вероятно, имели в виду strlcpy . Я узнал об этом трудным образом ... когда сработал биллинг на 60 миллионов долларов.


EDIT:

FYI: Вот «безопасная» (неоптимизированная) версия strlen который я назову strnlen (я считаю, что это должно быть в stdlib . Sigh.).

  // перенастраивает длину  string (capped at size-1) int strnlen (char * string, int size) {int i = 0;  while (i & lt; size & amp; & amp; string [i]! = '\ 0') {++ i;  } return i;  }  
2
ответ дан corlettk 16 August 2018 в 08:00
поделиться
  • 1
    Я новичок в C, и в учебнике много говорится о струне и безопасности. Может быть, мой учебник недостаточно хорош :( Спасибо за ваш профессиональный совет :) – Vayn 7 May 2011 в 02:09
  • 2
    Не выполняйте string [sizeof (string)] = '\ 0' [! ​​D0]! Это будет писать запись \ 0 ПОСЛЕ выделенной памяти! sizeof (s1) равен 101, а индекс s1 - от 0 до 100! Та же проблема возникает и с strnlen . Если нет \ 0 , он вернет размер , а не размер - 1 , как указано в комментарии! – TrueY 18 February 2016 в 00:19

scanf оставляет пробел во входном буфере, включая символы новой строки. Чтобы использовать fgets для чтения следующей строки, вам нужно вручную удалить оставшуюся часть текущей строки:

  int c;  do {c = getchar ();  } while (c! = EOF & amp; c! = '\n');   
4
ответ дан hugomg 16 August 2018 в 08:00
поделиться
  • 1
    Да, это тоже сработает, но я лично просто использую fgets, а затем sscanf (как было предложено geekosaur), потому что он работает «равномерно». для всех видов данных ... не только отдельных символов. И мне нравятся «универсальные, многоцелевые решения». Приветствия. Кит. – corlettk 7 May 2011 в 01:32
  • 2
    Это работает более чем на персонаже, хотя это и есть цикл для;) – hugomg 7 May 2011 в 02:22
  • 3
    , тогда как (c! = EOF & amp; c! = '\n'); не является хорошим. c выходит за рамки. – chux 23 February 2018 в 01:50
  • 4
    Я собирался извинить себя, сказав, что я, должно быть, смешивал правила C и Lua, но, видимо, этот ответ был до того, как я узнал Lua, ха-ха-ха. – hugomg 23 February 2018 в 03:45

Я знаю, что это очень старый. Я новичок в c и хотел проверить свой метод, который использует getchar :

  #include & lt; stdio.h & gt;  int main () {printf ("Введите свое имя \n");  char string [10];  scanf ("% s", строка);  printf ("Hello% s \n", строка);  // GetChar ();  # un комментируя эту строку, fgets отлично работает !!  printf («Пожалуйста, введите свое имя снова \n");  fgets (строка, 10, stdin);  printf («Hello again% s», строка);  GetChar ();  }  
1
ответ дан Michele 16 August 2018 в 08:00
поделиться
  • 1
    Попробуйте ввести «Michele \n» (пробел после имени) и посмотреть, работает ли код «un commenting this line». – chux 23 February 2018 в 01:53

просто поместите scanf ("% d \n", & amp; loops);

вместо scanf ("% d", & amp; loops);

1
ответ дан phantom_ab 16 August 2018 в 08:00
поделиться
  • 1
    Хотя этот ответ охватывает важный феномен первоначальной проблемы, он не может дать некоторое представление об этой проблеме. Таким образом, в лучшем случае полезно использовать оригинальную проблему exect и не очень полезно в долгосрочной перспективе. Пожалуйста, добавьте еще несколько объяснений, чтобы ваш ответ помог более поздним читателям найти похожие проблемы. – rpy 12 September 2016 в 13:48

Я решил вашу проблему. Теперь ваша программа работает нормально. Если у вас есть сомнения, вы можете спросить меня.

  # include & lt; stdio.h & gt;  #include & lt; string.h & gt;  int main () {int i, age;  char phone [10];  char name [100];  printf ("ENTER YOUR NAME:");  fgets (имя, 100, stdin);  printf ("ВВОД ВАШЕГО ВОЗРАСТА:");  зсапЕ ( "% d", & амп; возраст);  printf ("ВВОД ТЕЛЕФОННОГО НОМЕРА:");  scanf ("");  fgets (телефон, 10, STDIN);  printf ("\nСтадийная деталь \n");  printf ("Имя:");  fputs (name, stdout);  printf («Возраст:% d \n», возраст);  printf («Номер телефона:»);  ставит (телефон);  Е ( "---- \n");  return 0;  }  
-1
ответ дан Rohit Kadam 16 August 2018 в 08:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: