【问题标题】:Problem with strtok and segmentation faultstrtok 和分段错误的问题
【发布时间】:2011-05-08 03:24:44
【问题描述】:

我有两个辅助函数来分解十进制价格格式的字符串,即。 "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);
}

【问题讨论】:

    标签: c segmentation-fault strtok


    【解决方案1】:

    因为strtok()修改了输入字符串,所以调用getDollars()后在getCents()函数中找不到分隔符会遇到问题。

    请注意,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。

    【讨论】:

    • 感谢您的提示,我已经接受了。
    【解决方案2】:

    这个:

    char price[4] = "2.20";
    

    省略price 上的 nul 终止符。我想你想要这个:

    char price[5] = "2.20";
    

    或更好:

    char price[] = "2.20";
    

    因此,当您第二次尝试从price 中获取令牌时,您将跑出缓冲区的末尾。您很幸运,getCents() 每次运行时都不会出现段错误。

    在使用 strtok 之前,您几乎应该总是复制一个字符串(以避免 Jonathan Leffler 指出的问题)。

    【讨论】:

    • 我认为这两个答案/问题都是因素。我的是在同一字符串上(重新)使用strtok() 的一般问题。你的情况是这个特殊的非字符串的特殊情况。
    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多