在C语言中从函数返回字符串数组

3

我从给定的文件(字典)中读取单词并将字符串分配给字符串数组中的第n个索引。但它不起作用。 main() 中的for循环输出总是e3V\347等,而createWordTable()中的for循环输出总是字典的最后一个单词。以下是我的代码:

char** createWordTable();

char** createTable();

int main()
{

    int i;
    char **hashTable;
    hashTable = createTable();
    hashTable = createWordTable();



    for (i=0; i< 338; i++) {
        printf("%s \n",hashTable[i]);
    }

    return 0;
}

char** createWordTable(){

    char  word[20],**table;
    FILE *dicFile;
    table = createTable();

    dicFile = fopen("smallDictionary.txt", "r");
    if (dicFile == NULL) {
        perror("error");
    }
    int wordCount = 0,endFile = 1;
    while (endFile != EOF) {
        endFile = fscanf(dicFile,"%s",word);
        table[wordCount] = word;
        wordCount = wordCount+1;
    }
    for (int i=0; i< 338; i++) {
        printf("%s \n",table[i]);
    }
    return table;

}

char** createTable(){

    char **table;
    int i;
    table = (char **)malloc(338 * sizeof(char *));
    for (i=0; i<=338; i++) {
        *table = (char *)malloc(25 * sizeof(char));
    }
    return table;
}

我将代码更改为以下内容,它可以正常工作!我定义了全局变量'table'并移除了指针(以及动态分配函数)。我非常好奇为什么在C语言中指针不能与字符串数组一起使用(我知道方括号也表示“指针”)?因为我没有用整数数组遇到过这种问题。抱歉我的英文不太好,以下是新代码:

char words[338][10];

int main()

{

createWordTable();

for (int i=0; i< 338; i++) {
    printf("%s \n",words[i]);
}


return 0;

}

void createWordTable(){

char  word[20];

FILE *dicFile;


dicFile = fopen("smallDictionary.txt", "r");
if (dicFile == NULL) {
    perror("error");
}
int wordCount = 0;
while (!feof(dicFile)) {
    fscanf(dicFile,"%s",word);
    if(feof(dicFile)) break; 
   strcpy(words[wordCount], word);

    wordCount = wordCount+1;
}

 fclose(dicFile);

}`


1
当你把C语言、字符串和一位经验不足的程序员放在一个房间里时,总是让我感到惊讶,有太多的问题可能会出现... - Jonas Bötel
我刚刚稍微编辑了您的帖子,以修复正文和问题标题中的一些格式问题(例如大写字母"C")。 - Mr.C64
3个回答

1
你正在失去createTable()的结果。将其存储在单独的指针变量中。
hashTable = createTable();
hashTable = createWordTable();

1

从函数返回字符串数组的一种选项是使用NUL结尾字符串

这种数据结构是一个字符串序列,每个字符串在内存中紧随其后,每个字符串都以NUL结尾,并且在末尾有一个额外的NUL终止符,例如:

+---+---+---+---+---+-----+---+---+---+---+---+-----+-----+
| H | e | l | l | o | NUL | w | o | r | l | d | NUL | NUL |
+---+---+---+---+---+-----+---+---+---+---+---+-----+-----+
                                                 ^^^^^^
                                      Double-NUL at the end

你可以从函数中返回指向第一个字符串的指针,即序列开头的指针。
这种数据结构的一个巨大优势是它对数组中的字符串有非常好的局部性。
这种数据结构不难实现,并且易于导航,正如下面的源代码所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ARRAY_SIZE(a)   (sizeof(a) / sizeof(a[0]))

char * build_string_array(void) {
    const char * test_strings[] = {
        "Hello",
        "World",
        "Hi",
        "John",
        "Connie"
    };
    int i;
    char * p;
    char * string_array;
    int total_len;

    /* Calculate total length of strings */
    total_len = 0;
    for (i = 0; i < ARRAY_SIZE(test_strings); i++) {
        /* Update total length with current string. +1 for '\0' */
        total_len += strlen(test_strings[i]) + 1;
    }

    /* Consider double-NUL termination */
    total_len++;

    /* Allocate memory for the resulting string array */
    string_array = malloc(total_len);
    if (string_array == NULL)
        return NULL; /* error */

    /* Copy source strings to the destination string array memory */
    p = string_array;
    for (i = 0; i < ARRAY_SIZE(test_strings); i++) {
        strcpy(p, test_strings[i]);
        p += (strlen(p) + 1); /* +1 to skip terminating NUL */
    }

    /* Terminate with double-NUL */
    *p = '\0';

    /* Return the address of the string array to the caller */
    return string_array;
}

int main() {
    char * test_string_array;
    const char * p;

    /* Create the test string array */
    test_string_array = build_string_array();
    if (test_string_array == NULL) {
        printf("Error in creating array.\n");
        return 1;
    }

    /* Print string array content */
    for (p = test_string_array; *p != '\0'; p += (strlen(p) + 1)) {
        printf("%s\n", p);
    }

    /* Free array memory */
    free(test_string_array);

    /* All right */
    return 0;
}

我不确定这是否是一个选项。你失去了使用空字符串的可能性... - glglgl
@glglgl:你说的空字符串是对的。如果需要空字符串,那么另一个选项就是在上述结构之前使用一种“头”,存储一系列字符串指针,并以NULL指针终止。在该头部(包含字符串指针)之后,跟随字符串。 - Mr.C64

0
你应该直接使用fscanf读入到table[wordcount]或者使用strcpyword复制。否则,每个条目都只会指向包含文件中最后一个字符串的word

我之前做过这个,但是遇到了exc_bad_access问题。 - Anamort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接