【问题标题】:C, looping array of char* (strings) does't work. Why?C、char*(字符串)的循环数组不起作用。为什么?
【发布时间】:2013-11-29 12:38:34
【问题描述】:

我的 char* 数组有问题-

char *original_file_name_list[500];

while(dp=readdir(dir)) != NULL) {
   original_file_name = dp->d_name;
   original_file_name_list[counter] = original_file_name;
   printf("%s\n",original_file_name_list[0]);
   printf("%d\n",counter); 
   counter++;
}

问题是,它可以很好地打印所有文件。它应该只打印第一个文件,对吗? 如果我尝试printf("%s\n",original_file_name_list[1]); 它不起作用,这意味着它只在第一个字符串中写入。知道为什么吗?

edit:编译器没有语法错误。

【问题讨论】:

  • counter2 永远不会增加,对吧?
  • @Constantin:当我在这里编写代码时,我犯了一个错误(已经修复)。对不起,很遗憾,这不是问题。

标签: c arrays string loops


【解决方案1】:

您根本没有复制字符串-您的file_name_list 数组也没有足够的空间容纳文件名列表-仅用于指针列表。但是dp->d_name 只是一个指向char* 的指针——你不知道指针后面的内存有效的时间有多长。因此,您必须自己制作副本。

#include <string.h>
#include <dirent.h>

int main(int argc, char** argv){
  char original_file_name_list[50][50];
  size_t counter = 0;
  while(dp=readdir(dir)) != NULL) // does work fine (ordinary reading files from dir)
  {
    size_t len = strlen(dp->d_name);
    if(len >= 50) len = 49;
    strncpy(original_file_name_list[counter], dp->d_name, len);
    original_file_name_list[counter][len] = '\0';
    printf("%d\n",counter); 
    counter++;
  }
  printf("%s\n",original_file_name_list[1]); // <- will work if you have at least 2 files in your directory
  return 0;
}

【讨论】:

  • 为什么不使用 strndup()?
  • @Michael 因为它是邪恶的。另请参阅:stackoverflow.com/questions/12984948/… 但如果您愿意,可以随时使用strndup() 发布答案
  • @unwind 我认为他在谈论char *strndup(const char *s, size_t size);(他在回答中使用了它),但strdup() 的问题也适用于strndup()
  • @Constantin 它是不可移植的,它可能会“隐藏”它的分配(虽然函数返回分配的内存并不少见),但我不会称之为“邪恶”。跨度>
【解决方案2】:

我不确定counter2 的用途(我已将其替换为counter),但我可以建议使用strdup() 调用以下代码来存储文件名:

char *original_file_name_list[500] = {0}; // it is better to init it here

while(dp=readdir(dir)) != NULL) {
   original_file_name_list[counter] = strdup(dp->d_name); // strdup() is ok to use
                                                          // here, see the comments
   printf("%s\n%d\n",original_file_name_list[counter], counter);
   counter++;
}

/* some useful code */

/* don't forget to free the items of list (allocated by strdup(..) )*/
for (int i = 0; i < 500; ++i) {
   free(original_file_name_list[i]);
}

【讨论】:

  • counter2 应该只是 counter...我的错误,对不起。我会试试看,因为康斯坦丁的版本不行。
  • 是的,它有效......非常感谢迈克尔......你让我开心...... :))
  • "d_name in linux has a length of 256" - 那么为什么不使用sizeof dp-&gt;d_name而不是256呢?
  • @glglgl 哦,又是你……又是有用的评论。 :-) 谢谢。固定!
  • 来自pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html 的 POSIX 规范:“...dirent,其中包含至少包含 {NAME_MAX}+1 个元素的 char d_name 成员数组。”来自 Linux man7.org/linux/man-pages/man3/readdir.2.html 的手册页:“... d_name 是一个以 null 结尾的文件名。”所以第一个:我是 0-终止的,第二个不是256,而是NAME_MAX。跨度>
猜你喜欢
  • 2021-04-19
  • 2021-12-25
  • 2018-04-07
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多