web-dev-qa-db-ja.com

Cで整数コマンドライン引数を解析する方法は?

ユーザーに2つのパラメータを渡すか、空白のままにしてほしい。例えば:

_./program 50 50
_

または

_./program
_

int main(int argc, char *argv[])を使用しようとしたとき、最初に行ったのは_char *argv[]_を_int *argv[]_に変更することでしたが、機能しませんでした。私が欲しいのはユーザーからですから100までの2つの整数を入力するため。したがって、2つの整数でない場合はエラーになります。

(C#でプログラミングするために使用したように)型でエラーを出すと考えていましたが、入力した内容が何であれ、argv [1]は常に 'char'型になります。

だから私がやったことは

_for (int i = 0; i <= 100; i++) {
    //printf("%d", i);
    if (argv[1] == i) {
        argcheck++;
        printf("1st one %d\n", i);
    }
    else if (argv[2] == i) {
        argcheck++;
        printf("2nd one %d\n", i);
    }
_

これも機能しません。また、コンパイル時に警告が表示されますが、たとえばargvatoi(argv[1])で変更すると、Segmentation fault(core dumped)エラー。

この問題を解決する簡単な方法が必要です。

編集:

したがって、atoi()で修正しました。セグメンテーションエラーが発生したのは、パラメーターがないときにnull値で試行していたためです。だから私は余分な条件を追加することで修正しました。しかし、今問題は、値が

_./program asd asd
_

次に、atoi(argv[1])の出力は0になります。この値を変更する方法はありますか?

16
Sarp Kaya

atoi()を使用しないでください。また、strtol()を使用しないでください。 atoi()にはエラーチェックがありません(ご存知のとおり!)。また、strtol()はグローバルerrno変数を使用してエラーチェックする必要があります。つまり、errnoを0に設定してから呼び出す必要があります。 strtol()、次にerrnoでエラーを再度確認します。 より良い方法は、sscanf()を使用することです。これにより、整数だけでなく、文字列から任意のプリミティブ型を解析でき、(16進数のような)ファンシーな形式を読み取ることができます。

たとえば、文字列から整数「1435」を解析するには:

if (sscanf (argv[1], "%i", &intvar) != 1) {
    fprintf(stderr, "error - not an integer");
}

文字列から単一の文字「Z」を解析するには

if (sscanf (argv[1], "%c", &charvar)!=1) {
    fprintf(stderr, "error - not a char");
}

文字列からフロート「3.1459」を解析するには

if (sscanf (argv[1], "%f", &floatvar)!=1) {
    fprintf(stderr, "error - not a float");
}

文字列から大きな符号なし16進整数 "0x332561"を解析するには

if (sscanf (argv[1], "%xu", &uintvar)!=1) {
    fprintf(stderr, "error - not a hex integer");
}

それ以上のエラー処理が必要な場合は、正規表現ライブラリを使用してください。

29
Lelanthran

これは行います:

int main(int argc, char*argv[])
{
   long a,b;
   if (argc > 2) 
   {
      a = strtol(argv[1], NULL, 0);
      b = strtol(argv[2], NULL, 0);
      printf("%ld %ld", a,b);
   }
   return 0;
}
14
P.P

引数は常に文字列として渡され、main()のプロトタイプを変更することはできません。オペレーティングシステムと周囲の機械は常に文字列を渡し、変更したことを理解できません。

使用する必要があります。 strtol()は、文字列を整数に変換します。

5
unwind

あなたはかどうかを確認したい

  1. 0または2の引数を受け取りました
  2. 受け取った2つの値は0から100の間です
  3. 受け取った引数は文字列ではありません。文字列が来た場合、sscanfは0を返します。

以下のロジックはあなたを助けます

int main(int argc, char *argv[])
{
    int no1 = 0, no2 = 0, ret = 0;

    if ((argc != 0) && (argc != 2)) 
    {
        return 0;
    }

    if (2 == argc)
    {
        ret = sscanf(argv[1], "%d", &no1);
        if (ret != 1)return 0;
        ret = sscanf(argv[2], "%d", &no2);
        if (ret != 1)return 0;          

        if ((no1 < 0) || (no1 >100)) return 0;
        if ((no2 < 0) || (no2 >100)) return 0;          
    }

    //now do your stuff
}
2
rashok

stillatoiを使用できます。最初に引数が数値かどうかを確認してください;)
btw pplはgoto isevilと伝えますが、 '通常、賢明ではない人によって洗脳されます"goto is bad""goto is evil""goto is悪魔」インターネット上で詳細に説明することなく破棄されただけのステートメント。
はい、spaggethiコードは扱いにくいです。そして、その文脈における後藤は、それが機能を置き換えた時代からのものです...

    int r, n, I;
    for (I = 0; I < argc; ++I)
    {
      n = 0;
      do
        if ( !((argv + I) [n] >= '0' && (argv + I) [n] <= '9') )
        {
          err:
            fprintf(stderr,"ONLY INTEGERS 0-100 ALLOWED AS ARGUMENTS!\n");
            return 1;
        }
      while ((argv + I) [++n] != '\0')
      r = atoi(argv[I]);
      if (r > 100)
        goto err;
    }
0
Anonymous

あなたがそう無実に行ったことは、Cでは大失敗です。何があっても、引数として文字列または文字を取り、後でそれらを使って好きなことができるようになります。 strtolを使用してそれらを整数に変更するか、それらを文字列にして、48 to 57の範囲内の文字列の各文字をチェックします。これらはchar 0 to 9の10進値であるためです。個人的には、これは良いアイデアではなく、あまり良いコーディング方法ではありません。それらをよりよく変換し、必要な整数範囲をチェックしてください。

0
Abhineet