2016-05-20 11 views
-1

私は入力行を取り、コマンドライン引数のような入力行を解析するプログラムを書いていますが、これは通常のコマンドラインプログラムによって解析されます。私はchar * args []と呼ばれる変数を使用して、解析された文字列、構文解析、および変数を、char * argv []で使用される通常のコマンドラインプログラムとよく似ています。私はこのプログラムを使って作業していましたが、引数をループしても、それぞれをchar * args []に追加しても、最終的な結果は変数char * args []に格納される最後の "引数"その配列。ここで char * array []文字列配列を使用する正しい方法は何ですか?

は、コードの...ここで
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

typedef int bool; 
#define true 1 
#define false 0 

int main(int argc, char *argv[]) 
{ 
    char input[200]; 
    printf(">"); 
    gets(input); 
    int i=0; 
    int t=0; 
    int l=0; 
    bool space=false; 
    char arr[50]; 
    char *str; 
    char *args[10]; 
    memset(&arr,0,sizeof(arr)); 
    memset(&str,0,sizeof(str)); 
    memset(&args,0,sizeof(args)); 
    for(i;i<sizeof(input);i++) 
    { 
    printf("l=%d,t=%d\n",l,t); 
    if(input[i]=='\0') 
     break; 
    if(input[i]==' ') 
    { 
     if(!space) 
     { 
     printf("arr : %s...\n",arr); 
     str=arr; 
     printf("str : %s...\n",str); 
     args[l]=str; 
     printf("args[%d] : %s...\n",l,args[l]); 
     memset(&arr,0,sizeof(arr)); 
     memset(&str,0,sizeof(str)); 
     t=0; 
     l++; 
     space=true; 
     } 
    } 
    else 
    { 
     arr[t]=input[i]; 
     space=false; 
     t++; 
    } 
    } 
    printf("arr : %s...\n",arr); 
    str=arr; 
    printf("str : %s...\n",str); 
    args[l]=str; 
    printf("args[%d] : %s...\n",l,args[l]); 

    printf("\n"); 

    //Shows that all of char *args[] is the last string to be set... 
    int j=0; 
    for(j;j<=l;j++) 
    { 
    printf("args[%d] = %s...\n",j,args[j]); 
    } 
    //hello and goodbye are set and output below like a normal char *args[] 
    //array should... 
    args[0] = "hello"; 
    args[1] = "goodbye"; 
    j=0; 
    for(j;j<=l;j++) 
    { 
    printf("args[%d] = %s...\n",j,args[j]); 
    } 
    return 0; 
} 

は、いくつかのサンプル出力...

C:\Users\Auguest\Desktop>basecalc.exe 
>asdf hsdf ewrr ewr 
l=0,t=0 
l=0,t=1 
l=0,t=2 
l=0,t=3 
l=0,t=4 
arr : asdf... 
str : asdf... 
args[0] : asdf... 
l=1,t=0 
l=1,t=1 
l=1,t=2 
l=1,t=3 
l=1,t=4 
arr : hsdf... 
str : hsdf... 
args[1] : hsdf... 
l=2,t=0 
l=2,t=1 
l=2,t=2 
l=2,t=3 
l=2,t=4 
arr : ewrr... 
str : ewrr... 
args[2] : ewrr... 
l=3,t=0 
l=3,t=1 
l=3,t=2 
l=3,t=3 
arr : ewr... 
str : ewr... 
args[3] : ewr... 

args[0] = ewr... 
args[1] = ewr... 
args[2] = ewr... 
args[3] = ewr... 
args[0] = hello... 
args[1] = goodbye... 
args[2] = ewr... 
args[3] = ewr... 

C:\Users\August\Desktop> 

私はWindows XP上のMinGWのgcc 4.9.3を使用していますが...ある

