したがって、メイン関数に「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ターミナルで何かですか?
上の図では、数字2、4、5、3をもう一度印刷したいのですが、印刷されません。
ありがとう。
物事をステップごとに説明しましょう。まず、次のようなものを呼び出してプログラムを呼び出すと...
./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]);
意味:「i
のargv
th要素の最初の文字を出力します」。なぜこれが間違っているのでしょうか?まず、char
を出力し、printf
にそれが文字列であることを伝えています。 これには未定義の動作があります。次に、i
の最初のargv
th要素を繰り返し処理します。これは、最初の「引数ではない」要素がミックスに含まれ、最後の引数は含まれないことを意味します。それを解決するには、次のように書きます...
for(i = 1; i < argc; i++)
意味:「1
からi
までの範囲の各argc
」。
printf("%s", argv[i]);
意味:「i
のargv
th要素をstdout
に出力します。
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 *
のタイプが必要です。
編集した質問で、主な問題を修正しました。プロンプトが次のようになっていることに注意してください
./mygrep245YourName@ubuntu:~/test$
ここに ./mygrep245
は、印刷後の出力です"5\n"
。改行を印刷するのを忘れたため、すべての出力と後続のシェル出力がそのまま連結されました。最後の引数3
は、i<argc-1
の代わりに i<argc
またはi<=argc-1
ループ状態。
_char *argv[]
_は、char
へのポインターへのポインターです。関数引数の配列は、配列の要素を指すポインターに自動的に変換されるためです。
誤ったタイプのデータをprintf()
に渡すことで未定義の動作を呼び出しました:_%s
_は_char*
_を期待しますが、char
(int
可変数引数の場合)。
余分な_*
_ 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
_を使用することもできます。最後の引数を印刷しないのはなぜですか?
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;
}