将双精度转换为字符数组 C++

Posted

技术标签:

【中文标题】将双精度转换为字符数组 C++【英文标题】:Convert double to Char Array C++ 【发布时间】:2018-06-06 00:12:37 【问题描述】:

我正在尝试将 double 转换(并舍入)为 char 数组,而不首先在 double 上使用 std::to_string 进行转换。但是,我收到的是随机记忆文本。我究竟做错了什么?

这是我的代码:

double d = 1.0929998; 
d = std::round(d * 100) / 100;

char s[sizeof(d)];
std::memcpy(s,&d,sizeof(d));

结果:

s: q=×£pñ?

预期值:

s: 1.09

【问题讨论】:

使用to_string有什么问题? A double 不是 char 的数组。如果就这么简单,就不需要std::to_string。将浮点值转换为文本字符串涉及大量工作。对于更简单的问题,尝试将int 值转换为字符串。一旦你完成了这项工作,你就可以开始考虑浮点转换。或者您可以只使用内置的库设施。上次我写了一个浮点到文本的转换函数,花了好几个星期。这不是初学者的任务。 如果std::to_string 如此可恶,也许像sprintf 这样的C API 可以满足您的需求? 您可能会发现不想使用 sprintf 的人对这个问题的回答很有趣。几乎做了一些数学运算来获得幅度,然后通过重复除法一次获得一个数字来表示字符串。 ***.com/questions/2302969/convert-a-float-to-a-string 【参考方案1】:

您正在将double 的文字字节翻译成chars。 double 值是二进制表示(通常类似于IEEE 754),而char 是字符的二进制表示(通常基于ASCII)。这两个不兼容。

不幸的是,这意味着您必须进行某种转换过程。要么是你说不想做的std::to_string(),要么是更复杂的std::stringbuf(无论如何都会在后台调用std::to_string()

【讨论】:

所以我在看类似的东西:double d = 1.0909998; d = std::round(d * 100) / 100;字符 [4]; std::strncpy(s,std::to_string(d).c_str(), 4);对于带有舍入截断的双重转换? @Delrog 我建议使用snprintf 而不是strncpy+to_string 您可以让 STL 为您进行舍入。使用std::ostringstream,查看std::fixedstd::setprecision() 流操作符,例如:ostringstream oss; oss << fixed << setprecision(3) << d; string s = oss.str(); 谢谢,我通常会尽量避开字符串流,因为我认为它们会带来开销。他们有吗?有没有办法一目了然地确定标准库函数的内存/性能成本(cppreference 或替代文档)?【参考方案2】:

您正在将double(数字的二进制表示)复制到char 数组中;没有理由这些字节应该对应于数字字符。

【讨论】:

【参考方案3】:

这未经测试,但您可以尝试:

std::string to_string(double x)

    std::ostringstream ss;
    ss << x;
    return ss.str();

然后您可以将返回的字符串的字符放入一个 char 数组中,如下所示:

std::string str = to_string(doubleValue);
char digits[str.length()];

然后,感谢 Remy Lebeau 的评论,您可以这样做:

std::strncpy(digits, to_string(doubleValue).c_str(), sizeof(digits))

或者这个:

to_string(doubleValue).copy(digits, sizeof(digits))

【讨论】:

这是等待发生的缓冲区溢出。至少使用std::setprecision() 来控制ostringstream 输出的位数 您的编辑仍有风险。 std::strcpy() 不做任何边界检查。至少使用std::strncpy()std::string::copy() 代替,这样您就可以指定char[] 缓冲区的最大大小,例如:std::strncpy(digits, to_string(doubleValue).c_str(), sizeof(digits))to_string(doubleValue).copy(digits, sizeof(digits)) @Remy Lebeau 好的,我会更改的,谢谢您指出。【参考方案4】:

如果您想在不使用to_string 的情况下手动转换,您将不得不一次提取一个数字。 double 不会作为一组字符存储在内存中,因此您不能只是复制内存并希望一切正常。 (有关如何解释双打的更多信息,请参阅here)。

【讨论】:

【参考方案5】:

先do this:

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

这会将双精度 dbl 转换为字符串 str

然后你可以将它转换成这样的字符数组:

char *cstr = new char[str.length()+1];
str.copy(cstr, str.length());
cstr[str.length()] = '\0';
// use cstr as needed...
delete[] cstr;

或者,简单地说:

const char *cstr = str.c_str();
// use cstr as needed...

【讨论】:

这与使用std::to_string 像问题中提到的OP 有何不同? @scohe001 to_string 是 C++11。与 stringstream 不同,较旧的编译器将不支持它。【参考方案6】:

在不使用to_string的情况下,您自己的转换过程可能如下:

char* to_char_array(double num_double, int decimal_place)

    int num_int = std::round(num_double * pow(10, decimal_place));
    int sign = num_int < 0 ? 1 : 0;
    num_int = abs(num_int);

    if (num_int == 0)
    
        char* s = (char*)malloc(decimal_place + 3);
        s[0] = '0';
        s[1] = '.';
        for (int i = 2; i < decimal_place + 2; i++)
            s[i] = '0';
        s[decimal_place + 2] = '\0';
        return s;
    

    int digit_count = 1;
    int n = num_int;
    if (n >= 100000000)  digit_count += 8; n /= 100000000; 
    if (n >= 10000)  digit_count += 4; n /= 10000; 
    if (n >= 100)  digit_count += 2; n /= 100; 
    if (n >= 10)  digit_count++; 

    int size = digit_count + 1 + (decimal_place > 0 ? 1 : 0) + sign;
    char* s = (char*)malloc(size);

    for (int i = 0, integer = num_int; integer != 0; integer /= 10) 
        s[size - 2 - i++] = integer % 10 + 48;
        if (decimal_place > 0 && i == decimal_place)
            s[size - 2 - i++] = '.';
    
    s[size - 1] = '\0';
    if (sign)
        s[0] = '-';
    return s;


void main()

    double d = -12.268904;
    char* s = to_char_array(d, 3);
    cout << "double: " << d << " - char array: " << s << endl;
    system("pause");

【讨论】:

【参考方案7】:

这样做:

  #include <iostream>
  #include <string>
  #include <sstream>

  using namespace std;

  int main()
  
      double a=23.25;
      char b[12];
      stringstream ss;

      ss << a;
      ss >> b;
      cout << b << endl;

      return 0;
  

或者这个:

  #include <iostream>
  #include <string>
  #include <sstream>
  #include <stdio.h>


  using namespace std;

  int main()
  


  double a=23.25;
  char b[12];
  stringstream ss  ;
  ss<<a;
  sprintf(b,ss.str().c_str());
  cout<<b<<endl;
  return 0;

或者这个:

here don't forget to
 #include<bits/stdc++.h>
  
  double a=23.25;
  char b[12];
  stringstream ss  ;
  ss<<a;
  strcpy(b,ss.str().c_str());
  cout<<b<<endl;
  return 0;

【讨论】:

如果您解释为什么每组代码都能解决问题以及每个代码之间的差异(例如性能、易用性等。

以上是关于将双精度转换为字符数组 C++的主要内容,如果未能解决你的问题,请参考以下文章

如何将双精度数组转换为 JS 数组?

如何将双数组列表转换为位图? [关闭]

可可 - 将双精度转换为字符串

将双精度转换为字符串

SQL Server CE 转换/将双精度转换为字符串

Java:将双精度数转换为字符串