为什么stat会返回错误的结果?
我想通过使用stat
来检查给定的参数是否是目录。该程序需要2个参数:当第一个参数不是目录或它不存在代码工作正常。为什么stat会返回错误的结果?
但是,当第一个参数是一个目录并存在,并且第二个参数不存在时,程序会说它们都存在 - 错误的结果。我想知道为什么它不起作用。
#include <stdio.h>
#include <sys/stat.h>
int main(int n, char **argv)
{
char *dir_1=argv[1], *dir_2=argv[2];
if (is_dir(dir_1) == 0)
printf("Directory %s exists.\n", dir_1);
else
printf("Directory %s does not exist.\n", dir_1);
if (is_dir(dir_2) == 0)
printf("Directory %s exists.\n", dir_2);
else
printf("Directory %s does not exist.\n", dir_2);
}
int is_dir(char *file)
{
struct stat file_stat;
stat(file, &file_stat);
return((S_ISDIR(file_stat.st_mode)) ? 0 : -1);
}
如果文件不存在,stat
自己返回-1
,并设置errno
到ENOENT
。但是由于第一个目录存在并且是一个目录,所以struct stat
填充了一个目录的信息;这恰好位于堆栈中第二个调用的完全相同的位置。第二个stat
因errno
ENOENT
失败,但随后is_dir
解释了第一个调用留下的值。
为is_dir
更正确的实现可以是:
int is_dir(char *file)
{
struct stat file_stat;
// if an error occurs, we return 0 for false
if (stat(file, &file_stat) < 0) {
return 0;
}
// otherwise we return whatever the S_ISDIR returns
return S_ISDIR(file_stat.st_mode);
}
请注意,我改变返回值太大;一个函数如is_dir
预计会返回一个布尔值,在函数名称为true事实的情况下,该值为非零(非零),否则返回零。
你会使用它像:
if (is_dir(dir_1)) {
printf("Directory %s exists.\n", dir_1);
}
else {
printf("Directory %s does not exist.\n", dir_1);
}
if (is_dir(dir_2)) {
printf("Directory %s exists.\n", dir_2);
}
else {
printf("Directory %s does not exist.\n", dir_2);
}
注意,在这种情况下,返回值为0,并不意味着必然存在与该名称的目录;系统调用stat
也可能因为权限不足等原因而失败;扩展逻辑(解释价值errno
)超出了这个答案的范围。
或者,可以将其重命名为test_dir。 – user3125367
优雅的解决方案。我喜欢阅读漂亮的C代码。 –
谢谢,这回答我的问题。我只是想知道为什么当第二个目录不存在时返回0。我认为'struct stat'被初始化为一些值。 – user3140972
这个答案在另一个被接受之后。在MSVC中不存在S_ISDIR
,而是存在_S_IFDIR
。替换之后,编译器通知is_dir()
未返回值。原因是,_S_IFDIR
是一个掩码,而不是一个函数。所以在对代码进行一些调整之后,我得到了这个工作。
#include <stdio.h>
#include <sys/stat.h>
int is_dir(char *file)
{
struct stat file_stat;
if (stat(file, &file_stat) == 0) // check it worked
return file_stat.st_mode & _S_IFDIR; // it's a status mask
return 0;
}
int main(int argc, char **argv) // conventional ids
{
char *dir_1, *dir_2;
if (argc < 3) return 0; // check silliness
dir_1=argv[1];
dir_2=argv[2];
if (is_dir(dir_1)) // reversed the logic
printf("%s is a Directory.\n", dir_1);
else
printf("%s is not a Directory.\n", dir_1); // better text
if (is_dir(dir_2))
printf("%s is a Directory.\n", dir_2);
else
printf("%s is not a Directory.\n", dir_2);
return 0;
}
程序输出:
>test test.c wtest
test.c is not a Directory.
wtest is a Directory.
而且反过来:
>test wtest test.c
wtest is a Directory.
test.c is not a Directory.
谢谢。这是一个需要跨平台的项目的一小部分。所以'_S_IFDIR'会很有用。 – user3140972
由于使用功能的前*预计*输出,你应该检查它的返回值,看看它是否曾在所有。 –
如果函数只被调用一次,那么它总是正常工作。但是当我调用它两次时,它在所有情况下都不会返回预期值。 – user3140972
您没有'is_dir'的函数原型,所以编译器假定您传递了一个'int'参数。也许这就是为什么它行事不端。启用并记下所有编译器警告。 –