所以我正在研究c中的系統呼叫,我正在做這個練習,我必須制作一個簡單的程式來搜索檔案PATH
(有點類似于which
Linux),這就是我所做的:
int main(int ac, char **av)
{
int i = 1;
struct stat buf;
char *_path, *token, *temp;
if (ac < 2)
{
printf("Usage: %s path_to_file ...\n", av[0]);
exit(-1);
}
while (i < ac)
{
if (stat(av[i], &buf) == 0)
{
printf("%s\n", av[i]);
}
else
{
_path = getenv("PATH");
token = strtok(_path, ":");
while (token != NULL)
{
temp = token;
strcat(temp, "/");
strcat(temp, av[i]);
if(stat(temp, &buf) == 0)
{
printf("%s\n", temp);
break;
}
token = strtok(NULL, ":");
}
printf("%s: no %s in (\"%s\")\n", av[0], av[i], _path);
}
i ;
}
return (0);
}
以下是我的問題:
$ ./_which ls
Segmentation fault (core dumped)
如果我按如下方式添加 printf:
while (token != NULL)
{
temp = token;
strcat(temp, "/");
strcat(temp, av[i]);
printf("%s\n", temp);
if(stat(temp, &buf) == 0)
{
printf("%s\n", temp);
break;
}
token = strtok(NULL, ":");
}
然后我可以看到 strtok 永遠不會回傳NULL
,甚至沒有回傳正確的字串。
$ ./_which ls
/ls/ls
/ls/ls
/ls/ls
/ls/ls
/ls/ls
/ls/ls
/ls/ls
/ls/ls
Segmentation fault (core dumped)
我已經仔細檢查了如何使用 strtok 但我找不到我的問題。
uj5u.com熱心網友回復:
strtok 修改第一個引數,每次呼叫它時都會將一個靜態指標移到內部以指向傳遞的引數的另一部分。
所以當你這樣做時
temp = token;
它將 temp 設定為指向傳遞的陣列中的子字串,下次以 NULL 作為第一個引數呼叫它時, temp 將指向陣列中的下一個子字串,除了作為源之外,您不能使用從 strtok 回傳的內容從中復制。
所以首先創建一個足夠大的緩沖區來容納整個路徑。
char path[MAX_PATH 1]={'\0'};
然后 strcat 到那個緩沖區。
strcpy(path, token);
strcat(path, "/");
strcat(path, av[i]);
您的代碼的另一個問題是更改從 getenv() 回傳的內容。首先將其復制到緩沖區,然后在其上呼叫 strtok
例如
char* env = getenv("PATH");
char* fullEnv = malloc(strlen(env) 1);
strcpy(fullEnv,env);
// alternatively use
// char* fullEnv=strdup(getenv("PATH"));
token = strtok(fullEnv, ":");
...
free(fullEnv);
最后的評論,不要用前導下劃線宣告變數,它主要用于內部編譯器變數,可能會導致您難以找到問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/470647.html