1

私は C で関数を記述しようとしています。この関数は、末尾が'\0'文字列である連続文字へのポインターと単一の定数文字区切り文字を受け入れ、それぞれが新しい文字列を指す連続ポインターへのポインターを出力します。 . これらの新しい文字列は、各区切り文字で分割され、適切に終了する入力文字列に対応します。簡単に言えば、文字列の配列を動的に構築したいと考えています。

これを行うには、malloc() を使用して必要なメモリを割り当てる予定です。「親配列」はsizeof(char *) * (count + 2)バイト長で、区切られた各部分文字列の最初の文字へのポインターとターミネーターを収容します。同様に、各「子配列」はsizeof(char) * (j + 1)、各部分文字列のすべての文字にターミネータを加えた長さのバイトになります。

これまでの私のコードはこれです。

#include <stdio.h>
#include <stdlib.h>

char *split(char *string, const char delimiter);

int main(int argc, char *argv[]) {
    char *x = split(argv[1], '.');
    while (*x) {
        printf("%d\n", *x);
    }
    return 0;
}

char *split(char *string, const char delimiter) {
    int length, count, i, j = 0;
    while(*(string++)) {
        if (*string == delimiter) count++;
        length++;
    }
    string -= length;
    char *array = (char *)malloc(sizeof(char *) * (length + 1));
    for(i, j = 0; i < (count + 1); i++) {
        while(*(string++) != delimiter) j++;
        string -= j;
        *array = (char *)malloc(sizeof(char) * (j + 1));
        while(*(string++) != delimiter) *(*array++) = *(string++);
        **array = '\0';
        string++;
        array += sizeof(char *);
    }
    *array = '\0';
    array -= (sizeof(char *) * (length + 1));
    return array;  
}

私の質問は、コンパイラが次のエラーを吐き出すのはなぜですか?

split2.c: In function ‘split’:
split2.c:25: warning: assignment makes integer from pointer without a cast
split2.c:26: error: invalid type argument of ‘unary *’ (have ‘int’)
split2.c:27: error: invalid type argument of ‘unary *’ (have ‘int’)

私の推測では、「親配列」のメモリが割り当てられると、コンパイラはそこに格納されるintのではなく、値を期待します。char *この場合、コードを正しく修正するにはどうすればよいですか?

を使用してこの種のことを行うはるかに簡単な方法があることは承知していますstring.h。このコードを書く動機は、C でポインターがどのように機能するかをよりよく学ぶことです。

よろしくお願いします!

4

3 に答える 3

3

arrayダブルポインターとして欲しいと思いますchar **array.

char **array = (char **)malloc(sizeof(char *) * (length + 1));

あなたのロジックが言うようにchar*、それぞれが文字列を指す の配列が必要です。したがってarray、ダブルポインターである必要があります。この変更を行う場合は、戻り値の型も に変更しchar**ます。

ダブルポインターを使用したい場合は、これを試してください:

char **split(char *string, const char delimiter) {
    int length = 0, count = 0, i = 0, j = 0;
    while(*(string++)) {
        if (*string == delimiter) count++;
        length++;
    }
    string -= (length + 1); // string was incremented one more than length
    char **array = (char **)malloc(sizeof(char *) * (length + 1));
    char ** base = array;
    for(i = 0; i < (count + 1); i++) {
        j = 0;
        while(string[j] != delimiter) j++;
        j++;
        *array = (char *)malloc(sizeof(char) * j);
        memcpy(*array, string, (j-1));
        (*array)[j-1] = '\0';
        string += j;
        array++;
    }
    *array = '\0';
    return base;  
}

次のように、後でこの配列を解放します。

i = 0;
while(base[i]) {
    free(base[i]);
    i++;
}
free(base);
base = NULL;
于 2013-06-12T09:02:07.493 に答える
2
    *array = (char *)malloc(sizeof(char) * (j + 1));

する必要があります

    array = (char *)malloc(sizeof(char) * (j + 1));  // malloc returns a pointer, no need to dereference here

そして、これ

    while(*(string++) != delimiter) *(*array++) = *(string++);

する必要があります

    while(*(string++) != delimiter) *array++ = *(string++); // dereferenceing once would do

そして最後にこれ

    **array = '\0';

する必要があります

    *array = '\0'; // same as above

上記のすべての変更の理由は同じです。arrayはポインターであり、ポインターへのポインターではありません。

さらに、コードでは、ループ インデックスiが初期化されていないため、非決定的な動作につながる可能性があります。次のような宣言で初期化します

int length, count, i = 0, j = 0;

またはループの初期化で

for(i = 0, j = 0; i < (count + 1); i++) {

お役に立てれば!

于 2013-06-12T08:58:24.140 に答える
0
char *array = (char *)malloc(sizeof(char *) * (length + 1));

する必要があります

char **array = (char **)malloc(sizeof(char **) * (length + 1));

*array = (char *)malloc(sizeof(char) * (j + 1));

する必要があります

array[i] = (char *)malloc(sizeof(char) * (j + 1));

あなたは初心者のようです。*array やその他のポインター操作を使用するよりも、array[i] を使用することをお勧めします。これは、最初はより簡単です。

于 2013-06-12T09:09:10.477 に答える