c - C程序中一些数组元素从函数内部更改为main函数内部
问题描述
我正在编写一个 C 程序来获取给定目录中所有文件的列表。它接受一个命令行输入,表示用户想要列出的文件所在目录的文件路径。该函数返回一个字符串数组,其中每个元素都是目录中的文件之一。现在,我让每个元素不仅仅是文件名,而是整个文件路径。所以这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
char **show_dir_content(char *path)
{
char **files;
int number_of_files = 5;
int i = 0;
files = (char **)calloc(number_of_files, sizeof(char *));
DIR *d = opendir(path);
if (d == NULL)
return files;
struct dirent *dir;
while ((dir = readdir(d)) != NULL)
{
if (dir->d_type != DT_DIR)
{
int path_len = strlen(path);
files[i] = (char *)calloc(strlen(dir->d_name) + path_len + 1, sizeof(char));
sprintf(files[i], "%s/%s", path, dir->d_name);
printf("%d: %s\n", i, files[i]);
i++;
if (i == number_of_files)
{
number_of_files += 5;
files = (char **)realloc(files, number_of_files * sizeof(char *));
}
}
}
return files;
}
int main(int arcv, char *argv[])
{
char **files = show_dir_content(argv[1]);
int i;
printf("\n");
for (i = 0; files[i] != '\0'; i++)
{
printf("%d: %s\n", i, files[i]);
}
for (i = 0; files[i] != '\0'; i++)
{
free(files[i]);
}
return 0;
}
当我输入当前目录作为输入时,至少可以说输出很时髦。所以我输出2种不同的方式。在我的 show_dir_content 函数中,我在获取文件后立即打印数组的每个元素。然后在主函数中,我循环遍历从 show_dir_content 函数返回的数组,打印每个元素。如果程序打印正确,两个结果应该是相同的,但由于某种原因它们不是,我不知道为什么。
0: ./file2.txt
1: ./file1.txt
2: ./find-file-size.h
3: ./find-file-size.o
4: ./get-files.o
5: ./get-files.h
6: ./Makefile
7: ./get-dir-size.h
8: ./get-dir-size.o
9: ./get-files.c
10: ./find-file-size.c
11: ./get-dir-size.c
12: ./fsz
0: ./file2.txt
1: ./file1.txt
2: ./find-file-size.h
3: ./find-file-size.o
4: ./get-files.o
5: ./get-files.h
6: ./Makefile
7: ./get-dir-size.h./get-dir-size.o./get-files.c
8: ./get-dir-size.o./get-files.c
9: ./get-files.c
10: ./find-file-size.c
11: ./get-dir-size.c
12: ./fsz
正如您所看到的,在大多数情况下,它是正确的,除了元素 7 和 8。如果有人能解释为什么从 show_dir_content 函数中的这两个元素与 main 函数中打印的内容之间存在差异,那将有帮助。
解决方案
两件事:(1)您需要分配一个额外的字符来覆盖必要的字符串终止字符'\0'
。(2) 你应该用 显式标记列表的结尾NULL
,因为你不能依赖 arealloc
用零填充内存块(calloc
你可以依赖它,但不能依赖realloc
):
while ((dir = readdir(d)) != NULL) {
...
// note the +2, one for the '/' and one for the string termination character
files[i] = (char *)calloc(strlen(dir->d_name) + path_len + 2, sizeof(char));
sprintf(files[i], "%s/%s", path, dir->d_name);
...
}
files[i] = NULL;
您观察到(未定义)行为的原因可能是第(1)部分;a first 写入的字符串终止字符sprintf
超出分配的内存范围;第二个calloc
可以从第一个的字符串终止字符开始,第二个会sprintf
覆盖这个字符串终止字符。因此,它“连接”了两个字符串(从第一个字符串的角度来看)。
推荐阅读
- java - 如何在 java 11 中将 jar 添加到引导类路径
- php - PHP:trim() 不适用于两个变量
- python - 无法在熊猫中加载网址
- rust - 要求关联的错误类型实现调试特征是一种好习惯吗?
- python - 将 Ajax 从 java 脚本发送到烧瓶
- python - 在python上将方法作为参数传递
- python - Keras 似乎无法配置 inputShape
- c# - 将字符串从 Delphi 传递到 C# 返回 null。但是,当我从 Delphi 调用 Delphi lib 时,它工作正常。如何从 Delphi 接收字符串
- c++ - 违反 const-correctness [placement new] 和未定义的行为
- apache - 通过 SNI 提供的主机名 myfirstweb.intweb.net 和通过 HTTP 提供的主机名 mysecondweb.intweb.net 不同,Apache 错误