2

私のプログラムでは、ユーザーが正の整数のみを入力するようにする必要があります。たとえば、ユーザーが 12hi を入力した場合、プログラムを実行して std エラーに出力するべきではありません。これを実装する方法がよくわかりません。

int main(int argc, char *argv[])   
{ 
    if(atoi(argv[1]) < 1)
    {
        cerr << "ERROR!"<< endl;
        return 1;
    }
    return 0;
}
4

5 に答える 5

6

に渡し、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でオンライン デモを参照してください。

于 2013-04-22T21:35:34.187 に答える
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] のみを必要とすることに気づきました。この回答は、提供されたすべての引数をスキャンして、多くの有効なエントリと無効なエントリの出力を表示します。

于 2013-04-22T21:33:58.820 に答える
1

あなたは明らかに標準 C ライブラリの使用に反対していないので、関数

long strtol (const char* str, char** endptr, int base)

from<cstdlib>コマンドライン引数がオプションの「-」または「+」プレフィックスが付いた(長い)整数であり、それ以上のものではないことを確認するのに十分です。戻りアドレス '\0' にchar *格納されていることを確認する必要があるだけです。これは、関数が引数全体を消費したことを示しています。endptr

#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ます。

于 2013-04-22T22:34:09.520 に答える
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 );
}
于 2013-04-22T21:24:37.407 に答える