【问题标题】:typecasting char pointer to float in C [duplicate]在C中将char指针类型转换为浮点数[重复]
【发布时间】:2013-09-13 00:05:41
【问题描述】:

我有一个包含 ff 数据的平面文件:

date;quantity;price;item

我想使用以下结构创建数据记录:

typedef struct {
  char * date, * item;
  int quantity;
  float price, total;
} expense_record;

我创建了以下初始化方法:

expense_record initialize(char * date, int quantity, char *price, char *item) {
  expense_record e;
  e.date = date;
  e.quantity = quantity;
  e.item = item;
  /* set price */
  return e;
}

我的问题是如何从char *price 将价格设置为float(根据结构的要求)。我得到的最接近的,即没有产生编译器错误的是

 e.price = *(float *)price

但这会导致分段错误。

谢谢!

【问题讨论】:

  • 你将什么作为参数传递给initialize price
  • 所以您有一个人类可读格式的价格,并希望将其转换为浮点数?在这种情况下,您必须对其进行解析,如this question ...类型转换不是用于此目的...
  • 你用quantity做什么?
  • @us2012 @ppeterka66 是的,我有一个人类可读格式的price,例如10.50 作为char * price 传递给initialize 方法。
  • @Rohan,我会想在设置price 之后使用quantity 来计算total,即e.total = quantity*price

标签: c parsing casting


【解决方案1】:

您正在寻找 strtod strtof 库函数(包括 <stdlib.h>)。相关地,如果调用代码使用 strtoul 以外的任何东西将 quantity 从文本转换为 int,这可能是一个错误(我能想到的唯一例外是,如果由于某种原因 quantity 可以是否定的,那么你会想要strtol)。

【讨论】:

  • 我接受了这个答案,因为这解决了上面关于将文本/字符串“转换”为浮点数的主要问题。不过,我使用的是strtof,而不是strod
  • 在这种情况下,这不称为“铸造”。这将是“解析”。
  • 我,呃,倾向于忘记strtof 的存在(因为类似的strtoi 不存在)。不过你说的很对。
【解决方案2】:

要将文本转换为float,请使用strtof()strtod() 更适合 double
您的初始化例程可能需要“日期”等的副本
建议的改进例程如下:

expense_record initialize(const char * date, int quantity, const char *price, const char *item) {
  expense_record e;
  char *endptr;
  e.date = strdup(date);
  e.quantity = quantity;
  e.item = strdup(item);
  if (!e.date || !e.item) {
    ; // handle out-of -memory
  }
  e.price = strtof(price, &endptr); 
  if (*endptr) {
    ; // handle price syntax error
  }
  return e;
}

顺便说一句:建议进行额外的更改以将目标记录传递到您的初始化中,但这会进入更高级别的架构。

【讨论】:

  • 虽然我的问题仅限于转换或转换 char *,但您发布的答案提供了对代码的更彻底审查。感谢您提供额外的见解。为什么你会建议日期和其他人的copy?另外,我尝试了e.total = e.quantity*e.price,但没有得到预期的结果(非常大的数字)。
  • 需要查看调用initialize 的代码才能正确满足(或不满足)strdup() 的需求。我怀疑你的代码会。
  • 样本错误e.totale.quantitye.price 是什么值? e.quantity 可能无效或缺少 strtof() 的原型。
【解决方案3】:

您遇到分段错误,因为 float 有 4 个字节:当您创建 *(float *)price 时,您正在访问价格的前 4 个字节,因此如果价格的大小小于 4 个字符,您将拥有一个错误。

我认为您能做的最好的事情就是在解析数据时读取float 而不是char *(就像我假设你对数量所做的那样),例如fscanf (pFile, "%s;%d;%f;%s", &date, &quantity, &price, &item);

或使用strtod 转换为initialize 中的float,而不是进行强制转换。

【讨论】:

  • 如果“价格的大小小于 4 个字符”,您不能指望发生崩溃;相反,即使该地址有sizeof(float)字节的可访问内存(未对齐,加载启用FPU异常的信号NaN,......),它也可能崩溃的几个原因;还有,scanf should never be used.
  • 你发现了两个关于记忆的新有趣话题,谢谢。但是关于 scanf 我不同意:如果您不采取适当的预防措施,也许不是最安全的,但是因为它在 stdlib 中对我来说是有效的。此外,当这个问题是关于 c 时,关于 qt 的查询不是最合适的论据。
  • C 标准库非常古老,包含许多至少设计不佳的东西,最坏的情况是灾难性的危险。没有人会反对永远不应该使用gets 的断言,不是吗? 同样不可能安全地使用scanf(由于“输入溢出导致未定义行为”问题)。我的那个旧答案包含对 为什么 scanf 永远不应该使用的最清楚的解释;我承认关于做什么的建议在 this 上下文中没有帮助,但是有很多明显的选择(你提到了一个:strtod)。
  • 好的,scanf 读取字符串 (%s) 是不安全的,这会产生条目溢出,但是对于所有其他数据类型我不太确定,例如,因为 scanf 在内部使用了 strtod对于读取浮点数,scanf("%f", &number) 与调用 strtod 一样安全,对于更复杂的条目,scanf 可以提供更多函数 scanf("%f;%f", &n1, &n2)
  • 不,事实上,scanf("%f", &n); 安全。输入溢出会导致未定义的行为。如果用户键入太多数字,则允许 C 运行时崩溃strtof 不是这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多