1

C 文字列の配列を保持する必要があります。今、私はC文字列が単なる文字の配列であることを知っているので、本質的に私が望むのは文字の2次元配列です。保存しようとしている文字列も 6 文字を超えることはありません。私の計画は、50 個の「文字列スロット」で char 配列を初期化し、50 個の文字列に達した場合、配列のメモリを再割り当てして容量を 2 倍にすることです。私は次のような簡単なことを試しました:

int main() {
    char strings[50][6];
    strings[0] = "test";
    printf("The string is: %s", strings[0]);
    return(0);
}

しかし、コンパイルしようとすると、次のエラーが発生します。

test.c: 関数 'main' 内: test.c:3: エラー: 型 'char *' から型 'char[6]' に代入するときの型に互換性がありません test.c:4: 警告: 組み込みの暗黙の宣言に互換性がありません-関数「printf」内</p>

誰かが私を正しい方向に向けることができますか?

4

6 に答える 6

5

strncpy(strings[0], "test", 6);C ライブラリにstrlcpy(). ただし、ストレージのサイズを変更する必要がある場合は、char **with malloc()realloc()およびを使用することをお勧めしますfree()

于 2010-09-16T20:39:31.167 に答える
2

そのように配列を直接割り当てることはできません。あなたの現在のケースでは、次のようなことをする必要があります...

strcpy (strings[0], "test");

ただし、ポインターの配列を使用する方がより慣用的です。K&Rのp111以降をご覧ください。

于 2010-09-16T20:39:31.277 に答える
1

演算子を使用して配列の内容を割り当てることはできません。=まず、配列オブジェクトを代入演算子のターゲットにすることはできません(Online C Standard、ドラフトn1256、セクション6.5.16.1、段落1)。 strings[0]は型の配列オブジェクトであるため、演算子 char [6]のLHSには表示できません。=

次に、配列式がsizeoforまたはaddress-of&演算子のオペランドではなく、別の配列の内容を初期化するために使用される文字列リテラルではない場合、式の型は暗黙的に変換( "decays")されます。 「TのN要素配列」から「Tへのポインタ」。式の値は、配列の最初の要素のアドレスです(セクション6.3.2.1、パラグラフ3)。

文字列リテラル「test」は、静的エクステントを持つcharconst charC ++の)5要素配列です(つまり、そのメモリはプログラムの起動時に割り当てられ、プログラムが終了するまで保持されます)。ただし、式に現れる場合

strings[0] = "test";

その型は「charの5要素配列」から「pointertochar」に変換され、その値は最初の要素のアドレスであるため、最終的には、配列オブジェクトにポインター値を割り当てようとします。互換性のあるタイプではありません。悪いjuju、とにかく配列オブジェクトを割り当てることができないことに加えて。

ある配列の内容を別の配列にコピーする場合は、次のように各配列要素を個別に割り当てる必要があります。

strings[0][0] = 't';
strings[0][1] = 'e';
strings[0][2] = 's';
strings[0][3] = 't';
strings[0][4] = 0;

あるいは

size_t len = strlen("test");
size_t i;
for (i = 0; i < sizeof strings[0] - 1 && i < len; i++)
  strings[0][i] = "test"[i]; // yes, you can subscript a string literal
strings[0][i] = 0;

または、、、、、などmemcpy()のライブラリ関数を使用します。strcpy()strncpy()strcat()sprintf()

strcpy(strings[0], "test");

また

strncpy(strings[0], "test", sizeof strings[0] - 1); // -1 to leave room
                                                    // for 0 terminator
                                                    // if necessary  

また

sprintf(strings[0], "%*s", (int) sizeof strings[0] - 1, "test");

次のように、宣言時に配列の内容を初期化できることに注意してください。

char foo[] = "test";      // foo is implicitly sized to 5 (+1 for 0 terminator)
int  bar[] = {1,2,3,4,5}; // again, size is implied from initializer

float f[3] = {1.0, 2.0, 3.0}; // Initializer cannot contain more items than 
                              // array is sized for

別の回答へのコメントで、strcpy()vsの使用をめぐって陽気な戦争があるようです。strncpy()私の立場は、与えられた状況に適切な方を使用することです。バッファが可能な限り最大の入力を処理するのに十分な大きさであることがわかっている場合は、を使用してstrcpy()ください。そうでない場合は、を使用strncpy()しますが、0ターミネータを手動で追加する必要がある場合があることに注意してください。

于 2010-09-17T15:42:17.697 に答える
1

まず簡単な部分。あなたはする必要があります

#include <stdio.h>

互換性のないprintf警告を取り除きます。これは、標準の printf とは異なるいくつかの関数を作成できるようにするという標準の C の動作方法と関係があります。その関数の暗黙の宣言と、その署名がコンパイラによって (誤って) 推測され、コンパイラがそのことを認識しています。別の printf を定義することはできますが、おそらく実際には意図していませんでした。

さて、より複雑な部分です。C の配列は少し特殊です。は、コンテキストに応じて、ポインタ リテラル (これは に代入できず、 を試行するのと似てい6 = 4;ます) に評価されるか、配列全体に評価されます。通常、それらはポインター リテラルですが、この場合は配列と見なされるため、無効な左辺値 (左辺値、左側にある可能性があるものを意味する)strings[0]ではなく、エラーが発生するのはそのためです。strings[0]=)。いずれにせよ、文字ポインター リテラル ("test" が評価するもの) を配列にコピーすることはできません。ただし、文字列 (char 配列) を宣言する行でこれを行うと、コンパイラはそれを異なる方法で処理するため、混乱が生じる可能性があります。とにかく、どちらかを使用する必要がありますstrcpy「test」を構成する文字をコピーするか、strings[0] を次のように「test」に初期化します。

char strings[50][6] = { "test" };  // only initializes the first member of the array
于 2010-09-16T21:07:02.883 に答える
1

割り当てには strncpy (可能な場合) または strcpy を使用します。

于 2010-09-16T20:40:01.430 に答える
0

あなたが抱えている問題は、コンパイラがステートメントを解釈する方法にありますchar strings[50][6];

6 つの弦charに対して 50 のスロットを備えた配列ではなく、50x6 の次元を持つ 単一の の配列が得られました。charcharchar

ではなくchar strings[50][6];、配列を初期化する方法は次のとおりです(ヒープでこれを行う方法しか知りません、申し訳ありません):

char ** strings[50] = malloc(50 * sizeof(char *));
for(int i = 0; i < 50; ++i)
{
    strings[i] = malloc(50 * 6 * sizeof(char *));
}

その後、frees でクリーンアップすることを忘れないでください。

編集:そして、上記のように。メインメソッドの前。行を含めます#include <stdio.h>。これは、printf()関数が配置されている場所です。

于 2010-09-17T10:13:57.473 に答える