c++使用string来存储float和int
c++ use string to store float and int
假设现在我必须使用string传递一个结构体foo。结构体包含3个部分:一个int,一个float和一个string:
struct foo {
int a;
float b;
string c;
}
我决定写一个简单的包装器来编码和解码这个结构体foo:
string& encode_foo(const foo &input) {
// what do I do here?
// declare a string and fill in 4 bytes for a, 4 bytes for b and then c?
string ret;
ret.append((char*)(&input.a), 4); // This is really ugly, isn't it??
ret.append((char*)(&input.b), 4); // this is also very ugly??
}
foo decode_foo(const string &input) {
// get input.c_str() and cast to int and float?
}
我只是好奇是否有一种优雅的方式来做到这一点?
可能是这样的:
struct foo {
int a;
float b;
string c;
}
std::ostream& operator<<(std::ostream& os, const foo& f) {
return os << f.a << " " << f.b << " " << f.c;
}
std::istream& operator>>(std::istream& is, foo& f) {
return is >> f.a >> f.b >> f.c;
}
std::string encode(const foo& f) {
std::ostringstream oss;
oss << f;
return oss.str();
}
std::string decode(const std::string& s) {
std::istringstream iss( s );
foo f;
iss >> f;
return f;
}
int main() {
foo f;
std::string s=encode(f);
f=decode(s);
}
这样做的好处是:
- 这是一种习惯用法,一种众所周知的模式
- 它还允许您轻松打印对象的值,
std::cout << f
可以选择使用字符串流对结构字段进行编码和解码。这是一个简单的示例(但在更实际的代码中,您应该注意包含空格的字符串等内容):
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
struct foo
{
int a;
float b;
string c;
};
string encode_foo(const foo& f)
{
ostringstream os;
os << f.a << ' ' << f.b << ' ' << f.c;
return os.str();
}
foo decode_foo(const string& s)
{
istringstream is(s);
foo f;
is >> f.a;
is >> f.b;
is >> f.c;
return f;
}
int main()
{
foo f1;
f1.a = 10;
f1.b = 3.14f;
f1.c = "hello";
string s = encode_foo(f1);
foo f2 = decode_foo(s);
cout << f2.a << 'n' << f2.b << 'n' << f2.c << endl;
}
输出:10 3.14 hello
考虑使用ASN.1二进制编码,如DER或PER或协议缓冲区。您可能还会发现这个格式比较表很有用。
基本上,这些将数据标记为"浮点数,4字节"或"整数,8字节",然后写入二进制。这些格式是已知的和标准化的,因此实现可以在任何平台上读取它们。
您可以将它们存储在std::string
中,因为它实际上不需要数据以null终止。然而,字符串的c_str()
函数将不工作,如果数据包含null。
使用std::vector<unsigned char>
存储字节会更容易理解。
警告: 以下代码使用当前平台的端序来混淆数据。如果您将此发送到其他可能没有相同端序和其他相关架构参数的平台,请小心。
我将假设您理解您正在做的是将浮点数的4个字节放入字符串的内存,而不是浮点数的字符串表示。例如,对于值为2的整数,您将字符值' ',' ',' ','2'放入字符串中。这与将'002'写成普通的人类可读字符串不同(第一个字符串是3个null终止符加上一个十进制值为2的字符)。您还直接将浮点数的二进制表示形式注入到字符串中。
如果这是你想要的,那么你最好使用字符串以外的东西来存储值(maybe a std::vector<char>
/std::vector<unsigned char>
)。例如:
std::vector<char>& encode_foo(const foo &input) {
// Note that these loops, as @DeadMG pointed out in comments, can be
// more easily accomplished with vector.insert( ... ), e.g.:
// vector.insert(vector.end(), adata, adata + sizeof(input.a));
std::vector<char> data;
char* adata = (char*)&input.a;
char* bdata = (char*)&input.b;
char* cdata = (char*)input.c.data();
for ( int i = 0; i < sizeof(input.a); ++i) {
data.push_back( *adata );
++adata;
}
for ( int j = 0; j < sizeof(input.b); ++j) {
data.push_back( *bdata );
++adata;
}
for ( int k = 0; k < input.c.length(); ++k) {
data.push_back( *cdata );
++cdata;
}
// Now, data contains the absolute minimum binary
// representation of the structure
// There are probably even simpler ways to do this,
// but the 3 loops are very explicit
// And demonstrate what you want.
// You could consider std::copy or memcpy instead if you need
// More flexibility.
return data;
}
foo decode_foo(const std::vector<char>& input) {
// Because you know the structure ahead of time, you can simply reverse the process
// Here, I'll use memcpy to show how that's used too
foo datafoo;
memcpy( datafoo.a, input.data(), sizeof(datafoo.a) );
// Offset by 4 (which is the typical size of an int
memcpy( datafoo.b, input.data() + sizeof(datafoo.a), sizeof(datafoo.b) );
// Now, we offset by 8, and each byte represents a character
// We can memcpy into a std::string's data and null-terminate it as needed
// By calling resize and telling it it's as big as the leftover data
// minus the size of the other structures
int offset = ( sizeof(datafoo.a) + sizeof(datafoo.b) );
int csize = input.size() - offset;
datafoo.c.resize( csize );
memcpy( datafoo.c.input.data(), input.data() + offset, csize );
// Usually, you don't use memcpy with strings,
// but this should do exactly as you want
return datafoo;
}
这不应该"浪费任何字节或空间",正如你所要求的,但请记住,如果你想要一个二进制表示,你可能应该使用std::vector<char>
作为你的存储。此外,还要研究protobuff和其他数据打包和数据传输协议。您也可以使用上面的std::string,但是请记住,使用std::string加上上面的一些修改将使该字符串在许多程序和例程中表现得不太好,因为strings
期望以null结尾,而c++中数字的二进制表示将为您带来麻烦。
- 没有从阵列<float>到阵列<int>的可行转换
- 为什么我会收到此错误?无法将 {lb, ub} 从<大括号括起来的初始值设定项列表>转换为 float(**)(float*, int)
- 如何将 qml 的文本转换为 float 和 int
- 有没有比static_cast更优雅的从int到float的演员阵容<float>?
- 如何在函数中将字符串和分数存储为(Int 或 float)
- 谷歌测试编译错误 Os X:函数式转换从"int"到"internal::FloatingEq2Matcher"的模糊转换<float>
- 如何使用 std:from_chars 在 C++17 中从字符串转换为 int/float
- 如何修复 E2015 "ambiguity between pow(double,double) and pow(float,int)"
- C++优化从 int 到 float 的数组转换
- 如何在 c++ 中将数据从文件读取到 int/float 值
- 错误:二进制'operator*' 'int [1]'和'float'类型的操作数无效
- 功能使用INT和Float类型作为C 中的参数过载
- 内部字符串/字符如何在 int 和 float 中存储
- 无法将'int*'转换为参数'1'的'float*'
- 将 python list 作为 'float*' 或 'int*' 传递给 C/C++
- 在C++/Visual Studio中,通过给定数据格式(doubles、float、int、1位bools)的UDP发
- 当float转换为int时,此代码中是如何/为什么进行缩小的
- 用 (float&)int works,(float const&)int 转换像 (float)int 代替?
- float(int)const的类型特征
- C ++:此操作做什么:float(int)