【问题标题】:C converting string/char input to floating pointC将字符串/字符输入转换为浮点
【发布时间】:2014-02-26 02:13:35
【问题描述】:

我正在用C编写一个程序,其中一个要求是用户输入一个数字作为字符串值,然后程序必须将其转换为浮点格式,然后对该值执行各种操作。我似乎无法弄清楚如何简单地将输入字符串转换为数字。我将如何编写第一块这样的代码?我知道有类似的帖子,但它们没有帮助。我需要相当简单地做到这一点,而且我不想#include 除了...

#include <stdio.h>

int main(int argc,char* argv[]) { 
  /*having issues with this in particular...*/

  int number;    
  int newNumber;
  int i;
  printf("Enter a number in decimal...");
  scanf("%d",&number);

  /*                        */

  printf("%d in binary is: ",number);
  for(i = 31;i >= 0;i--) {
    newNumber = (number>>i);
    if(newNumber & 1) {
      printf("1");
    }
    else {
  printf("0");
}
   }  


  return 0;
}

谢谢!

【问题讨论】:

  • 代码和问题没有关系!!!。
  • 您遇到了什么问题,您已经有scanf("%d"…) 可以将输入字符串转换为数字?
  • 您的代码似乎“工作” - 因为它读取输入并产生输出。您可以考虑在 printf 语句的末尾添加 \n。到底什么不适合你?考虑使用8*sizeof(int)-1 而不是31。您不会提前知道系统上的 int 有多大。
  • 根据您到目前为止收到的答案,在我看来,您可能需要更清楚地解释您的“问题”。在上面的代码中究竟是什么不适合你? “有问题”有点模糊。也许您可以编辑您的问题:“当我输入 xxx 时,我想要 yyy 而不是 zzz”。
  • 我的意思是我需要用户的输入是“字符串”类型,然后我需要将其转换为“浮点”类型。因此,例如“int number”将变为“char[100] number”。

标签: c string floating-point


【解决方案1】:

跟进我的评论:

您的代码似乎“有效” - 因为它读取输入并生成 输出。您可以考虑在 printf 末尾添加 \n 陈述。到底什么不适合你?考虑使用 8*sizeof(int)-1 而不是 31。你不提前知道有多大 您的系统上有一个 int。

只需稍加改动,您的代码就非常适合我:

#include <stdio.h>

int main(int argc,char* argv[]) {
  /*having issues with this in particular...*/

  int number;
  int newNumber;
  int i;
  printf("Enter a number in decimal...\n"); // <<< added a newline
  scanf("%d",&number);

  /*                        */

  printf("%d in binary is: ",number);
  for(i = sizeof(int)*8 - 1;i >= 0;i--) {  // make sure `i` starts with the right size
    newNumber = (number>>i);
    if(newNumber & 1) {
      printf("1");
    }
    else {
      printf("0");
    }

  }

  printf("\n");  // <<< print a newline

  return 0;
}

当我运行它时:

Enter a number in decimal...
123
123 in binary is: 00000000000000000000000001111011

注意 - 您必须输入一个整数才能使其工作。如果您需要您的代码对输入中的用户“错误”更加健壮,最好的办法是将输入作为字符串读取,然后进行更多解析。例如:

char buffer[100];
printf("enter an integer:\n");
fgets(buffer, 100, stdin);
// now you can look for spaces, letters, anything you want to skip, in the string
// you could even use sscanf().
// scanf() is a terribly fragile function to use, especially with "free form user input".
if(sscanf(buffer, "%d", &number) == 1) {
  // successfully converted number... run your code
} else {
  printf("unable to convert input to a number!\n%s\n", buffer);
  return 0;
}

another note 重新阅读您的问题,您说“程序必须转换为 浮点数。这意味着您应该这样做

float fnumber;
sscanf(buffer, "%f", &fnumber);

double dnumber;
sscanf(buffer, "%lf", &dnumber);

进行转换。但是,如果要打印为二进制,则需要将数字从浮点数转换为无符号整数 - 浮点数的移位操作没有明确定义。所以

unsigned int *intPtr, number;
intPtr = (unsigned int*) *fnumber; // this is hairy but it works
number = *intPtr;

