删除C中的文件表明找不到该文件

Boa*_*rdy 1 c delete-file

我正在研究ac项目,我需要从目录中删除一个文件.出于某种原因,虽然它继续说它无法删除,因为文件或目录不存在.下面是我用来删除文件的代码.

void deleteOldestLog()
{
    FILE *fp;
    char path[FILE_PATH_BUF_LEN], *fileName;

    fp = popen("ls -tr /home/myfolder/logs/ |head -1", "r");
    if (fp == NULL)
    {
        printf("Failed to run command");
    }
    else
    {
        char removalPath[FILE_PATH_BUF_LEN];
        while ((fileName = fgets(path, sizeof(path)-1, fp)) != NULL)
        {
            sprintf(removalPath, "/home/myfolder/logs/%s", fileName, sizeof(fileName)-1);

            printf("Removing file: %s", removalPath);
            if (remove(removalPath) != 0)
            {
                perror("ERROR DELETING LOG");
            }
            else
            {
                printf("Successfully deleted %s", removalPath);
            }
            break;
        }
        pclose(fp);
    }
}
Run Code Online (Sandbox Code Playgroud)

即使它说它找不到文件因为它不存在我知道这不是真的,因为如果我运行ll后跟c程序打印的路径它返回我试图删除的文件.

我想这可能是因为fgets将'\ 0'放在字符串的末尾,这会阻止删除工作.

我怎样才能解决这个问题?

Jon*_*ler 5

读取的文件名末尾有换行符fgets().您的文件名实际上并不以换行符结尾.

您尝试删除换行符:

sprintf(removalPath, "/home/myfolder/%s", fileName, sizeof(fileName)-1);
Run Code Online (Sandbox Code Playgroud)

但是,为了有效,您需要使用strlen()而不是sizeof(),并且您需要修改格式字符串:

sprintf(removalPath, "/home/myfolder/%.*s", (int)strlen(fileName)-1, fileName);
Run Code Online (Sandbox Code Playgroud)

*必须为a 的论证intstrlen()返回a size_t; 因此演员.(如果你打开警告,海湾合作委员会会警告这类事情;至少使用-Wall.)

给你的提示:如有疑问,请打印字符串.我通常会使用这样的格式.请注意字符串周围的尖括号:

printf("Removing: <<%s>>\n", removalPath);
Run Code Online (Sandbox Code Playgroud)

当你看到:

Removing: <</home/myfolder/something
>>
Run Code Online (Sandbox Code Playgroud)

你知道字符串中有换行符有问题.如果没有标记,您可能不会注意到字符串中有换行符导致输出中出现额外的换行符.


为什么需要修改格式字符串?

让我们再看一下原作sprintf():

sprintf(removalPath, "/home/myfolder/%s", fileName, sizeof(fileName)-1);
Run Code Online (Sandbox Code Playgroud)

格式字符串需要1个参数,一个字符串.该调用提供两个值,一个字符串和一个长度.所以,第一个问题是有一个遗留的论点.这通常没有损坏,但要注意它.据推测,传递长度减去一的原因是失去最后一个角色.系列中的格式printf()可以用一个或两个数字装饰,其中一个或两个都可以有一个*而不是整数值.这些数字限制格式化值的长度.当你写:

%.*s
Run Code Online (Sandbox Code Playgroud)

您声明输出的长度应该是int在字符串本身之前作为参数传递的值指定的长度.因此修订:

sprintf(removalPath, "/home/myfolder/%.*s", (int)strlen(fileName)-1, fileName);
Run Code Online (Sandbox Code Playgroud)

(我刚刚在添加此信息时修复了这个问题.)

我也没有将错误检查添加到输出sprintf()等等.这并不罕见; 但是,最佳编码实践确保函数sprintf()返回您期望的值(这是写入字符串的字符数,不包括尾随空值'\0'.

(旁白:一般来说,使用snprintf()比它更好sprintf();这可以避免缓冲区溢出.

snprintf(removalPath, sizeof(removalPath), "/home/myfolder/%.*s",
         (int)strlen(fileName)-1, fileName);
Run Code Online (Sandbox Code Playgroud)

但是,*snprintf()MSVC 下的功能行为与C标准(C99,C11)规定的行为不同.更糟糕的是,在vsnprintf_s()其他_s函数和其他函数的情况下,参数列表在MSVC和C标准之间是不同的.)