Convert structor to string

How to convert structor to string?
Write conversion code.

For more details, provide more question.
Here's a way to convert a struct to a string.

1
2
3
4
5
6
7
8
9
	#include <ctime>
	std::string myString;
	//Time computations
	struct tm LocalTime;
	__time32_t aclock;
	_time32( &aclock );   // Get time in seconds.
	_localtime32_s( &LocalTime, &aclock );   // Convert time to struct tm form.

	asctime_s(&myString,LocalTime);
How about the structure on data not on time?
1
2
3
4
5
6
7
8
9
std::string structToString (someStructureType* theStruct)
{
  char* tempCstring = new char[sizeof(someStructureType)+1];
  memcpy(tempCstring, theStruct, sizeof(someStructureType));
  tempCstring[sizeof(someStructureType)+1] = '0';
  std::string returnVal(tempCstring, sizeof(someStructureType));
  delete tempCstring;
  return returnVal;
}



This code is horrific. It turns any structure into a string. There is no interpretation, just blind copy. If there is a zero value in the data somewhere, it'll might get truncated (and I've stuck one on the end of the C style string used as a halfway-house, just to be sure it's terminated, out of a nervous reflex); possibly the string constructor I've used ignores zero-termination of C style strings (as I specified a size). I'd have to look it up (or just experiment) to be sure.

Make no mistake; what this does is truly hideous and is asking for all sorts of trouble.
Last edited on
@OP: Really ¿what do you want to do? ¿a serialization?

'\0' and delete []
Off topic: ¿Can that be done directly in the std::string?
Off topic: ¿Can that be done directly in the std::string?


Right now, don't know. Banged it all out in sixty seconds before going to Friday pub. When I sober up, I'll either tidy it up, or wonder what I was thinking even answering :)

Copying the bytes of the structure into the buffer of a string does not look like conversion to me. If you want to deal with the bytes directly, you'd be better off just writingthe bytes directly to file, e.g. ofsteam::write(), so it's clear what's going on.

In addition to 0 bytes embedded in the struct "string", which Mochops mentioned, there would also be a big problem with pointer members.

As ne555 asked, what is the conversion required for? Is it for serialization? Or just for display purposes?

Whatever, you will need to code a structure function. Probably easiest with the help of ostringstream (if you like iostreams?)

Andy
Last edited on
I just thought of another method:
1
2
3
4
5
std::string Struct2String(void* StructIn)
{
    std::string* StringOut = static_case<std::string*>(StructIn);
    return StringOut;
}


Would that work? An easier alternative might be a character array:

1
2
3
4
5
char Struct2String(void* StructIn)
{
    char* StringOut = static_case<std::string*>(StructIn);
    return StringOut;
}
Last edited on
8-0 Has this become a competition to come up with the scariest possible bit of code???

Telling the compiler that a random bit of memory is a std::string would just end in tears!!

The char* route is not as bad, but as char = byte, you're just saying you're going to treat the struct's data as bytes (it still can't be treated as a null terminated string)

Neither actually converts the struct to a string.

Andy
Last edited on
Neither actually converts the struct to a string.


