0

メイン関数の外にこのコードがあります

mystr * arrstr[] = {
    "rec",
    "cent",
    "ece",
    "ce",
    "recent",
    "nt",
};

テキストファイルから値を読み取れるように修正しました。この目的のために、この作業コードを変更して、ファイルから文字列という名前の配列に行を読み取ります。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
    int i=0,j;
    char* string[100];
    char line[100];
    FILE *file; 
    file = fopen("patt", "r"); 
    while(fgets(line, sizeof(line), file)!=NULL) {
        printf("%s", line);
        string[i] = (char*)malloc(strlen(line));
        strcpy(string[i], line);
        i++;
    }
    fclose(file);
    return 0;
}

最終的なコードは次のようになります。

..
..
char *getpatterns(const char *filename) {
    int i=0;
    char* string[100];
    char line[100];
    FILE *file; 
    file = fopen(filename, "r"); 
    while(fgets(line, sizeof(line), file)!=NULL) {
        //printf("%s", line);
        string[i] = (char*)malloc(strlen(line));
        strcpy(string[i], line);
        i++;
    }
    fclose(file);
    return(string);
}
mystr * arrstr[] = getpatterns("patt");/*{
    "rec",
    "cent",
    "ece",
    "ce",
    "recent",
    "nt",
};*/
..
..

しかし、私はこのようなエラーが発生します。

example1.c: In function ‘getpatterns’:
example1.c:43:2: warning: return from incompatible pointer type [enabled by default]
example1.c:43:2: warning: function returns address of local variable [enabled by default]
example1.c: At top level:
example1.c:45:1: error: invalid initializer
make: *** [example1.o] Error 1

ここで45行目はこの行です

mystr * arrstr[] = getpatterns("patt");/*{

是正措置を提案してください。

4

1 に答える 1

2

char **最初の警告は、 a を aとして返そうとしていることchar *(これは良い考えではありません) と、関数が戻るときに割り当て解除されるローカル変数を返していること (これも良い考えではありません) です。最後は、C のグローバル変数の初期化子で関数呼び出しを使用できないことを示しています (C++ でその一部を実行できますが、これを実行できるとは確信していません)。

それを修正するには、いくつかの再考が必要です。割り当てられたメモリを返す関数が必要か、関数にメモリを渡す必要があります。また、グローバル変数の型を変更する必要があります。そして、どういうわけか、配列にいくつのエントリがあるかを知る必要があります。

mystr **arrstr = 0;  // Either
mystr  *arrstr[100]; // Or

全体として、おそらくメモリ割り当てと「どちらか」の宣言を使用します。

mystr **arrstr = 0;

char **getpatterns(const char *file)
{
    char **array = 0;
    ...code similar to yours that allocates entries in the array...
    ...include space for a null pointer to mark the end of the list of strings...
    return(array);
}

int main(void)
{
    arrstr = getpatterns("patt");
    ...
}

(別の「チート」メカニズムが in で使用static char *string[100];されgetpatterns()ます。戻り値の型とグローバル変数の型を修正する必要があります。)


これらを試しましたが、エラーは解決されませんでした: ...

コードがなければ、何が間違っていたのかを正確に判断することは不可能です。ただし、以下のコードは私にとってはうまくいきます。ソースコードはファイルにありましたgp.c。ソースコード自体が出力され、メモリが解放されます。valgrindきれいな健康状態でチェックされました。

元のコードでは、コピーする文字列に十分なスペースが割り当てられていないことに注意してください (これは、改行を保持していたためですfgets()— しかし、少なくとも and を使用fgets()していなかったためgets()、これは非常に重要です)。このコードでは使用memmove()memcpy()オーバーラップがないことが保証されているため、代わりに使用できますが、memmove()常に機能memcpy()し、ソース データがターゲット データと重なっている場合は必ずしも機能するとは限りません。文字列の長さを認識しているため、コピー関数は、コピーされる文字が NUL かどうかをテストする必要はありません'\0'。このコードでは、ポインターのリストの末尾にヌル ポインターがあることを慎重に確認しています。これにより、文字列のリストの最後に到達したことがわかります。このコードgp.cは、 が空のファイルの場合にも機能します。

num_xxxmax_xxx、およびの 3 つの項目を使用するアルゴリズムxxxは、増分割り当てを処理する一般的な方法です。通常、わずかに過剰に割り当てられます。スペースが気になる場合strings = realloc(strings, (num_strings+1) * sizeof(*strings)); max_strings = num_strings + 1;は、ループの最後で使用して余分なスペースを解放できます。これ+ 1は、null ポインターを許可することです。割り当てるたびに割り当てられるサイズをおおよそ 2 倍にすることで、毎回 1 ずつインクリメントする場合と比較して、2 次動作を回避できます。

が失敗した場合に、コードが割り当てられたスペースを失うことを慎重に回避していることにも注意してくださいrealloc()space = realloc(space, new_size);ポインターを失うことを避けるために、「決して」使用しないでください。このコードは、null ポインターの逆参照を慎重に回避し、メモリ不足になると読み取りを停止します。

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

extern char **getpatterns(const char *filename);

char **getpatterns(const char *filename)
{
    size_t num_strings = 0;
    size_t max_strings = 0;
    char **strings = 0;
    FILE *file = fopen(filename, "r"); 

    if (file != 0)
    {
        char line[4096];
        while (fgets(line, sizeof(line), file) != NULL)
        {
            if (max_strings == 0 || num_strings >= max_strings - 1)
            {
                size_t   new_num = max_strings * 2 + 2;
                char   **new_space = realloc(strings, new_num * sizeof(*new_space));
                if (new_space == 0)
                    break;
                strings = new_space;
                max_strings = new_num;
            }
            size_t len = strlen(line);  /* Includes '\n' at end */
            strings[num_strings] = (char*)malloc(len);
            memmove(strings[num_strings], line, len - 1);
            strings[num_strings][len] = '\0';
            strings[++num_strings] = 0; /* Null terminate list of strings */
        }
        fclose(file);
    }
    return(strings);
}

int main(void)
{
    char **data = getpatterns("gp.c");
    char **argp = data;

    if (argp != 0)
    {
        /* Print data */
        while (*argp != 0)
            puts(*argp++);

        /* Free space */
        argp = data;
        while (*argp != 0)
            free(*argp++);
        free(data);
    }

    return(0);
}
于 2013-01-20T18:37:20.467 に答える