7

C ではchar **、一連の文字列を保持するために a を使用しています。

これが私のコードです:

char ** c;
//now to fill c with data ????

//cannot change:
printf ("%*s%s", 0, "", *c);
while (*++w)
    printf (" %s", *c);

データの入力方法がわかりませんc。適切な方法は何ですか?外部関数にあるため、3 つの印刷行を変更できません。

4

3 に答える 3

7

ここでは用語が重要だと思います。はchar **一連の文字列をまったく「保持」しません(Cよりも高水準言語のコンテナオブジェクトとは異なります)。変数cは文字へのポインタへの単なるポインタであり、その文字はヌル文字で終了する文字列の最初の文字になります。

この考え方は、解決策に直接つながります。cが文字へのポインタへのポインタである場合、それは、文字列の配列を実際に保持するためのメモリを割り当てる必要があることを意味します。

コメントとして投稿された@DB_Monkeyのソリューションはこれを実行しようとしますが、c[0] = "cat"「cat」をにコピーするようなコードを意味するため、正しくc[0]ありません。割り当ては文字列ではなくポインタに適用されます。より良い方法は次のとおりです。

int rows = 3;
char **c = calloc (rows,sizeof(char*));
c[0] = "cat";
c[1] = "dog";
c[2] = "mouse";

これは、各文字列の明示的なヌル終了を表示する必要がないことも示しています。

于 2013-01-28T03:11:56.250 に答える
4

あなたのchar**は、実際には、その番号が有効な文字のアドレスである番号のアドレスであると考える番号です。

簡単に言えば:

// I am a number that has undefined value, but I pretend to point to a character.
char *myCharPointer;
// | The statement below will access arbitrary memory
// |   (which will cause a crash if this memory is not allowed to be accessed).
char myChar = *myCharPointer; 

このポインタを利用するには、初期化する必要があります。

char *myCharPointer = (char *)malloc(10 * sizeof(char));

これで、配列を処理するのと同じ方法でこのポインターを使用できます。必要に応じて、適切なポインター演算を使用できます。

mallocは「配列」内のすべての値を0に設定しないことに注意してください。それらの値は、デフォルトでは未定義です。

やりたいことをするためには、次のことをしなければなりません。

// I can store 10 "strings"
char **myArrayOfStrings = (char **)malloc(10 * sizeof(char *));
char *str0 = "Hello, world0";
char *str1 = "Hello, World1";
char *str2 = "Hello, World2";
char *str3 = "Hello, world3";
char *str4 = "Hello, world4";
char *str5 = "Hello, world5";
char *str6 = "Hello, world6";
char *str7 = "Hello, world7";
char *str8 = "Hello, world8";
char *str9 = "Hello, world9";
myArrayOfStrings[0] = str0;
myArrayOfStrings[1] = str1;
myArrayOfStrings[2] = str2;
myArrayOfStrings[3] = str3;
myArrayOfStrings[4] = str4;
myArrayOfStrings[5] = str5;
myArrayOfStrings[6] = str6;
myArrayOfStrings[7] = str7;
myArrayOfStrings[8] = str8;
myArrayOfStrings[9] = str9;
// the above is the same as
// *(myArrayOfStrings + 9) = str9

同じ長さの文字列を使用する必要はありません。str[0..9]が実際には、これらの文字列の最初の文字がメモリ内にあるアドレスを格納する数値であるとします。

str0 = (char *)&9993039;
str1 = (char *)&9993089;

myArrayOfStringsは、実際には、特に最初の文字列の場所のアドレスを格納する数値でもあります。myArrayOfStrings = (char **)&str0;

明らかに、これは私が示したように明示的には行いませんが、実行時に問題なく実行できます。ユーザーからの文字列をバッファーに格納し、リストに追加して、不足しないようにします。スペース(それを回避するためのテクニックがあります)。

うまくいけば、これが役に立った。

于 2013-01-28T03:39:40.433 に答える
2

あなたが持っているのは、へのポインタへのポインタcharです。これは、別のポインターである可能性がある (より多くの必要がある) 変数を参照するのに十分なスペースを確保したことを意味します。これにより、それらの文字用のスペースを予約する前に実際の文字を保存することはできません。

cしたがって、必要に応じて変数に文字または文字列を含めることができるように、2 段階のメモリ割り当てが必要です。

これは、mallocsizeof、およびforループで行います。

最初に、文字列のベクトルにスペースを割り当てる必要があります (C では、文字のベクトルにすぎないため、実際には、文字のベクトルへのポインターのベクトルにスペースを割り当てることになります)。

char **c = malloc(NUMBER_OF_STRINGS * sizeof(char*));

これにより、c 変数が を指すようになります。これはNUMBER_OF_STRINGS整数であり、char へのポインターです。

これで、文字列の最大サイズを選択して必要なすべてのスペースを割り当てるか、新しい文字列を配置する必要があるたびにそれを行うことができます。

/*All the space with MAX_STR= maximum string size*/
 for(i=0;i<NUMBER_OF_STRINGS;i++){
    c[i] = malloc(MAX_STR * sizeof(char));
 }

そして、文字列をコピーして、サイズc[i]のある文字列を保持したり、文字列i から文字 j を取得したりすることで、文字列からMAX_STR実際の文字列を取得したりできます。charc[i][j]

/*Alloc when you have the string*/
  while(fgets(buff, BUFFSIZE, stdin) != NULL){   //This is just an example of an input reading from the keyboard
       c[i] = malloc(strlen(buff) * sizeof(char));
       i++;
  }

関数を使用しstrlenてサイズを取得しましたbuff(バフは単なる文字列です)。文字列操作関数については、string.hを確認してください。

これで問題が解決することを願っています。もう1つ、各mallocの後に、プロセスの仮想メモリが不足したときに発生するmalloc返されないかどうかを確認する必要があります。NULL

お役に立てれば。

于 2013-01-28T03:35:09.053 に答える