首页 > 解决方案 > 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 函数中打印的内容之间存在差异,那将有帮助。

标签: c

解决方案


两件事:(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覆盖这个字符串终止字符。因此,它“连接”了两个字符串(从第一个字符串的角度来看)。


推荐阅读