【问题标题】:char array assignment [closed]char数组赋值[关闭]
【发布时间】:2013-01-03 19:41:02
【问题描述】:

我正在尝试将文本文件中的行读入 char 数组,但出现了问题。请查看代码,让我知道我做错了什么。 谢谢。

#include <stdio.h>
#include <stdlib.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("%d %s",i, line);
        string[i]=line;
        i++;
    }
    for (j=0 ; j<i ; j++) {
        printf("string[%d] %s",j, string[j]);
    }
    fclose(file);
    return 0;
}

输入文件patt有以下内容。

rec
cent
ece
ce
recent
nt

在执行上面的代码时,我得到了这个

0 rec
1 cent
2 ece
3 ce
4 recent
5 nt
string[0] nt
string[1] nt
string[2] nt
string[3] nt
string[4] nt
string[5] nt

我期待的是这个

0 rec
1 cent
2 ece
3 ce
4 recent
5 nt
string[0] rec
string[1] cent
string[2] ece
string[3] ce
string[4] recent
string[5] nt

【问题讨论】:

  • 要求人们发现代码中的错误并不高效。您应该使用调试器(或添加打印语句)来隔离问题,然后构造一个minimal test-case。

标签: c arrays file-handling


【解决方案1】:

为了帮助您理解您的代码:

  • 您每次都在向string[i] 写入line 的地址,而数组line 的内容在整个循环中不断变化。 这导致所有string[i] 都包含相同变量的地址,即line。 在循环结束时,从文件中读取的最后一行存储在line 数组中。现在,当您打印 string[i] 时,您正在打印变量 line 中存在的数据。由于 string[i] 的所有实例都包含 line 的相同地址,它们都在打印相同的值,即nt 在您的输出中。
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) {//You missed the ()'s in the sizeof
        printf("%d %s",i, line);
        string[i]=line;
        i++;
    }

*你应该做的是:

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) {//You missed the ()'s in the sizeof
    printf("%d %s",i, line);
    string[i]=malloc(strlen(line)+1); ///You need to allocate some memory to char* string[i] here
    if(string[i] == NULL)//Do a NULL check if malloc failed
      //Handle NULL here
    strncpy(string[i],line,strlen(line)+1);//Use strncpy to copy line into the malloced memory in string[i]
    i++;
}

现在,由于您已分配内存来存储数据,因此您也需要释放内存。 所以,而不是在你的代码中:

    for (j=0 ; j<i ; j++) {
        printf("string[%d] %s",j, string[j]);
    }
    fclose(file);
    return 0;
}

这样做:

    for (j=0 ; j<i ; j++) {
    printf("string[%d] %s",j, string[j]);
    free(string[j]);
    }
   fclose(file);
   return 0;
}

现在,这应该会给你你想要的。

【讨论】:

  • 您的代码在创建重复字符串时不包含 NUL 终止符,因此当他尝试将它们打印出来时,他会得到未定义的行为。
  • 是的,我遇到了很多疯狂的错误
  • 这是一个错字,free(string[i]); 也是。
  • 代码已修复。请注意,您可以存储最大值。由于代码中的char* string[100];,100 行。您可以使用realloc() 而不是使用静态数组从文件中读取所需的行数。
  • @askmish:我认为“修复”这个词有点强。您已经成功地使 zigs 和 zags 正确匹配,因此您不再有未定义的行为,但代码如下:strncpy(string[i],line,strlen(line)+1); 是......可怕。事实上,任何时候你甚至考虑使用strncpy,停下来,深呼吸,然后思考。如果strncpy 是正确答案,那么您几乎肯定问错了问题。
【解决方案2】:

您的string[i]=line; 表示您将指向同一缓冲区 (line) 的指针重复存储到 string 中的每个连续项目中。像这样的:

为了使事情顺利进行,您需要为每个指向的缓冲区分配一个新缓冲区,例如:string[i] = dupe_string(line);,其中dupe_string 将类似于:

char *dupe_string(char const *in) { 
    char *dupe;
    if (NULL != (dupe = malloc(strlen(in) + 1)))
        strcpy(dupe, in);
    return dupe;
}

请注意,由于这使用malloc 为每个字符串分配空间,您最终需要为每个字符串调用free 以避免内存泄漏。

【讨论】:

  • 谢谢,你的意思是我必须使用类似 for(i=0 to 100) 然后 free(string[i])
  • 我试图按照 Ashrj 的建议来实现这一点,但有这样的错误 -> test.c:23:8: error: 'dupe_string' test.c:12:16 的类型冲突:注意:先前的“dupe_string”隐式声明在这里 test.c:在函数“dupe_string”中:test.c:26:11:错误:“dup”未声明(在此函数中首次使用)test.c:26:11:注意: 每个未声明的标识符对于它出现的每个函数只报告一次
  • @user1733911: 是的,除了你想确保你只释放你分配的尽可能多的字符串(在未初始化的指针可能包含的任何随机值上调用free 将给出未定义的行为)。或者,您可以将未使用的指针初始化为NULL。至于其他:我在代码中有错字 --dup 应该是dupe。您可以将dupe_string 放在 使用它的代码之前,或者在调用它的函数之前添加一个类似char *dupe_string(char const *); 的原型。
【解决方案3】:

您重复写入同一个数组。

while(fgets(line, sizeof line, file)!=NULL) {

在这一行中,您反复写入数组line。


我认为您误解了 char* string[100]; 的作用。您将它用作数组数组,而实际上它是一个包含 100 个指针的数组。

要纠正这个问题,你需要在每次迭代中首先分配一个新的内存块:

 string[i] = malloc(strlen(line)+1);

那你需要把line的内容复制到string[i]:

strcpy(string[i], line); 

另外,在程序结束时,您需要使用free 来释放内存。

【讨论】:

  • 从文件中读取的那些行分配给字符串数组的正确方法是什么
  • 非常感谢,它现在可以工作了 PS:你能建议更好的方法来处理这个 char* string[100];字符线[100];
  • 1) 不要从malloc 转换返回值(这样做会隐藏错误)。 2) 你没有为字符串上的 NUL 终止符分配足够的空间——你需要`malloc(strlen(line) + 1)`。
  • @JerryCoffin 不投射从 malloc 返回的指针的原因是什么?我在 SO 上看到过一些帖子说同样的话,但没有解释。
  • @AshRj 你应该偶然发现my answer here 确实试图提供一些解释。
猜你喜欢
  • 2015-03-08
  • 2013-02-01
  • 2011-08-13
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 2018-12-15
相关资源
最近更新 更多