如何在循环中结合使用 scanf(对于非字符或字符串)获取单个字符
How to get a single character in conjunction with using scanf (for non-characters or Strings) in a loop
这是我的代码:
struct Patient{
char name[50];
char gender ; // M:male , F:female
unsigned age ;
unsigned Systole;
unsigned Diastole;
};
//blah blah blah
struct Patient P[3];
for(i=0 ; i<3 ; i++){
printf("\nPATIENT%d\n",i+1);
printf("Name:");
gets(P[i].name);
printf("Gender(F=female , M=male):");
scanf("%c",&(P[i].gender));
printf("Systole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
printf("\n%s %c %u %u\n", P[i].name, P[i].gender, P[i].Systole, P[i].Diastole);
}
这是我的输出:
PATIENT1
Name:Samantha
Gender(F=female , M=male):F
Systole:120
Diastole:90
Samantha F 120 90
PATIENT2
Name:Gender(F=female , M=male):Jack
Systole:Diastole:
J 4718656 131072
PATIENT3
Name:Gender(F=female , M=male):Michael
Systole:Diastole:
ack M 16454 2
Normal:0
如您所见(我在获取每个结构索引数据后打印)我在获取用户输入时遇到问题。有什么问题吗?
编辑。
我将代码(由于建议)更改为:
for(i=0 ; i<3 ; i++){
printf("\nPATIENT%d\n",i+1);
printf("Name:");
scanf("%s", &(P[i].name));
printf("Gender(F=female , M=male):");
scanf("%c",&(P[i].gender));
printf("Systole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
printf("\n%s %c %u %u\n", P[i].name, P[i].gender, P[i].Systole, P[i].Diastole);
}
但输出仍然失真:
PATIENT1
Name:Alison
Gender(F=female , M=male):Systole:F
Diastole:
Alison
436170816 4044120064
PATIENT2
Name:Gender(F=female , M=male):Systole:Jack
Diastole:
F
4456512 131072
PATIENT3
Name:Gender(F=female , M=male):Systole:Sandy
Diastole:
Jack
函数gets
不存储换行符,所以你必须使用:
scanf(" %c", &(P[i].gender))
注意 space 将跳过空白 space 包括换行符
你应该避免使用 gets
函数,尽量只使用 scanf
这应该是:
scanf(" %49[^\n]%*c", P[i].name)
有关 scanf 如何工作的更多信息,请参阅此 post
将所有工作代码放在一起是:
for(i=0 ; i<3 ; i++){
printf("\nPATIENT%d\n",i+1);
printf("Name:");
scanf(" %49[^\n]%*c", P[i].name);
printf("Gender(F=female , M=male):");
scanf(" %c",&(P[i].gender));
printf("Systole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
printf("\n%s %c %u %u\n", P[i].name, P[i].gender, P[i].Systole, P[i].Diastole);
}
第一个 scanf 现在也消耗上一次迭代中的任何换行符。
你的主要问题是这条语句:
scanf("%c",&(P[i].gender));
c
转换说明符不会跳过输入流中的任何前导白色space(例如前一个条目后面的换行符,gets
不会consume),所以你选择了性别的换行符,这就抛弃了后面的所有内容。
要解决此问题,请在 %c
:
之前放置一个空白 space
scanf(" %c",&(P[i].gender));
空白 space 告诉 scanf
消耗所有领先的白色 space。
此外,请勿使用 gets
- 它已在 C99 TC3 中弃用,并已从 C2011 规范中完全删除。它 将 在您的代码中引入一个故障点。使用 fgets
代替:
fgets( P[i].name, sizeof P[i].name, stdin );
与 gets
不同,如果有空间,fgets
将使用换行符并将其存储到目标缓冲区中,因此您需要检查并删除它,如下所示:
char *newline = strchr( P[i].name, '\n' );
if ( newline )
*newline = 0;
scanf("%u",&(P[i].Diastole));得到一个整数,但留下一个新行(从用户输入数字并按回车)
在循环的第二次迭代中,gets(P[i].name);读取剩下的换行符并将其他所有内容从该点开始。
您需要处理读取最后一个换行符(或可能 \r\n),或者您可以使用 gets 或更好的 fgets 读取每一行输入并使用 sscanf 或 atoi 等获取值来自它(当需要一个数字时)。
我终于得到了真实而简洁的答案:
The scanf
function removes whitespace automatically before trying to parse things other than characters. The character formats (primarily %c
) are the exception; they don't remove whitespace.
自从我得到一个性别字符后,它就引起了问题。最后我意识到使用 getch()
是最好的解决方案,因为它不会立即将任何内容放入缓冲区和 returns。另外 getch()
是 non-standard,但它存在于我的案例中。
所以最后这是我的代码:
for(int i=0 ; i<3 ; i++){
printf("\nPatient%d",i+1);
printf("\nName:");
scanf("%s", P[i].name);
printf("Age:");
scanf("%u", &(P[i].age));
printf("Gender(F=female , M=male):");
P[i].gender = getchar();
printf("\nSystole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
}
我还编辑了问题标题,因为它具有误导性。谢谢大家的回答努力。
这是我的代码:
struct Patient{
char name[50];
char gender ; // M:male , F:female
unsigned age ;
unsigned Systole;
unsigned Diastole;
};
//blah blah blah
struct Patient P[3];
for(i=0 ; i<3 ; i++){
printf("\nPATIENT%d\n",i+1);
printf("Name:");
gets(P[i].name);
printf("Gender(F=female , M=male):");
scanf("%c",&(P[i].gender));
printf("Systole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
printf("\n%s %c %u %u\n", P[i].name, P[i].gender, P[i].Systole, P[i].Diastole);
}
这是我的输出:
PATIENT1
Name:Samantha
Gender(F=female , M=male):F
Systole:120
Diastole:90
Samantha F 120 90
PATIENT2
Name:Gender(F=female , M=male):Jack
Systole:Diastole:
J 4718656 131072
PATIENT3
Name:Gender(F=female , M=male):Michael
Systole:Diastole:
ack M 16454 2
Normal:0
如您所见(我在获取每个结构索引数据后打印)我在获取用户输入时遇到问题。有什么问题吗?
编辑。
我将代码(由于建议)更改为:
for(i=0 ; i<3 ; i++){
printf("\nPATIENT%d\n",i+1);
printf("Name:");
scanf("%s", &(P[i].name));
printf("Gender(F=female , M=male):");
scanf("%c",&(P[i].gender));
printf("Systole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
printf("\n%s %c %u %u\n", P[i].name, P[i].gender, P[i].Systole, P[i].Diastole);
}
但输出仍然失真:
PATIENT1
Name:Alison
Gender(F=female , M=male):Systole:F
Diastole:
Alison
436170816 4044120064
PATIENT2
Name:Gender(F=female , M=male):Systole:Jack
Diastole:
F
4456512 131072
PATIENT3
Name:Gender(F=female , M=male):Systole:Sandy
Diastole:
Jack
函数gets
不存储换行符,所以你必须使用:
scanf(" %c", &(P[i].gender))
注意 space 将跳过空白 space 包括换行符
你应该避免使用 gets
函数,尽量只使用 scanf
这应该是:
scanf(" %49[^\n]%*c", P[i].name)
有关 scanf 如何工作的更多信息,请参阅此 post
将所有工作代码放在一起是:
for(i=0 ; i<3 ; i++){
printf("\nPATIENT%d\n",i+1);
printf("Name:");
scanf(" %49[^\n]%*c", P[i].name);
printf("Gender(F=female , M=male):");
scanf(" %c",&(P[i].gender));
printf("Systole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
printf("\n%s %c %u %u\n", P[i].name, P[i].gender, P[i].Systole, P[i].Diastole);
}
第一个 scanf 现在也消耗上一次迭代中的任何换行符。
你的主要问题是这条语句:
scanf("%c",&(P[i].gender));
c
转换说明符不会跳过输入流中的任何前导白色space(例如前一个条目后面的换行符,gets
不会consume),所以你选择了性别的换行符,这就抛弃了后面的所有内容。
要解决此问题,请在 %c
:
scanf(" %c",&(P[i].gender));
空白 space 告诉 scanf
消耗所有领先的白色 space。
此外,请勿使用 gets
- 它已在 C99 TC3 中弃用,并已从 C2011 规范中完全删除。它 将 在您的代码中引入一个故障点。使用 fgets
代替:
fgets( P[i].name, sizeof P[i].name, stdin );
与 gets
不同,如果有空间,fgets
将使用换行符并将其存储到目标缓冲区中,因此您需要检查并删除它,如下所示:
char *newline = strchr( P[i].name, '\n' );
if ( newline )
*newline = 0;
scanf("%u",&(P[i].Diastole));得到一个整数,但留下一个新行(从用户输入数字并按回车)
在循环的第二次迭代中,gets(P[i].name);读取剩下的换行符并将其他所有内容从该点开始。
您需要处理读取最后一个换行符(或可能 \r\n),或者您可以使用 gets 或更好的 fgets 读取每一行输入并使用 sscanf 或 atoi 等获取值来自它(当需要一个数字时)。
我终于得到了真实而简洁的答案:
The
scanf
function removes whitespace automatically before trying to parse things other than characters. The character formats (primarily%c
) are the exception; they don't remove whitespace.
自从我得到一个性别字符后,它就引起了问题。最后我意识到使用 getch()
是最好的解决方案,因为它不会立即将任何内容放入缓冲区和 returns。另外 getch()
是 non-standard,但它存在于我的案例中。
所以最后这是我的代码:
for(int i=0 ; i<3 ; i++){
printf("\nPatient%d",i+1);
printf("\nName:");
scanf("%s", P[i].name);
printf("Age:");
scanf("%u", &(P[i].age));
printf("Gender(F=female , M=male):");
P[i].gender = getchar();
printf("\nSystole:");
scanf("%u",&(P[i].Systole));
printf("Diastole:");
scanf("%u",&(P[i].Diastole));
}
我还编辑了问题标题,因为它具有误导性。谢谢大家的回答努力。