我需要从用户输入中收到可以有2种形式的char
int
float
或char
int
,但我不会#39知道会给出哪一个。我试过这个:
int main(){
char letter;
int num;
float value;
while(getchar()!=EOF){
scanf(" %c %d %f", &letter, &num, &value);
printf("%c\n", letter);
printf("%d\n", num);
printf("%f\n", value);
}
return 0;
}
这个问题是当我提供这样的输入时:
? 12345
g 12345 45.6
? 12345
Output given: Expected Output:
1 ?
2345 12345
0.000000 0.000000
1 g
2345 12345
45.599998 45.599998
? ?
12345 12345
45.599998 45.599998
为什么忽略char
和char
位置的部分号码?有办法解决这个问题吗?
答案 0 :(得分:1)
在这种情况下,最好首先将用户输入检索为char *(fgets-like),然后使用sscanf(而不是scanf,sscanf)解析它。 您必须检查sscanf的返回值,以便了解输入用户的格式是否正确。
如果您需要在解析后检查是否没有垃圾值(例如" g 12345 45.6 garbagevalue"),您可以在之后添加%c并检查值是否已更改。
char letter;
int integerNumber;
double floatingNumber;
char end;
char *userInput = ...;
end = '\0';
if (sscanf(userInput, "%c %d %f%c", &letter, &integerNumber, &floatingNumber, &end) == 3 && end == '\0') {
// First form
} else {
end = '\0';
if (sscanf(userInput, "%c %d%c", &letter, &integerNumber, &end) == 2 && end == '\0') {
// Second form
} else {
// Error : Input not strictly "%c %d %f" or "%c %d"
}
}
听起来不错?
答案 1 :(得分:1)
我想知道从键盘读取数据块到键盘上的字符串然后用sscanf
进行分析会更简单,如下面的大纲所示
#define MAX_INPUT 100
char data_input[MAX_INPUT];
int finished=0, test;
char letter;
int num;
float value;
while (finished==0) {
// scanf("%s",data_input); //taken out after useful comments below
fgets(data_input,100,stdin); //replacement from comments...
// insert code using sscanf to read in data from user
test=sscanf(data_input, "%c %d %f", &letter, &num, &value);
if (test==3)
{
//success - sscanf successfully assigned 3 values...
// (ony if you have everything you need then....)
finished =1;
} else if (test==2){
// insert something to try to test if data from two data entries is ok....
// (ony if you have everything you need then....)
finished =1;
} else {
printf("problem with data entry - please type again\n");
}
}
向@ Tom's道歉,因为sscanf
的使用是他首次提出的......
答案 2 :(得分:1)
这里有几个问题:
缺少的字符。当您第一次执行while(getchar()!=EOF)
时,您正在使用流中的第一个字符,恰好是'?'
。后续的scanf()
无法再检索到它,因此它会抓取下一个非空格字符,该字符恰好是以下数字的'1'
。
在读取'1'
之后,将解析该数字的其余部分,并提供结果2345
。
以下转换尝试解析float,但下一个非空白字符是g
,因此无法读取浮点数,转换失败。
您无法检查,转化成功的次数。 scanf()
尽职尽责地返回成功转化的次数,但您忽略了这一点。
如果您检查了返回值,您会发现第一个scanf()
调用返回2
,因为字符和整数转换成功完成,但浮点转换失败。
同样,第二个scanf()
调用应返回3
,表示所有三次转换都成功。对scanf()
的最后一次通话应该再次返回2
。
while(getchar()!=EOF)
中某个角色的吞噬会在第二行再次咬你,这次是'g'
在scanf()
获得之前从流中删除的scanf()
有机会阅读它。
第二次调用'\n'
成功终止后,while(getchar()!=EOF)
字符将保留在流中。因此,以下scanf()
gogbles up和第三个'?'
调用最终可以正确获取行上的第一个字符(scanf()
)。
浮点转换在第三个输入行上再次失败,并且相应的变量保持不变,并且您无法通过忽略getchar()
的返回值来检测此情况。
长话短说:
每次scanf()
来电都会消耗scanf()
无法读取的字符。
忽略返回值的任何man scanf
调用都是错误。没有检查,你就不知道你实际上读过任何东西。
顺便说一下:man getchar
和const oneHour: number = 1000 * 60 * 60;
const projection: {} = { tag: 1 };
const filter: {} = {
battleLogMonitorFrequency: interval,
profileRefreshedAt: { $lt: new Date(snapDate.valueOf() - interval * oneHour) }
};
const profileCursorTrophies: QueryCursor<IPlayerProfileModel> = PlayerProfile.find(filter, projection).sort({ trophies: -1 })
.limit(50000).lean().cursor();
await profileCursorTrophies.eachAsync(
(profile: IPlayerProfileModel) => {
outDatedProfileTags.push(profile.tag);
},
{ parallel: 100 }
);
本来可以告诉你我刚说过的一切。知道如何阅读联机帮助页是值得的。