strtok和分段错误的问题
我有两个辅助函数来分解十进制价格格式的字符串,即。 “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, ".")); }
现在,当我运行以下时,我得到一个分段错误:
printf("%u\n", getDollars(string)); printf("%u\n", getCents(string));
然而,当我单独运行它们而没有一个跟随另一个时,它们工作正常。 我在这里想念的是什么? 我是否必须进行某种重置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); }
因为strtok()
修改了输入字符串,所以在调用getDollars()
后无法在getCents()
函数中找到分隔符时会遇到问题。
请注意, strtok()
在找不到分隔符时返回空指针。 您的代码不会检查strtok()
找到了它所寻找的东西 – 这总是有风险的。
您对问题的更新表明您至少了解了strtok()
一些危险(邪恶? strtok()
。 但是,我建议更好的解决方案只使用strchr()
。
首先,我们可以观察到atoi()
将停止转换’ .
‘无论如何,我们可以将getDollars()
简化为:
unsigned getDollars(const char *price) { return(atoi(price)); }
我们可以使用strchr()
– 它不会修改字符串 – 来找到'.'
然后处理它之后的文本:
unsigned getCents(const char *price) { const char *dot = strchr(price, '.'); return((dot == 0) ? 0 : atoi(dot+1)); }
我认为,相当简单得多。
还有一个问题:假设字符串是26.6; 你将不得不比上面的修改后的getCents()
更努力地工作,以获得返回60而不是6.另外,给定26.650,它将返回650,而不是65。
这个:
char price[4] = "2.20";
在price
上省略了nul终结者。 我想你想要这个:
char price[5] = "2.20";
或更好:
char price[] = "2.20";
因此,当您第二次尝试从price
获取令牌时,您将在缓冲区的末尾运行。 你很幸运,每次运行时, getCents()
都不会出现段错误。
在使用strtok
之前,你几乎应该总是复制一个字符串(以避免Jonathan Leffler指出的问题)。