Chr*_*ris 6 c strtok segmentation-fault
我有两个辅助函数来分解十进制价格格式的字符串,即."23.00","2.30"
考虑一下:
char price[4] = "2.20";
unsigned getDollars(char *price)
{
return atoi(strtok(price, "."));
}
unsigned getCents(char *price)
{
strtok(price, ".");
return atoi(strtok(NULL, "."));
}
Run Code Online (Sandbox Code Playgroud)
现在,当我运行以下时,我得到一个分段错误:
printf("%u\n", getDollars(string));
printf("%u\n", getCents(string));
Run Code Online (Sandbox Code Playgroud)
然而,当我单独运行它们而没有一个跟随另一个时,它们工作正常.我在这里错过了什么?我必须做某种重置strtok ??
我的解决方案
根据我在下面选择的答案中获得的关于strtok的知识,我更改了辅助函数的实现,以便它们首先复制传入的字符串,从而屏蔽原始字符串并防止出现此问题:
#define MAX_PRICE_LEN 5 /* Assumes no prices goes over 99.99 */
unsigned getDollars(char *price)
{
/* Copy the string to prevent strtok from changing the original */
char copy[MAX_PRICE_LEN];
char tok[MAX_PRICE_LEN];
/* Create a copy of the original string */
strcpy(copy, price);
strcpy(tok, strtok(copy, "."));
/* Return 0 if format was wrong */
if(tok == NULL) return 0;
else return atoi(tok);
}
unsigned getCents(char *price)
{
char copy[MAX_PRICE_LEN];
char tok[MAX_PRICE_LEN];
strcpy(copy, price);
/* Skip this first part of the price */
strtok(copy, ".");
strcpy(tok, strtok(NULL, "."));
/* Return 0 if format was wrong */
if(tok == NULL) return 0;
else return atoi(tok);
}
Run Code Online (Sandbox Code Playgroud)
因为strtok()修改了输入字符串,所以在getCents()调用后无法在函数中找到分隔符时会遇到问题getDollars().
请注意,strtok()当找不到分隔符时返回空指针.您的代码不会检查strtok()找到它正在寻找的东西 - 这总是有风险的.
您对该问题的更新表明您至少了解了一些危险(邪恶?)strtok().但是,我建议使用更好的解决方案strchr().
首先,我们可以观察到,无论如何atoi()都会停止转换.,所以我们可以简化
getDollars()为:
unsigned getDollars(const char *price)
{
return(atoi(price));
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用strchr()- 不修改字符串 - 来查找'.'然后处理文本:
unsigned getCents(const char *price)
{
const char *dot = strchr(price, '.');
return((dot == 0) ? 0 : atoi(dot+1));
}
Run Code Online (Sandbox Code Playgroud)
我想,相当简单得多.
还有一个问题:假设字符串是26.6; 你将不得不比getCents()上面的修改更努力地工作以使得返回60而不是6.另外,给定26.650,它将返回650而不是65.
这个:
char price[4] = "2.20";
Run Code Online (Sandbox Code Playgroud)
留下了nul终结符price.我想你想要这个:
char price[5] = "2.20";
Run Code Online (Sandbox Code Playgroud)
或更好:
char price[] = "2.20";
Run Code Online (Sandbox Code Playgroud)
因此,当您第二次尝试获取令牌时,您将在缓冲区的末尾运行price.你很幸运,getCents()每次运行它都不会出现段错误.
在使用strtok它之前,你几乎应该总是复制一个字符串(以避免Jonathan Leffler指出的问题).