Not a meaningful string, no, but then there is no general way to convert a struct to a string. It does convert it to a completely legal string :)
To me a legal string is a series of printible chars (letter, number, punctuation, plus '\r', '\n', '\t', ... ending with a single '\0'. That is not what will happen if you randomly cast emory to a "string".

As there is no general way to convert to a string, you need to write you own conversion routine, akin to ltoa() which - as you no doubt know - converts a long to a string. Unlike (char*)some_long_value!
Last edited on
As Moschops said, there is no general way. If a specific question was asked, we could give a specific and meaningful solution. This is about as general as it can get so it could be scary indeed!
How about serializing as a byte string?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;

struct Example
{
	int  index;
	char name[16];
	bool registered;
	bool suspended;
};

void dumpExample(ostream& os, const char* var_name, const Example& ex)
{
	os << "[Example : name = \"" << var_name << "\" size = " << sizeof(Example) << "]" << endl
	   << "- index      = " << ex.index      << endl
	   << "- name       = " << ex.name       << endl
	   << "- registered = " << ex.registered << endl
	   << "- suspended  = " << ex.suspended  << endl;
}

// wrap function with macro which uses stringizing operator
#define DUMP_EXPAMPLE(s, v) dumpExample(s, #v, v)

bool saveAsByteString(ostream& os, const unsigned char* pch, int size)
{
	bool ret = true; // in real code, there would be error handling!

	ostream::fmtflags old_flags = os.flags();
	char old_fill  = os.fill();

	os << hex << setfill('0');

	// could break line every 16/? bytes?
	for(int idx = 0; size > idx; ++idx)
	{
		if(0 < idx)
			os << ' ';
		// force output to use hex version of ascii code
		os << "0x" << setw(2) << static_cast<int>(pch[idx]);
	}

	os.flags(old_flags);
	os.fill(old_fill);

	return ret;
}

bool readAsByteString(istream& is, unsigned char* pch, int size)
{
	bool ret = true; // in real code, there would be more error handling!

	// get the line we want to process
	// could handle multi-line easy enough
	string line;
	getline(is, line); // error not handled, etc

	istringstream iss_convert(line);
	iss_convert >> hex;

	// read in unsigned ints, as wrote out hex version of ascii code rather
	// than the actual char (some of which would have been control
	// codes, etc)
	unsigned int u   = 0;
	int          idx = 0;

	while((iss_convert >> u) && (idx < size) && ret)
	{
		if((0x00 <= u) && (0xff >= u))
			pch[idx++] = static_cast<unsigned char>(u);
		else
			ret = false;
	}

	// if nothing went wrong in the loop, make sure we got the right
	// number of bytes.
	if(ret)
	{
		ret = iss_convert.eof() && (size == idx);
	}

	return ret;
}

// Test using stringstream as too lazy to code file reading...
void Test()
{
	bool ret = false;

	const Example ex = {
		11,        // index;
		"Tintin",  // name
		true,      // registered;
		false      // suspended;
	};

	cout << "Start:" << endl
		 << endl;
	DUMP_EXPAMPLE(cout, ex);
	cout << endl;

	ostringstream oss;

	cout << "=> saveAsByteString()" << endl;
	ret = saveAsByteString(oss, reinterpret_cast<const unsigned char*>(&ex), sizeof(Example));
	cout << endl;

	if(ret)
	{
		cout << "Ok!" << endl
			 << endl;

		string result = oss.str();
		// to force failure
		//result += " 0x66 0x60"; // too long
		//result.resize(result.length() - 4); // too short
		// Note: if you loose only a bit of the last byte
		// e.g. 0xC cf 0xCC then error is not detected.
		// Prob need to write the lenth of the string to file
		// so can check it's all read back. Or use explicit
		// markers for begin and end of data?

		cout << "Result:" << endl
			 << endl
			 << result << endl
			 << endl;

		istringstream iss(result);

		Example chk = {0};

		cout << "=> readAsByteString()" << endl;
		ret = readAsByteString(iss, reinterpret_cast<unsigned char*>(&chk), sizeof(Example));
		cout << endl;

		if(ret)
		{
			cout << "Ok!" << endl
				 << endl;

			cout << "Do structs match? = " << (0 == memcmp(&ex, &chk, sizeof(Example))) << endl
				 << endl;

			cout << "Check:" << endl
				 << endl;
			DUMP_EXPAMPLE(cout, chk);
			cout << endl;
		}
		else
		{
			cerr << "Erk!" << endl
				 << "readAsByteString failed?" << endl;
		}
	}
	else
	{
		cerr << "Erk!" << endl
			 << "saveAsByteString failed?" << endl;
	}

	cout << "Done." << endl;
}

int main()
{
	cout << boolalpha;

	Test();

	return 0;
}


The results for VC++2008 are:

Start:

[Example : name = "ex" size = 24]
- index      = 11
- name       = Tintin
- registered = true
- suspended  = false

=> saveAsByteString()

Ok!

Result:

0x0b 0x00 0x00 0x00 0x54 0x69 0x6e 0x74 0x69 0x6e 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x01 0x00 0xcc 0xcc

=> readAsByteString()

Ok!

Do structs match? = true

Check:

[Example : name = "chk" size = 24]
- index      = 11
- name       = Tintin
- registered = true
- suspended  = false

Done.


Last edited on

http://yaml.org/


never used it hough.
Topic archived. No new replies allowed.