【问题标题】:returning 2d array in C…在 C 中返回二维数组...
【发布时间】:2014-12-22 03:30:06
【问题描述】:

我完全是 C 语言的菜鸟。我无法在这个函数和 main 之间建立连接。我正在尝试打印出一个二维数组,但我不断收到分段错误。任何帮助将不胜感激。

编辑:当我将最后一行 'printf("%d:[%s]\n",i,*(p+i))' 从 %s 更改为 %c 时,我得到了我正在读取的文件。事实证明,我的函数实际上正在返回一些东西。现在只需要弄清楚如何让它从文件中的其他行返回单词。

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

#define num_strings 20
#define size_strings 20

int *read_file(){
    int j = 0;
    static char text[num_strings][size_strings];

    FILE *fp;
    int x;

    fp = fopen("dictionary2.txt", "r");

    char s[100];
    while(!feof(fp)) {
        x = fscanf(fp,"%[^\n]",s);
        fgetc(fp);

        if (x==1) {
            strcpy(text[j],s);
            j++;
        }
    }
    return text;
}

int main() {
    int *p;
    p = read_file();
    int i;
    for(i = 0; i < 10; i++) {
        printf("%d:[%s]\n",i,*(p+i));
    }
    return(0);
}

【问题讨论】:

  • 这一定是我见过的最奇怪的 C 代码。
  • ;} 看起来像某种表情符号
  • 您不能在 C 中返回数组,句号。因为它被声明为static,所以你能做的最好的就是返回一个合适的指向它的指针。更好的是在main() 中声明它,然后将它传递给你的函数,然后完全忘记返回它。检查来自fopen() 的返回以防万一失败,并且不要从malloc() 转换返回。学会正确地格式化你的代码。
  • 我有代码可以检查以防 fopen() 失败。我把它拿出来只是为了在这里发布我关心的内容,即访问这个二维数组。
  • char *s=(char*)malloc(100); :内存泄漏。更改为char s[100];

标签: c arrays


【解决方案1】:

尝试将您的#defines 移回并更改您的函数头以返回指向size_strings 字符数组的指针,如下所示:

    #define num_strings 20
    #define size_strings 20

    char (*read_file())[size_strings] {

或者,使用 typedef:

    #define num_strings 20
    #define size_strings 20

    typedef char (*PCharArr)[size_strings];

    PCharArr read_file() {

...并相应地更改 main 中 p 的类型:

    char (*p)[size_strings];

这将返回一个字符数组数组(指向第一个元素的指针),它或多或少等同于char 的二维数组。

【讨论】:

    【解决方案2】:

    一般来说,你应该在main() 中创建你的数组并传入,这种行为是非常不正统的。但是,如果你坚持这样做,你必须返回一个指向你的数组的指针,因为你不能在 C 中返回数组。

    这是你需要的东西:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define num_strings 20
    #define size_strings 20
    
    typedef char (*PARR)[num_strings][size_strings];
    
    PARR read_file(int * wordsread)
    {
        static char text[num_strings][size_strings];
        FILE *fp;
    
        if ( (fp = fopen("dictionary2.txt", "r")) == NULL ) {
            fprintf(stderr, "Couldn't open file for reading\n");
            exit(EXIT_FAILURE);
        }
    
        char s[100];
        int j = 0;
    
        while ( j < num_strings && fgets(s, sizeof s, fp) ) {
            const size_t sl = strlen(s);
            if ( s[sl - 1] == '\n' ) {
                s[sl - 1] = 0;
            }
    
            if ( (strlen(s) + 1) > size_strings ) {
                fprintf(stderr, "String [%s] too long!\n", s);
                exit(EXIT_FAILURE);
            }
    
            strcpy(text[j++], s);
        }
    
        fclose(fp);
        *wordsread = j;
        return &text;
    }
    
    int main(void)
    {
        int wordsread = 0;
        PARR p = read_file(&wordsread);
    
        for ( int i = 0; i < wordsread; ++i ) {
            printf("%d:[%s]\n", i, (*p)[i]);
        }
    
        return 0;
    }
    

    通过合适的输入文件输出:

    paul@horus:~/src/sandbox$ ./twoarr
    0:[these]
    1:[are]
    2:[some]
    3:[words]
    4:[and]
    5:[here]
    6:[are]
    7:[some]
    8:[more]
    9:[the]
    10:[total]
    11:[number]
    12:[of]
    13:[words]
    14:[in]
    15:[this]
    16:[file]
    17:[is]
    18:[twenty]
    19:[s'right]
    paul@horus:~/src/sandbox$ 
    

    请注意,这只有效,因为您将 read_file() 中的数组声明为 static - 不要以这种方式返回指向具有自动存储持续时间的局部变量的指针。

    【讨论】:

    • 如果我能在这里投票一千次,我会非常感谢!!
    • 如果这是您想要的并且您倾向于接受答案,我会接受一个赞成票和一个接受。
    【解决方案3】:

    更新,哦,我明白了,您将代码从 main 粘贴到函数中,我知道这里发生了什么,您假设 p[20][20] 与 ap* 或 ap** 相同,这是不正确的,因为现在如果你做 *(p+1),编译器不知道 p 中的每个元素都是 20 宽而不是 1 宽。您在这里的方法应该是在 read_file 中声明一个指向字符串数组的指针并返回它:

    static char text[num_strings][size_strings];
    static char *texts[num_strings]
    
    ...
    while....
        ....
           if (x==1)
            {strcpy(text[j],s);texts[j]=text[j];j++;}
    
    
    return texts;
    

    你的 p 应该是 char* 而不是 int*。如果已读入 20 个项目,您还需要终止循环。

    【讨论】:

    • 是的,我稍后会编辑格式。现在,我只想让它工作。它正在读取的txt文件很小,我分配的空间足够了。我正在尝试返回指向该函数的指针。我在 main() 中编写了所有代码并且它有效。但我的目标是能够从函数中调用它。
    • 我会看看,但代码现在仍然可以工作。感谢您的时间和精力,非常感谢。