2015-10-16 3 views
0

Я новичок в мире C, и у меня проблема с функцией fgets(). Я искал почти 2 часа своей ошибки и нашел разные решения, но никто не работал.C fgets семантическая ошибка

Мой класс слишком велик для просто показать каждую ее части, но позвольте мне показать вам проблемную часть:

//... kivansag is a struct(!) 
if(check == 1){ 
     char name; 
     printf("Please give me your nickname!\n"); 
     scanf("%s", &name); 
     strcpy(kivansag.name,&name); 

     char city; 
     printf("Please give me your city!\n"); 
     scanf("%s", &city); 
     strcpy(kivansag.city,&city); 

     char *address = malloc(100); 
     printf("Please give me your address!\n");   
     fgets(address,100,stdin); 

     if((strlen(address)>0) && address[strlen(address)-1] == '\n'){ 
      address[strlen(address)-1] = '\0'; 
     } 

     strcpy(kivansag.address,address); 
     free(address); 
}//... 

Проблема заключается в том: Каждый раз, когда я запускаю этот код, бегущая сервер пропуск fgets() после того, как он написал «Дайте мне свой адрес» и выполните следующую функцию.

Могу ли я получить предложения?

ОБНОВЛЕНО:

Теперь у меня есть только это:

 printf("Please give me your address!\n");   
     fgets(kivansag.address,sizeof(kivansag.address),stdin); 

     if((strlen(kivansag.address)>0) && kivansag.address[strlen(kivansag.address)-1] == '\n'){ 
      kivansag.address[strlen(kivansag.address)-1] = '\0'; 
     } 

структура кажется, что это:

struct Kivansag{ 
    //... 
    char address[100]; 
}; 

И да, еще пропуская мою часть ... Я пытался использовать fflush(stdin) тоже, чтобы все было ясно, но не сработало.

+0

'char name;' - переменная с достаточным пространством для ** одного символа **. – wildplasser

+1

Подсказка: какой символ не соответствует 'scanf ("% s ")' (остающийся во входном потоке), но приводит к немедленному возврату 'fgets()'? – EOF

+0

всегда проверяют (! = NULL) возвращаемое значение из malloc(), чтобы гарантировать успешную работу. – user3629249

ответ

0
scanf("%s", &name);  //you cant use %s to take input in a char variable 
... 
scanf("%s", &city); 

В этих name и city две символьные переменные, а не null terminated строки. Таким образом, используя здесь -

strcpy(kivansag.name,&name); 

приводит к UB.

Вы можете объявить их как массивы -

char name[20]; 
char city[20]; 
fgets(name,20,stdin);  
... 
fgets(city,20,stdin); 
strcpy(kivansag.name,name);  // note address of name is not required 
/* similarly for copying city */ 

Так из-за этого следующий fgets также не будут пропущены.

И тогда поступайте так, как вы делали.

+0

Я пробовал и не делал работал. В последнем случае я прокомментировал имена и городские входы, и теперь у меня есть только адресная часть .. все еще пропускаю. –

0

- всего лишь один символ, вы не можете использовать его для чтения строки с форматом %s в scanf. Вам нужно предоставить массив символов. Нет необходимости сканировать в одну переменную, а затем копировать в другую, вы можете сканировать непосредственно в член структуры.

scanf("%s", kivansag.name); 

Вы также можете использовать fgets() непосредственно в переменную:

fgets(kivansag.address, sizeof kivansag.address, stdin); 
size_t len = strlen(kivansag.address); 
if((len>0) && kivansag.address[len-1] == '\n'){ 
    kivansag.address[len-1] = '\0'; 
} 

См fgets doesn't work after scanf, почему ваша программа пропускает fgets и как это исправить.

+0

Я мог бы использовать его для чтения строки :). Но ваш отчет достаточно справедлив. Но код работает отлично, за исключением части «адрес». –

+0

Вы также можете использовать 'fgets' для чтения непосредственно в структуре. Я обновил ответ, чтобы показать это. – Barmar

+0

Спасибо, это действительно лучше, чем у меня, я использовал его ... все еще есть проблема, я обновил сообщение. –

0

эти две линии всегда будут создавать неопределенное поведение.

Неопределенное поведение может привести ни к чему, в том числе случае неисправности SEG

char name; 
    .... 
    scanf("%s", &name); 

функция Scanf() всегда присоединяет байт NUL на строку, которая была ввода.

есть только один байт, указанный в char name.

На «% s» нет ограничений, поэтому пользователь может/всегда будет перегружать этот один байтовый буфер.

Предложите что-то вроде:

char name[30]; 
    .... 
    if(1 != scanf("%29s", &name) { // handle error } 

этой линии:

scanf("%s", &city); 

оставил строку во входном потоке.

следующий вызов fgets() будет видеть, что символ новой строки, и сразу же вернуться ни с чем положить в буфер ввода, но символ новой строки и байт NUL

это очень запутанные линии:

if((strlen(address)>0) && address[strlen(address)-1] == '\n'){ 
     address[strlen(address)-1] = '\0'; 
    } 

может или не может найти встроенный символ новой строки и обложите его байтами NUL Предлагайте:

if(char* newline = strstr(address, "\n")) 
    *newline = '\0'; 

Есть даже «аккуратнее» способы заменить т он newline в строке , но этот метод легко понять.

Смежные вопросы