6

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

2 回答 2

5

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

请注意,strtok()当它找不到分隔符时返回一个空指针。您的代码不会检查是否strtok()找到了它正在寻找的东西——这总是有风险的。


您对问题的更新表明您至少了解了strtok(). 但是,我建议更好的解决方案是使用 just 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。

于 2011-05-08T03:32:29.930 回答
5

这:

char price[4] = "2.20";

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

char price[5] = "2.20";

或更好:

char price[] = "2.20";

因此,当您第二次尝试从price. 您只是很幸运,getCents()每次运行它时都不会出现段错误。

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

于 2011-05-08T03:32:50.700 回答