2015-07-13 3 views
1

Я хочу ссылаться на ввод name на протяжении всего кода, который я пишу, но по какой-то причине после его успешного использования в первом printf() второй printf() не печатает имя.Вход Scanf для char работает один раз, а затем пуст

int main() 
{ 
    char name[50]; 
    char q1[1]; 
    printf(" What is your name?\n"); 
    scanf("%s", name); 
    printf(" Hi %s, Do you want to have some fun? [Y/N]\n",name); 
    scanf("%s",q1); 

    if(strcmp(q1,"Y") == 0||strcmp(q1,"y")==0) 
    { 
     printf("Awesome, let's play!\n"); 
    } 
    else 
    { 
     printf("Fine"); goto endgame; 
    } 
    printf("So %s, it's time to get started\n", name); 
    endgame: 
     getchar(); 
    return 0; 
} 

Выход для записи «Ника» является:

Привет Ник, вы хотите повеселиться?
Удивительная давайте играть
Так, давайте начнем

я ожидал бы сказать:

Так Ник, давайте начнем.

но почему-то char name пуст после того, как он правильно используется в первый раз.

+3

что 'q1', точно ? –

+1

'scanf ("% s ", name);' -> 'scanf ("% 49s ", name);' –

+0

Я добавил 'char q1 [50];' и он работает для меня. – moffeltje

ответ

2

Развернуть размер вашего q1 буфера. scanf("%s", q1) не хватает места для хранения ввода. Помните, что C использует пустой символ '\0' для прекращения строк. Если вы не учтете это, буфер может переполняться в другую память, вызывая undefined behavior. В этом случае это, вероятно, переписывает память, выделенную для name, поэтому name заканчивается, указывая на «\ 0ick». Это вызывает printf(%s), который ищет '\0', чтобы узнать, когда прекратить печать, подумать, что строка короче, чем есть на самом деле.

код работает отлично, если вы расширяете буфер:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

int main(void) 
{ 
    char name[50]; 
    char q1[50]; 
    printf(" What is your name?\n"); 
    scanf("%49s", name); 
    printf(" Hi %s, Do you want to have some fun? [Y/N]\n",name); 
    scanf("%49s",q1); 

    if(strcmp(q1,"Y") == 0||strcmp(q1,"y")==0) 
    { 
     printf("Awesome, let's play!\n"); 
    } 
    else 
    { 
     printf("Fine"); 
    } 
    printf("So %s, it's time to get started\n", name); 
    getchar(); 
    return 0; 
} 

Выход:

What is your name? 
Nick 
Hi Nick, Do you want to have some fun? [Y/N] 
y 
Awesome, let's play! 
So Nick, it's time to get started 

Обратите внимание, что я добавил спецификатор %49s, чтобы избежать переполнения буфера, как это.


Вы можете также обойти необходимость другой строки полностью изменив char q1[50] и scanf("%49s") не просто char q1 и scanf("%c%*c", &q1) (обратите внимание на «адрес» оператора, потому что q1 больше не является указателем).

Возможно, вы даже получите выигрыш в производительности от этого (хотя и небольшой), потому что строки являются печально известными хоггерами памяти. Сравнение одного символа обычно предпочтительнее сравнения строк.

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

int main(void) 
{ 
    char name[50]; 
    char q1; 
    printf(" What is your name?\n"); 
    scanf("%49s%*c", name); 
    printf(" Hi %s, Do you want to have some fun? [Y/N]\n",name); 
    scanf("%c%*c",&q1); 

    if(q1 == 'Y' || q1 == 'y') 
    { 
     printf("Awesome, let's play!\n"); 
    } 
    else 
    { 
     printf("Fine"); 
    } 
    printf("So %s, it's time to get started\n", name); 
    getchar(); 
    return 0; 
} 
    if(q1 == 'Y' || q1 == 'y') 
    { 
     printf("Awesome, let's play!\n"); 
    } 
    else 
    { 
     printf("Fine"); 
    } 
    printf("So %s, it's time to get started\n", name); 
    getchar(); 
    return 0; 
} 

Если вы идете по этому пути, вы должны игнорировать клавишу ввода с помощью спецификатора формата %*c, потому что нажатие кнопки ENTER посылает ключ к потоку, а также.

4

Проблема, (, как я правильно предполагается) находится с char q1[1];, а затем использовать его как

scanf("%s",q1); 

Это вызывает граничную переполнение памяти, потому что, массив один-символ не является достаточным, чтобы провести строка имеет только один элемент, поскольку ему не хватает места для нуль-терминатора, необходимого для строки . Это вызывает undefined behaviour.

Вместо

  • изменение char q1[1]; к char q1;
  • изменение scanf("%s",q1); к scanf(" %c", &q1);
  • изменение if(strcmp(q1,"Y") == 0||strcmp(q1,"y")==0) в if((q1 =='Y') || q1 == 'y')

Тем не менее, как примечание,

  1. Рекомендованная подпись main() - int main(void).
  2. Чтобы избежать переполнения буфера на более вход (ы), то лучше ограничить длину ввода с scanf() написав как

    scanf("%49s", name); 
    
Смежные вопросы