2

我想先说我很少用 C 语言进行编程,所以我更愿意知道为什么给定的解决方案有效,而不仅仅是它是什么。

我正在尝试编写一个函数,该函数将采用路径名,并将路径名返回到同一目录中的不同文件。

  "/example/directory/with/image.png" => "/example/directory/with/thumbnail.png"

在阅读了realpathand的示例用法dirname(我正在使用 Linux;如果有跨平台的等价物,请告诉我)之后,我尝试过的是:

#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char *chop_path(char *orig) {
  char buf[PATH_MAX + 1];
  char *res, *dname, *thumb;

  res = realpath(orig, buf);
  if (res) {
    dname = dirname(res);
    thumb = strcat(dname, "/thumbnail.png");
    return thumb;
  }
  return 0;
}

编译它似乎工作,但运行程序

int main(void) {
  char *res = chop_path("original.png");
  if (res) {
    printf("Resulting pathname: %s", res);
  } 
  return 0;
}

给我一个段错误。有什么提示吗?

4

2 回答 2

2

我看到的唯一问题是您的chop_path例程的签名;它应该是

char *chop_path(char *orig) {

您的版本缺少*. 这实际上有很大的不同;如果没有*,您实际上是在将参数字符串dirnamerealpath第一个字符的字符代码解释为数字地址(即指向路径的指针)。这将指向您肯定没有分配的低内存位置;尝试使用它会导致“分段错误”错误,这实际上意味着您正在尝试访问不允许的内存。

另一个问题是该dirname()函数是在 中声明的libgen.h,而您没有包括在内。如果您不包含该标头,编译器会假定dirname()返回int而不是指针,并且在 64 位架构上,来自函数的 64 位返回值被削减为 32 位,错误的指针被分配给dname,并且这将导致您的 seg 错误。

于 2012-04-30T03:29:13.890 回答
1

如果您不想使用dirname, realpath, 不需要的字符串缓冲区和字符串操作等 - 您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#define FILE_MAX 100

void chop_path(char path_name[], char new_file[]) {
    int len = strlen(path_name);
    int i;

    for (i=len-1; i>0 ; i--) {
        if (path_name[i] == '/') {
            strcpy(path_name+i+1, new_file);
            break;
        }   
    }   

    return;
}

int main(void) {
    char path[PATH_MAX + 1] = "/this/is/a/path/filename.c";
    char new_file[FILE_MAX] = "newfilename.txt";

    printf("old : %s \n", path);
    chop_path(path, new_file);
    printf("new : %s \n", path);

    return 0;
}

输出:

$ gcc path.c 
$ ./a.out 
old : /this/is/a/path/filename.c 
new : /this/is/a/path/newfilename.txt 
$ 
于 2012-04-30T03:51:29.183 回答