【问题标题】:C function to return file name from file address [closed]C函数从文件地址返回文件名[关闭]
【发布时间】:2021-11-09 16:22:42
【问题描述】:

我正在尝试编写一个函数,该函数将从文件地址返回文件的文件名。它只是复制地址的每个字符,从终止字符开始,直到第一个正斜杠'\\',到一个名为name 的字符数组变量。然后,它只是颠倒变量name 中所有字符的顺序。我写了一个函数叫file_name(),像这样:

char* file_name(char* addr){
    static char name[100];
    char temp;
    int i = -1;
    for (; addr[i] != '\\'; --i){
        name[-1-i] = addr[i]; // -1-i increases from 0 as i decreases. We get the reversed name of the file in "name"
    }
    int len = -i; //array length is simply -i. we know that through as i acts as the counter in the above iteration.
    for (int count = 0; count < len; ++count){
        temp = name[count];
        name[count] = name[len - 1 - count];
        name[len - 1 - count] = temp;
    }
    return name;
}

在收到编译器的警告并在 Google 上查找后,我已将 name 声明为静态变量。我发现没有使用static 关键字(或通过动态分配)声明它,name 被视为局部变量,并且作为一个数组,在返回语句后被“删除”(我想知道一个正确的解释。我还是有点不明白那是什么。只有一个模糊的想法)。

现在,在代码中添加 main 函数后,编译就很好了:

int main(int argc, char** argv){
    char* name = file_name(argv[1]);
    printf("File name is: %s", name);
    return 0;
}

现在,由于某种原因,我没有得到任何输出。我给可执行文件一个带有有效文件地址的参数,但它没有输出。最重要的是,它只会停顿几秒钟,然后退出。这是怎么回事?我不认为这是算法的问题。该函数返回数组没有问题,因为它在更简单的情况下运行良好。为什么它不起作用?

我正在使用 GNU 编译器集合在 Windows 10 上工作。

附: - 如果标准库中已经有一个从地址返回文件名的函数,我将不胜感激。但是,仍然想知道为什么我的代码不起作用。

【问题讨论】:

  • 仅供参考 `\` 是反斜杠,而不是正斜杠。
  • 使用调试器 - DIY 解决方案。
  • 我很确定name[-1-i]addr[i] 总是会越界。您是否希望一个负索引环绕到数组的最后一个索引或其他什么?
  • @mediocrevegetable1 @mediocrevegetable1 i 从 -1 开始并减少(变得更负)所以-1-i 从 0 开始并变得更正。
  • 不应将名称定义为大小为 100 的静态字符,而应定义为输入文件名 +1 的 char* 和分配字符数。查看 strrchr 函数。从文件名的长度向后循环。循环停止应考虑 \ char 并且您仍在字符串中。

标签: arrays c function scope


【解决方案1】:

这是一个非常明显的错误,可能会导致崩溃:

int i = -1;
for (; addr[i]

同样-1-i 是错误的。这两个都是越界未定义的行为错误。

int len = -i; 也是错误的。您不能在 C 编程中使用负数组索引。正式来源见 C17 6.5.6/8。


数组,在return语句后被“删除”(我想知道一个正确的解释

这个非常常见的初学者错误在任何一本不错的 C 书籍中都会提到。关于它的 SO 规范常见问题解答帖子是这样的:Can a local variable's memory be accessed outside its scope?


该函数返回数组没有问题,因为它在更简单的情况下运行良好。

如果一个函数只适用于某些测试用例,这非常强烈地表明该函数没有运行良好,并且在其他情况下只是通过(坏)运气给出了正确的结果。见What is undefined behavior and how does it work?

【讨论】:

  • 其实我使用 addr[i] 作为条件语句是因为 geeksforgeeks 上有一个页面:geeksforgeeks.org/c-tricks-competitive-programming-c-11。根据第 4 点,它应该可以工作。
  • @AnujJodha 该网站的名声很差。从适当的书籍和课程中学习编程,而不是从垃圾的互联网教程中学习……不,第 4 点并没有说明使用负数组索引。
  • @AnujJodha 您链接的页面是“用于竞争性编程的 C++ 技巧(针对 C++ 11)”,也就是您通常不想用正常的、理想的可读代码编写的东西。虽然真正的问题是索引超出范围。
  • @Lundin 那么,我应该用什么来代替“GeeksForGeeks”呢?
  • @AnujJodha 读一本书。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多