嘿,我一直在努力解决这个问题。第二个scanf不允许输入整数。我检查过以确保一切都是正确的,但还是一样。我是不是错过了什么?输出在"0"处停止;在今年年底输入您的年龄:";
int main() {
int age;
char usrname;
printf("Hello, Welcome to the birth year calculator!");
printf("nnEnter Your Name: ");
scanf("%c", &usrname);
printf("Enter your age at the end of this year: ");
scanf("%d", &age);
return 0;
}
问题在于以下两行:
printf("nnEnter Your Name: ");
scanf("%c", &usrname);
您告诉用户输入由多个字符组成的内容,但您只是从输入流中提取一个字符并将其写入usrname
。
例如,如果输入Michael
,则将从输入流中提取M
,并在流中保留ichael
。
之后,您将执行行
scanf("%d", &age);
其将尝试将输入流上剩余的内容转换为整数。但是,这将失败,因为无法将ichael
转换为整数。
通常不建议将scanf
用于基于线路的用户输入。这是因为scanf
不以直观的方式表现。例如,如上所述,它并不总是在一个函数调用中读取一行输入,这可能会造成麻烦,就像它对您所做的那样。
出于这个原因,通常建议使用函数fgets
,如果可能的话,它将始终只读取一行输入。将一行输入读取为字符串后,可以尝试将其转换为整数,例如使用函数strtol
。
请注意,fgets
还会将行末尾的换行符写入字符串,因此您可能需要删除它
从fgets((输入中删除尾部换行符
这里有一个例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char usrname[200];
char line[200];
int age;
printf("Hello, Welcome to the birth year calculator!");
printf("nnEnter Your Name: ");
fgets( usrname, sizeof usrname, stdin );
//remove newline character
usrname[strcspn(usrname,"n")] = ' ';
printf("Enter your age at the end of this year: ");
fgets( line, sizeof line, stdin );
age = strtol( line, NULL, 10 );
return 0;
}
除了char usrname
的奇数选择外,它对我来说很有效。如果在输入前键入超过1个字母,它将导致第二个scanf()
失败,您将看到错误检查。如果你不想让第一个提示的任何输入渗入第二个提示,那么你需要在两者之间刷新输入流。变量范围最小化:
#include <stdio.h>
int main() {
printf("nnEnter Your Name: ");
char usrname;
if(scanf("%c", &usrname) != 1) {
printf("usrname failedn");
return 1;
}
printf("Enter your age at the end of this year: ");
int age;
if(scanf("%d", &age) != 1) {
printf("age failedn");
return 1;
}
printf("name=%c, age=%dn", usrname, age);
return 0;
}
您可能希望使用字符串而不是用于名称的字符。如果你的用户名包含空格,那么你最好读一行fgets()
,而不是scanf()
。还将年龄更改为unsigned
。
#include <stdio.h>
#define TADMAN_IS_NOT_STINGY 254
#define str(s) str2(s)
#define str2(s) #s
int main() {
printf("nnEnter Your Name: ");
char usrname[TADMAN_IS_NOT_STINGY+1];
if(scanf("%" str(TADMAN_IS_NOT_STINGY) "s", usrname) != 1) {
printf("usrname failedn");
return 1;
}
printf("Enter your age at the end of this year: ");
unsigned age;
if(scanf("%u", &age) != 1) {
printf("usrname failedn");
return 1;
}
printf("name=%s, age=%un", usrname, age);
return 0;
}
第一个scanf
仅从stdin中读取1个字符(因为usrname
是字符而不是字符数组(,然后,如果stdin为空->则第二scanf
会等待输入,否则第二次提示打印后会自动执行第二个scanf
。
在您的情况下,我假设在第一个提示时,您输入了超过1个字符,在这种情况下,第二个scanf
将不会等待,而是使用第一个scanf
没有读取的额外输入运行。例如,如果您在第一个提示中输入john,那么第一个scanf
取j
,第二个scanf
取ohn
,并尝试转换为int。
要解决此问题,请对usrname
使用char数组,例如char usrname[128] = {0}
,或者在第一个提示(输入名称(时不要输入超过1个char。
int main() {
int age;
char usrname[128] = {0};
printf("Hello, Welcome to the birth year calculator!");
printf("nnEnter Your Name: ");
scanf("%s", usrname);
printf("Enter your age at the end of this year: ");
scanf("%d", &age);
return 0;
}
在设计这个C++答案之前,请阅读下面的注释。
这就是我所做的,它似乎运行得很好。
我创建了一个类,不确定这是否是必要的
class Person {
std::string userName;
int age;
}
main() {
Person shalofty;
std::cout << "Enter name and age" << std::endl;
std::cin >> shalofty.userName;
std::cin >> shalofty.age;
}
不同的人查看不同的优先级并提供不同的建议。这里,在注释代码中,是另一个接近原始版本但经过修饰的版本
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char usrname[200] = { 0 }; // ALWAYS initialise variables
printf("Hello, Welcome to the birth year calculator!");
printf("nnEnter Your Name: ");
if( scanf( "%[^n]", usrname ) != 1 ) { // test return codes
fprintf( stderr, "Scanf failedn" );
exit( EXIT_FAILURE );
}
// remove trailing 'n' from the name entered
usrname[ strcspn( usrname, "n" ) ] = ' ';
int usrage = 0; // define and initialise variables close to use
printf("Enter your age at the end of this year: ");
if( scanf( "%d", &usrage ) != 1 ) { // test return codes
fprintf( stderr, "Scanf failedn" );
exit( EXIT_FAILURE );
}
// do something with the user's input
printf( "Hello %s, who will be %d years old at year's endn", usrname, usrage );
return 0;
}
输出
Hello, Welcome to the birth year calculator!
Enter Your Name: Foo Bar
Enter your age at the end of this year: 42
Hello Foo Bar, who will be 42 years old at the end of this year