scanf() 的使用有点棘手,我会不惜一切代价避免使用它来扫描用户生成的输入。但是这里是关于如何获取scanf() 错误的简短概述
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int x, i, scanf_return;
printf("Enter an integer: ");
/* Reset "errno". Not necessary here, just in case. */
errno = 0;
/* scanf() returns a value in case of an error */
scanf_return = scanf("%d", &x);
/*
* scanf() returns "EOF" if it didn't find all what you wanted or
* and error happened.
* It sets "errno" to the value of the actual error. See manpage
* for all of the details.
*/
if (scanf_return == EOF) {
/*
* The error is connected to the stream, so we can differ between
* an error within scanf() and and error with the input stream
* (here: stdin)
*/
if (ferror(stdin)) {
fprintf(stderr, "Something went wrong while reading stdin: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
/* e.g. a conversion error, a float instead of an integer, letters
instead of a decimal number */
fprintf(stderr, "Something went wrong within scanf()\n");
exit(EXIT_FAILURE);
}
}
/*
* If no error occurred, the return holds the number of objects
* scanf() was able to read. We only need one, but it would throw an
* error if cannot find any objects, so the check is here for
* pedagogical reasons only.
*/
if (scanf_return != 1) {
fprintf(stderr, "Something went wrong within scanf(): wrong number of objects read.\n");
exit(EXIT_FAILURE);
}
if (x <= 1) {
fprintf(stderr, "Input must be larger than 1!\n");
exit(EXIT_FAILURE);
}
printf("The prime factorization of %d is ", x);
/* No need for that test, x is already larger than one at this point. */
/* if (x > 1) { */
while (x%2 == 0) {
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2) {
while (x%i == 0) {
printf("%d ",i);
x = x / i;
}
}
/* } */
/* Make it pretty. */
putchar('\n');
exit(EXIT_SUCCESS);
}
有效吗?
$ ./stackoverflow_003
Enter an integer: 1234
The prime factorization of 1234 is 2 617
$ factor 1234
1234: 2 617
$ ./stackoverflow_003
Enter an integer: asd
Something went wrong within scanf(): wrong number of objects read.
$ ./stackoverflow_003
Enter an integer: 123.123
The prime factorization of 123 is 3 41
不,它不起作用。为什么不?如果您要求scanf() 扫描一个整数,它会抓取所有连续的十进制数字(0-9),直到没有一个。小限定符“连续”很可能是您的问题的根源:带有小数部分的浮点数有一个小数点,这就是 scanf() 假定您想要的整数结束的点。检查:
$ ./stackoverflow_003
Enter an integer: .123
Something went wrong within scanf(): wrong number of objects read
你是怎么知道的? @weather-vane 提供了多种方法之一:检查整数之后的下一个字符是否是句点(或您选择的另一个小数分隔符):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int x, i, scanf_return;
char c = -1;
printf("Enter an integer: ");
/* Reset "errno". Not necessary here, just in case. */
errno = 0;
/* scanf() returns a value in case of an error */
scanf_return = scanf("%d%c", &x, &c);
/*
* scanf() returns "EOF" if it didn't find all what you wanted or
* and error happened.
* It sets "errno" to the value of the actual error. See manpage
* for all of the details.
*/
if (scanf_return == EOF) {
/*
* The error is connected to the stream, so we can differ between
* an error within scanf() and and error with the input stream
* (here: stdin)
*/
if (ferror(stdin)) {
fprintf(stderr, "Something went wrong while reading stdin: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
/* e.g. a conversion error, a float instead of an integer, letters
instead of a decimal number */
fprintf(stderr, "Something went wrong within scanf()\n");
exit(EXIT_FAILURE);
}
}
/*
* If no error occurred, the return holds the number of objects
* scanf() was able to read. We can use this information now.
* If there is a period (actually any character) after the integer
* it returns 2 (assuming no error happened, of course)
*/
/* If no integer given, the following character ("%c") gets ignored. */
if (scanf_return == 0) {
fprintf(stderr, "Something went wrong within scanf(): no objects read.\n");
exit(EXIT_FAILURE);
}
/* Found two objects, check second one which is the character. */
if (scanf_return == 2) {
if (c == '.') {
fprintf(stderr, "Floating point numbers are not allowed.\n");
exit(EXIT_FAILURE);
}
}
if (x <= 1) {
fprintf(stderr, "Input must be larger than 1!\n");
exit(EXIT_FAILURE);
}
printf("The prime factorization of %d is ", x);
/* No need for that test, x is already larger than one at this point. */
/* if (x > 1) { */
while (x%2 == 0) {
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2) {
while (x%i == 0) {
printf("%d ",i);
x = x / i;
}
}
/* } */
/* Make it pretty. */
putchar('\n');
exit(EXIT_SUCCESS);
}
检查:
$ ./stackoverflow_003
Enter an integer: 123
The prime factorization of 123 is 3 41
$ ./stackoverflow_003
Enter an integer: 123.123
Floating point numbers are not allowed.
$ ./stackoverflow_003
Enter an integer: .123
Something went wrong within scanf(): no objects read.
对我来说已经足够好了。有一个小错误:
$ ./stackoverflow_003
Enter an integer: 123.
Floating point numbers are not allowed
但我想我可以把它留给亲爱的读者作为练习。