对于我的程序,我必须确保用户只输入一个正整数。例如,如果用户输入12hi,则不应运行程序并打印到std错误。我不太清楚如何实现这个。
int main(int argc, char *argv[])
{
if(atoi(argv[1]) < 1)
{
cerr << "ERROR!"<< endl;
return 1;
}
return 0;
}
答案 0 :(得分:4)
将其传递给std::istringstream
并确保处理完所有数据:
if (a_argc > 1)
{
std::istringstream in(a_argv[1]);
int i;
if (in >> i && in.eof())
{
std::cout << "Valid integer\n";
}
}
请参阅http://ideone.com/8bEYJq的在线演示。
答案 1 :(得分:1)
好的,我修改了答案。 sscanf没有表现出我的想法,strtol提供了非常便携的最佳C类解决方案。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
for (int i=1; i < argc; i++){
char* end;
long val = strtol(argv[i], &end, 10);
if (argc >= 2 && !end[0] && val >= 0){
printf("%s is valid\n", argv[i]);
} else {
printf("%s is invalid\n", argv[i]);
}
}
return 0;
}
示例输出: ./a.out 10 -1 32 1000 f -12347 +4 --10 10rubbish
10 is valid
-1 is valid
32 is valid
1000 is valid
f is invalid
-12347 is valid
+4 is invalid
--10 is invalid
10rubbish is invalid
这是有效的,因为strtol会将参数转换为long int。然后如果end [0]不在字符串的末尾那么它将是非零意味着它会为10rubbish抛出一个错误但是对于像10这样的值是可以的。那么当然我们只想要正整数而且我已经包含该集合中的值0。
atoi()本身并不够好,因为失败会返回零。 0可能是有效的输入。
sscanf()本身也不够好,因为它会成功转换10rubbish之类的字符串并返回值10.
我意识到op只想要argv [1],这个答案会扫描所有提供的args,只是为了显示许多有效和无效条目的输出。
答案 2 :(得分:1)
由于您显然不反对使用标准C库, 功能
long strtol (const char* str, char** endptr, int base)
来自<cstdlib>
的足以确保。{1}}
commandline参数是一个(长)整数,带有一个可选项
“ - ”或“+”前缀,仅此而已。你只需要
检查char *
存储在endptr
的返回地址'\ 0',
它告诉你函数已经消耗了整个参数。
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
if (argc < 2) {
return 1;
}
char * endp;
long i = strtol(argv[1],&endp,10);
if (!*endp) {
cout << "The value of \"" << argv[1] << "\" is " << i << endl;
return 0;
}
cerr << "\"" << argv[1] << "\" is not an integer" << endl;
return 1;
}
以后 ......或者为Steve Jessop的评论提供服务:
#include <cstdlib>
#include <iostream>
#include <climits>
using namespace std;
int main(int argc, char *argv[])
{
if (argc < 2) {
return 1;
}
char * endp;
long i = strtol(argv[1],&endp,10);
if (*endp) {
cerr << "\"" << argv[1] << "\" is not an integer :(" << endl;
return 1;
}
if (endp == argv[1]) {
cerr << "Empty string passed :(" << endl;
return 1;
}
if (i < 0) {
cerr << "Negative " << i << " passed :(" << endl;
return 1;
}
if (i <= INT_MAX) {
cout << "Non-negative int " << i << " passed :)" << endl;
} else {
cout << "Non-negative long " << i << " passed :)" << endl;
}
return 0;
}
包装函数将是为了这种程度的歧视。那里
仍然是非常极端的情况,即ULONG_MAX
的输入将被接受
为LONG_MAX
。
答案 3 :(得分:0)
您可以尝试检查argv[1]
中的所有字符是否都是数字(可能带有前导减号)。可以使用标准库函数isdigit()
执行检查。
http://www.cplusplus.com/reference/cctype/isdigit/
基于OP实际代码的完整解决方案(也可在http://codepad.org/SUzcfZYp获得):
#include <stdio.h> // printf()
#include <stdlib.h> // atoi()
#include <ctype.h> // isdigit()
int main(int argc, char *argv[])
{
if( argc != 2 ) {
return 0;
}
char * pWord = argv[ 1 ];
char c = 0;
for( int i = 0; c = pWord[ i ], c ; ++i ) {
if( ! isdigit( c ) ) {
return 0;
}
}
int argvNum = atoi( argv[ 1 ] );
printf( "argc = %d, argv[ 1 ] = %s, argvNum = %d\n",
argc, argv[ 1 ], argvNum );
}
答案 4 :(得分:-1)
我是C ++的新手,所以如果这是错误的话请不要激怒我,但是你不能抛出异常并让用户重新纠正输入吗?
我已经学会了一些处理错误的方法:
1.如果/ ELSE #include
int main(int argc, int **argv) {
if (!isdigit(argv[1])) {
// handle code if it's not a digit.
return 0;
}
}
这可能是确保
的最简单方法2.ASSERT #include
int main(int argc, int *argv[]) {
assert(isdigit(argv[1]));
}
3.THROW #include
using namespace std;
class Except {};
int main(int argc, int **argv) {
try {
isdigit(argv[1]);
throw Except();
// this code will not be executed
// if argv[1] is not a digit
}
catch (Except) {
cout << "argv[1] is not a digit.";
// handle exception or rethrow
}
}
绝对值得注意的是,抛出异常将创建堆栈跟踪,并且抛出的异常和捕获异常的块之间的所有代码都不会被执行。