现在像以前一样使用number - 您将能够打印出浮点数的二进制等价物。有人会抱怨以上内容不“符合标准”。如果您创建了一个联合,他们可能更喜欢它:

union f2i
{
  float fvalue;
  unsigned int ivalue;
} Values;

然后将输入分配给Values.fvalue,并使用Values.ivalue打印出二进制数。它仍然是一个黑客......

【讨论】:

  • 我知道它确实有效,但是给我的分配指定用户输入需要是一个字符串...我知道,它很挑剔
  • 请注意,如果使用 scanf() 时输入超出参数范围,则无法安全地从错误中恢复,因为超出范围的转换会导致未定义的行为 (C.11第 7.21.6.2 节第 10 段)。
  • 非常感谢!这很有帮助
  • @jhx - 我完全同意你的看法。因此我在答案中的评论:// scanf() is a terribly fragile function to use, especially with "free form user input". 你更明确地陈述它,并提供参考。感谢那!我希望 scanf()gets() 将被排除在课程之外(也可能是标准)。无非就是麻烦。
【解决方案2】:

您可以使用strtod()。将数字作为字符串读入缓冲区(比如fgets()),然后执行:

double x;
char *endptr;
errno = 0;
x = strtod(buffer, &endptr);
if (endptr == buffer) {
    //... parse error or empty input ...
} else if (*endptr != '\n' && *endptr != '\0') {
    //... parse error extraneous data ...
} else if ((x == HUGE_VAL || x == -HUGE_VAL) && errno != 0) {
    //... error overflow ...
} else if (x <= DBL_MIN && x >= -DBL_MIN) {
    if (errno != 0) {
        //... error underflow (detected) ....
    } else {
        // ... underflow still possible, but is undiagnosed ...
    }
}

通过检查x 返回的值以及errno 是否已设置来完成错误检查。通过检查endptr 来完成解析错误。 C 标准说下溢检测是实现定义的(C.11 §7.22.1.3 ¶10)。

【讨论】:

  • 支持可靠的错误检查方法。如果用户可以输入垃圾,他们就会 - 所以你最好确保你的代码可以应付。
  • 想法:如果buffer 的值为"\n",则此代码不会报错。我认为char* endptr; x = strtod(buffer, &amp;endptr); if (buffer == endptr) fail(); 捕获所有空白或"" 的输入。
  • @chux:谢谢你的提示。
  • 您已经很好地解决了上溢/下溢问题!下溢 的实现定义的行为是 一个泥泞的角落案例 - 太糟糕了。对于fgets()char buffer 设为多大仍然是一个令人讨厌的问题。可能视情况而定。
【解决方案3】:

使用 GCC 4.7.3 测试的简单 scanf 示例

$ gcc -Wall -Wextra -pedantic -std=c99 cstring-double.c

#include <stdio.h>

int main() {
  double v;
  int err;

  err = scanf("%lf", &v);
  if (1 == err) {
    printf("%lf\n", v);
  } else {
    printf("read failed\n"); }

  return 0; }

【讨论】:

  • 请注意,如果使用 scanf() 时输入超出参数范围,则无法安全地从错误中恢复,因为超出范围的转换会导致未定义的行为 (C.11第 7.21.6.2 节第 10 段)。
【解决方案4】:

只需使用 atof。 cplusplus documentation

【讨论】:

  • 不要使用atof(),应该使用strtod()
  • 完全主观,编码没有绝对性。 strtod() 肯定更安全,但 atof() 仍然是他问题的正确答案...如果您没有注意到,我确实添加了文档。
  • 我同意这是一个有效的答案,所以向我 +1。但是,请注意atof() 不会报告任何错误。
  • 来自问题:“我不想#include 除了...之外的任何东西” - 并且atof() 需要#include &lt;stdlib.h&gt;。所以不是最优的。不足以让我投反对票 - 但不是最优的。
  • @Floris:对于这部分需求,唯一安全的选择是仅使用&lt;stdio.h&gt; 中可用的功能来实现strtod(),这甚至不是最优的。
猜你喜欢
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多