web-dev-qa-db-ja.com

Cのメイン関数からargv引数を出力するには?

したがって、メイン関数に「argc」と「argv」という2つの引数を指定できることを知りました。ただし、argvの内容を理解することはできません:int main(int argc, char* argv[]);

Argvは文字の配列ですか?それとも、文字を指すポインターの配列ですか?いずれにしても、ユーザーがこのプログラムに渡す引数を印刷する方法を探しています。これは私が書いたコードですが、いわばargvの出力ではありません。何が問題なのですか?このコードを間違っているのは、argvを理解しているからだと思います。

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",*argv[i]);
    }
    return 0;
}

回答から得た提案の後、次のようにコードを修正しました。

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=1;i<argc;i++)
    {
        printf("%s",argv[i]);
    }
    return 0;
}

また、Windows 8.1 pc上のVMWareでUbuntu Linuxを使用しています。これは私が得ている出力です。 argcを出力するだけで、その後は何もしません。どうしたの?それは私がそれをコンパイルする方法ですか、Linuxターミナルで何かですか?

The snapshot of my terminal

上の図では、数字2、4、5、3をもう一度印刷したいのですが、印刷されません。

ありがとう。

11
user5987642

物事をステップごとに説明しましょう。まず、次のようなものを呼び出してプログラムを呼び出すと...

./my-program arg0 arg1 arg2

一連の3つの引数を渡していますよね?そして、各引数は文字列ですよね?これで、main関数は、C標準で指定されている2つのプロトタイプのいずれかを持つことができます...

int main(); // Let's not worry about this for now
int main(int argc, char **argv);

mainは、指定した引数を処理できるという考え方です。 argcは引数の数を提供します。お気づきのように、3つの引数を渡す間、argcは4です!これは、最初の引数が他のすべての./my-programの前に渡され、プログラムが自分自身を認識できるようにするために発生します。

さて、char **argvはどういう意味ですか? X*という形式の何かはXへのポインターですよね?したがって、char *charへのポインターであり、char **charへのポインターへのポインターです。 Cでは、文字列は単にcharのゼロで終わる配列であり、配列はポインターに「分解」できます。つまり、argvは文字列の配列であり、最初のargv[0]はプログラムの名前です。

現在、C標準では、mainの「互換性のある」プロトタイプを作成できます。たとえば、これらのいずれかを書くことができます...

int main(int argc, const char *const argv[]);
int main(int argc, const char *argv[])
int main(int argc, const char **argv);
int main(int argc, const char *const *const argv);

argvは文字列の配列であり、neverは元のmainとして文字列を変更する必要があることだけを理解する必要はありません。プロトタイプはあなたを信頼しているようです。さて、引数がargv[1]で始まることを知って、あなたのコード...

for(i=0;i<argc-1;i++)

意味:「0〜argc - 1の範囲の各i」。

    printf("%s",*argv[i]);

意味:「iargvth要素の最初の文字を出力します」。なぜこれが間違っているのでしょうか?まず、charを出力し、printfにそれが文字列であることを伝えています。 これには未定義の動作があります。次に、iの最初のargvth要素を繰り返し処理します。これは、最初の「引数ではない」要素がミックスに含まれ、最後の引数は含まれないことを意味します。それを解決するには、次のように書きます...

for(i = 1; i < argc; i++)

意味:「1からiまでの範囲の各argc」。

    printf("%s", argv[i]);

意味:「iargvth要素をstdoutに出力します。

11
3442

argvは文字の配列ですか?それとも、文字を指すポインターの配列ですか?

argvは、charへのポインターへのポインターです。引数のリストがコマンドラインを介して渡されると、charポインターの配列が作成され、これらの各ポインターはこれらの各引数を指し、プログラム名とともに文字列の形式で格納されます。 argvは、このchar *配列の最初のポインターを指します。したがって、argv[i]charへのポインターです。

                           +--------------------------+
              +----+  +--> | argument 1 (program name)|
argv[0]+----> |    |  |    +--------------------------+
              |  +----+
              +----|       +--------------------------+
              |  +-------> |       argument 2         |
              |    |       +--------------------------+
              +----+
              |  +----+    +--------------------------+
              |    |  +--> |       argument 3         |
              +----+       +--------------------------+
           "char *" array

変更する必要があります

printf("%s",*argv[i]);  

printf("%s",argv[i]);  

*argv[i]char型です。 %sにはchar *のタイプが必要です。

5
haccks

編集した質問で、主な問題を修正しました。プロンプトが次のようになっていることに注意してください

./mygrep245YourName@ubuntu:~/test$

ここに ./mygrep245は、印刷後の出力です"5\n"。改行を印刷するのを忘れたため、すべての出力と後続のシェル出力がそのまま連結されました。最後の引数3は、i<argc-1 の代わりに i<argcまたはi<=argc-1ループ状態。

2
Ruslan

_char *argv[]_は、charへのポインターへのポインターです。関数引数の配列は、配列の要素を指すポインターに自動的に変換されるためです。

誤ったタイプのデータをprintf()に渡すことで未定義の動作を呼び出しました:_%s_は_char*_を期待しますが、charint可変数引数の場合)。

余分な_*_ oを削除して、ポインターを逆参照します。

_#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",argv[i]);
    }
    return 0;
}
_

また、_i<argc_の代わりに__i<argc-1_を使用することもできます。最後の引数を印刷しないのはなぜですか?

1
MikeCAT

document を参照できます:

ご覧のとおり、mainには引数があります。変数argcの名前は「引数カウント」を表します。 argcには、プログラムに渡された引数の数が含まれています。変数argvの名前は「引数ベクトル」を表します。ベクトルは1次元配列であり、argvは文字列の1次元配列です。各文字列は、プログラムに渡された引数の1つです。

印刷する必要がある場合は、*を削除してこれを試してください。

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",argv[i]);   //remove * from here
    }
    return 0;
}
0
Rahul Tripathi