私はchar * args []を正しく使用していないと感じています。この配列をループして各エントリに値を割り当てる正しい方法は何ですか? char * args []を一般的に使用する正しい方法は何ですか?私のプログラムで何か他のものがあれば、そう言えば、インターネットが聞きたいと思います。引数の各エントリは、[]引数[においてので、ポインタSTRにエントリのすべてを設定されている

if(!space) 
    { 
    printf("arr : %s...\n",arr); 
    str=arr; 
    printf("str : %s...\n",str); 
    args[l]=str; 
    printf("args[%d] : %s...\n",l,args[l]); 
    memset(&arr,0,sizeof(arr)); 
    memset(&str,0,sizeof(str)); 
    t=0; 
    l++; 
    space=true; 
    } 

私はそれを考え出し

+0

申し訳ありませんが、これは実際の混乱であり、迅速な回答よりも多くのTLCを使用します。私はCのポインタ、文字列、およびメモリの割り当てを読むことをお勧めします。また、sizeof()は静的なコンパイル時の演算子で、あなたの場合は常に200を返します。 strlen()を使うつもりだと思う。 – OldProgrammer

+0

マイナーコメント: 'l'のような変数名は、多くのフォントで' 1'と非常によく似ているのですばらしいものではありません。 –

+0

また、 'strtok()'のようなものを使って、文字列をパースすることもできます。 –

答えて

0

問題は、現在処理している文字列のコピーを保持する配列(arr [])が1つしかないことです。スペースを使用すると、args [l]の次のポインタを指すように設定しますarr []の現在の内容次回のループでは、arr []の内容を次の文字列で置き換え、args [0]からargs [l-1]までがすべてarr []の単一コピーを指しているので、あなたがarr []にコピーした最後の内容のみ。

あなたがしたいことをやるためにはもっとエレガントな方法がありますが、最初に試してみるのが最も簡単です(あなたがすでに書いたコードを見てみると) 'arr []'をあなたのハードコーディングされた定数から2次元配列を作成するには、 'arr [10] [50]'を使用し、arr [] []を入力するときは 'arr [l] [t] = input [i]; args [l]を代入するときは、 'args [l] = &(arr [l] [0]);'を使用します。

ポインタや配列などがもっとうまくいくようになったら、コードを単純化して安全にする(バッファオーバーフローを避けるなど)、不要なコピーを減らすことができます(つまり、args [l ]は、最初に別の配列にコピーするのではなく、 'input []'配列内の各文字列の先頭を直接指すようにします。

希望のトラックに乗るのに役立ちます。.....

+0

多くの感謝!ポインタの使用がバッファオーバーフローを回避するのに役立つことは決してありませんでした。私はgets()が安全ではないことを知っています。特に、固定次元の配列が入力を受け取っているのですが、私はプログラムを使用する唯一の人ですので、私はそれをハックするしかないと思います。 ;)p.s.ポインタがバッファオーバーフローを避ける方法についてさらに読んで私を正しい方向に導くことができますか?もう一度ありがとう! – August

+0

入力バッファのサイズが200であることを暗示していましたが、arr []配列のサイズは50であるため、input []配列の文字列の1つが50バイトより大きい場合は、arr [ ]配列。これを避ける1つの方法は、input []配列の ''文字をNULL終端文字( '\ 0')で置き換えることです。そして、args [l]は入力内の各文字列の開始点を指し示すようにします[ ]配列そのもの。これはあなたの潜在的なバッファオーバーフローをコード内で回避します..... –

0

...このブロック内

... ]配列は同じポインタstrに設定され、arr変数の最新の状態を指します。

char * args []を使用する代わりに、args [] []を使用する必要があります。注意:args [] [] 2次元配列の寸法は、コンパイル時に必要です。

char * strcat(char * dest、const char * src);

各args [x]エントリをarr変数の現在の状態に設定する必要があります。

+0

'memset(&arr、0、sizeof(arr));'構文を再確認することができます。 'arr'と' str'がすでに配列(したがって*ポインタ*)である場合、あなたの構文は正しくなく、警告を生成するはずです。 –

関連する問題