scanf("%f", &num);
我必须检查这是否是一个有效的浮点变量,如果它有@
或!
或之类的符号则停止执行%
。
建议?
检查来自的返回值scanf()
。它将返回成功扫描输入的数量 - 在您的情况下应该是1
。如果不等于 1,则可能是 -1,表示“文件结束”或 0,表示“输入无效”。
scanf
不是你的朋友,在这里。即使您检查结果以确保您成功读取了一个完整的参数,但这并不能真正保证输入在有意义的意义上是有效的。
给定输入,例如:
1!!!1!oneone!
解析将在%f
读取第一个后停止(但成功)1
,并将读取指针留在下一个!
。这可能不是您认为的“有效输入”。
在这种情况下,请尝试:
if (scanf("%f%c", &f, &c) == 2 && isspace(c))
/* success */
但是,这将接受以下内容:
1 oneoneonespace!bang
如果同一行上的任何内容都被视为垃圾,那么它会变得很困难,因为scanf
不区分空格和换行符。也许尝试这样的事情:
char buffer[1024];
if (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
if (sscanf(buffer, "%f %c", &f, &c) == 1)
/* success */
}
在 scanf 中使用 %f 说明符不会扫描任何其他内容,如果没有指定浮点数,则不会读取任何内容。您应该检查 scanf 的返回值。
有几个定义的返回值:
EOF = -1
invalid input = 0
valid = >0
将您的输入读取为文本,然后使用strtod
库函数将其转换;允许您检查输入是否包含任何无效字符:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
...
char buf=[81];
double result = 0.0;
...
if ( fgets( buf, sizeof buf, stdin ) != NULL )
{
char *chk;
double tmp = strtod( buf, &chk );
if ( isspace( *chk ) || *chk == 0 )
result = tmp;
else
fprintf( stderr, "%s is not a valid floating-point number\n", buf );
}
调用 后strtod
,变量chk
将指向字符串中不属于有效浮点常量的第一个字符。如果这个字符是空格或 0,那么你很好;否则你有错误的输入。
此方法的优势scanf
在于,如果您的输入仅以一个有效字符(例如"1blkjhsdf"
)开头,它将转换并分配"1"
并返回 1,表示转换成功,即使您可能想要拒绝该输入。它还消耗整个输入字符串(假设输入缓冲区足够大),因此它不会在输入流中留下任何垃圾来破坏下一次读取。
scanf
当您知道您的输入格式正确时,这是一个很好的工具;否则,最好使用上述方法。
您可以从中检查返回值scanf()
。如果您查看此页面:
返回值
成功时,该函数返回参数列表中成功填充的项目数。由于匹配失败、读取错误或到达文件末尾,此计数可以与预期的项目数匹配或更少(甚至为零)。
所以像:
if ( scanf( "%f", &num ) <= 0 )
{
// Stop the execution
}
// Continue
会做你想做的。
您不能在 中检查您的两个条件scanf
。我建议将整个输入读入一个字符串,寻找特殊字符。一旦此测试通过,请尝试通过将其重新处理为字符串sscanf
。要搜索特殊字符,strpbrk
在string.h
char* specials = "%@!";
char* buffer[SOME_SIZE];
double value;
int err;
scanf("%s", buffer);
if( strpbrk(buffer, specials) ) return SPECIAL_FOUND;
err = sscanf(buffer, "%f", &value);
if(err <= 0) return NOT_VALID_INPUT; //NOTE: there should probably be not EOF case
// process your value
注意:我没有检查代码,这是一个粗略的想法。