【问题标题】:Please explain What's wrong with this C code?请解释这个C代码有什么问题?
【发布时间】:2020-09-09 19:40:34
【问题描述】:

我正在尝试获取目录中存在的所有文件,然后为该文件添加 .enc 扩展名。示例 - 让 File.txt 存在,然后我将执行一些与加密相关的任务,之后新文件名将是 File.txt.enc

这是我的代码:

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

int main(void)
{
    DIR *d;
    struct dirent *dir;
    char *name;
    int val;
    d = opendir(".");
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            name=dir->d_name;
            printf("File Found:%s\n",name);
            strcat(name,".enc");
            val=rename(dir->d_name,name);
            if(val==0)
                    printf("Encrypted File:%s\n",name);
            else
                    perror("Error: ");
        }
        closedir(d);
    }
    return(0);
}

但是我得到这样的输出......

File Found:write_pgm_img.c
Error: : No such file or directory
File Found:realloc.c
Error: : No such file or directory
File Found:getusage.txt
Error: : No such file or directory
File Found:directory.c
Error: : No such file or directory

您可以看到“没有这样的文件或目录”错误。但我不明白为什么?请解释一下。提前致谢。

【问题讨论】:

  • 重命名前尝试打印dir-&gt;d_namename
  • write_pgm_img.c.enc 看起来像一个有效的文件名吗?你好调试器,我的老朋友……又来找你聊天了……
  • 你在什么平台上? opendir() 不是标准 C 函数。
  • @12431234123412341234123 我正在使用 gcc 编译器。 Opendir() 是 GNU C 库中的标准函数......
  • @Rupam098 GCC 可以在没有opendir() 功能的windows 和许多没有目录概念的嵌入式平台上使用,甚至没有文件。如果您使用特定于 POSIX、Linux 或 GNU C 库的函数,请添加标签或在问题中指定。

标签: c gcc


【解决方案1】:

你搞乱了指针和内存内容:

            name=dir->d_name;
            printf("File Found:%s\n",name);
            strcat(name,".enc");
            val=rename(dir->d_name,name);

在第一行之后,namedir-&gt;d_name 指向同一个内存地址。这意味着您尝试将后缀添加到dir-&gt;d_name 所在的内存中。 您不能期望该内存足够大以容纳您的后缀。 (但在这种情况下,这不会导致问题,因为您的文件名似乎足够短)

此外,您的更新将同时影响 namedir-&gt;d_name,这使得重命名毫无意义,因为您尝试将 getusage.txt.enc 重命名为 getusage.txt.enc

一个可能的解决方案是:

        char name[sizeof(dir->d_name)+4];
        while ((dir = readdir(d)) != NULL)
        {
            strcpy(name, dir->d_name);
            printf("File Found:%s\n",name);
            strcat(name,".enc");
            val=rename(dir->d_name,name);

【讨论】:

    【解决方案2】:

    您的namedir-&gt;d_name 具有相同的地址。因此strcat(name,".enc"); 将同时更新namedir-&gt;d_name 并且源将具有前缀'.enc'

    【讨论】:

      【解决方案3】:

      我想您可能假设name=dir-&gt;d_name 创建了一些名为name 的新数据。这是一个很容易犯的错误,因为在许多编程语言中,这正是会发生的事情。但在 C 中,您只需设置一个名为 name 的指针来引用名为 d_name 的现有数据。

      如果您想在d_name 上附加一些内容,您可能需要将其复制到char *,该char * 引用了一个足够大的存储空间以容纳它、后缀和终止空值,然后复制后缀到该新存储的末尾。比如:

      char *new_name = malloc (strlen (dir->d_name) + strlen (suffix) + 1);
      strcpy (new_name, dir->d_name);
      strcat (new_name, suffix);
      ...
      free (new_name);
      

      可能还有许多其他方法可以实现相同的目标。基本点是在 C 中分配指针类型不会分配或复制存储。

      【讨论】:

      • 是的,这是一个错误。我认为它就像正常分配一样,忘记了指针指向的是一个空间内存地址。谢谢。
      【解决方案4】:

      由于name 可能没有更大的大小,strcat(name,".enc"); 可能会超过该大小并导致 UB。正如其他人指出的那样,这不会导致您得到 ENOENT 错误(假设您使用 linux)。

      要解决这个问题,您必须创建一个足够大的新缓冲区并将新名称复制到其中。这也可以解决您遇到的错误,因为这样您就不会覆盖旧名称。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        • 2015-02-23
        相关资源
        最近更新 更多