I have an array of type uint8_t. I want to create a string that concatenates each element of the array. Here is my attempt using an ostringstream, but the string seems to be empty afterward.
std::string key = "";
std::ostringstream convert;
for (int a = 0; a < key_size_; a++) {
convert << key_arr[a]
key.append(convert.str());
}
cout << key << endl;
Try this:
std::ostringstream convert;
for (int a = 0; a < key_size_; a++) {
convert << (int)key[a];
}
std::string key_string = convert.str();
std::cout << key_string << std::endl;
The ostringstream class is like a string builder. You can append values to it, and when you're done you can call it's .str() method to get a std::string that contains everything you put into it.
You need to cast the uint8_t values to int before you add them to the ostringstream because if you don't it will treat them as chars. On the other hand, if they do represent chars, you need to remove the (int) cast to see the actual characters.
EDIT: If your array contains 0x1F 0x1F 0x1F and you want your string to be 1F1F1F, you can use std::uppercase and std::hex manipulators, like this:
std::ostringstream convert;
for (int a = 0; a < key_size_; a++) {
convert << std::uppercase << std::hex << (int)key[a];
}
If you want to go back to decimal and lowercase, you need to use std::nouppercase and std::dec.
Probably the easiest way is
uint8_t arr[];
// ...
std::string str = reinterpret_cast<char *>(arr);
or C-style:
std::string str = (char *) arr;
Related
For example, would there be a way that I could do the following?
//string converted = ConvertToVirtual(int numberToConvert);
string converted = ConvertToVirtual(12);
converted would then hold "0x31 0x32".
Ideally, the number passed into the function could be of any number of digits, but for now, I am just wondering if this is possible, and how I could go about it?
Thank you very much in advance (:
Something like this should work:
#include <ios>
std::string ConvertToVirtual(int num)
{
std::string numStr = std::to_string(num);
std::stringstream output;
output << std::hex; // this will convert all following data to hex
for (const char& c : str)
{
output << "0x" << (int)c << " ";
}
return output.str(); // extract string from stringstream
}
I am using C++ on Arduino.
Suppose I have a stream of binary data;
binary data: 0xFF, 0x00, 0x01, 0xCC
I want to convert it to the ASCII equivalent and store it in a String object type.
The converted string should look like this "FF0001CC".
Here are some draft code.
char buffer[100];
String myString;
for (int i=0; i < numBytes; i++)
{
//assume buffer contains some binary data at this point
myString += String(buffer[i], HEX);
}
The problem with this code is that myString contains FF01CC, not FF0001CC.
My guess would be that the String class resizes each time a text is appended, that could be improved.
Assuming you know the input size and it´s constant, you could try this:
char outbuffer[numBytes*2+1];
const char* pHexTable="0123456789ABCDEF";
int iPos=0;
for(int i=0; i<numBytes; i++){
//assume buffer contains some binary data at this point
const char cHex=buffer[i];
outbuffer[iPos++]=pHexTable[(cHex>>4)&0x0f];
outbuffer[iPos++]=pHexTable[cHex&0x0f];
}
outbuffer[iPos]='\0';
There is stringstream class available in C++, it may be usable in this case. With C three bytes would be printed to a buffer with one sprintf-statement sprintf(buffer, "%02x%02x%02x", bytes[0], bytes[1], bytes[2]) (preferably snprintf).
#include <sstream>
#include <iostream>
#include <iomanip>
int main(void)
{
std::stringstream ss;
unsigned char bytes[] = {0xff, 0x00, 0xcc};
ss << std::hex;
// This did not work, 00 was printed as 0
// ss << std::setfill('0') << std::setw(2)
// ...
// ss << (unsigned int)bytes[i]
for (int i=0; i<3; i++) {
unsigned int tmp = bytes[i];
ss << (tmp >> 4) << (tmp & 0xf);
}
std::cout << ss.str();
return 0;
}
As understand numBytes can be bigger than 3 or 4 (otherwise why buffer size is 100?)
Also I prefer to use C++ classes when working with string (you need string, not char[]?).
Consider the following example with stringstream class (just include sstream and iomanip standard headers):
string myString;
stringstream myStringStream;
myStringStream << setbase(16);
myStringStream << uppercase;
for (int i = 0; i < numBytes; i++)
{
myStringStream << (0xFF & (unsigned int) buffer[i]);
}
myString = myStringStream.str();
I can not compare the speed of my example with other answers, but this solution is really C++ approach for buffer of any size.
I am trying to represent a variable in the form of a string to a integer, I have done so using;
atoi(str.c_str())
The string is originally obtained from a text file and stored into a;
CharArrayPtr cmemblock;
Which is then represented as a string;
string str;
for(int i = 0; i < numberofvalues; i++)
{
str = cmemblock[i];
int number = atoi(str.c_str());
cout << number;
}
If I was to change the 'cout' to print str;
str = cmemblock[i];
int number = atoi(str.c_str());
cout << str;
The number show correctly as stored in the text file
However, I require the output to be an integer so that I could represent it in a loop to search for a value stored in a array. So this is where 'number' comes into play, which is the reason why I am asking for your help, when;
cout << number;
Whenever a new line is read it is represented as '0' how would I go about removing this? If your require my full code it is in several different .cpp files and to prevent anyone copying my work I can only email it you, im sure you have already guessed it is part of a University Assignment.
Using Member Adosi code I came up with this;
std::string str;
for(int i = 0; i < numberofvalues; i++)
{
str = cmemblock[i];
std::stol(str);
int number = std::stoi(str);
cout << number;
}
I get an error R6010. Have I done this wrong?
std::stoi(str)
Use this instead of atoi
C++11 has this and a few other functions such as std::stol() for longs, std::stof() for floats, etc.
http://en.cppreference.com/w/cpp/string/basic_string/stol
If you dont have C++11 for std::stoi but do have boost you could use lexical cast
#include <boost/lexical_cast.hpp>
int main()
{
std::string s = "100";
try
{
int n = boost::lexical_cast<int>(s);
std::cout << "n = " << n << std::endl;
}
catch (boost::bad_lexical_cast)
{
std::cout << "conversion failed" << std::endl;
}
}
This ensures a valid conversion can take place and throws an exception if it cannot
Regarding your Edit - This requires a C++11 Compiler to work
std::string str;
for(int i = 0; i < numberofvalues; i++)
{
str = cmemblock[i];
//std::stol(str); -> This line is unneeded as it converts string to a long
// Ideally you should check that str is valid here etc. before changing it to an int
int number = std::stoi(str);
cout << number;
}
Another option is to use std::stringstream:
#include <sstream>
#include <string>
int string_to_int(const std::string &string) {
std::stringstream s(string);
s >> number;
if (!s.good()) {
throw std::exception();
}
return s;
}
int main(int argc, const char* argv[]) {
int number = string_to_int(argv[1]);
return 0;
}
This doesn't require any external libraries or C++11, and should be compatible with any C++ compiler out there.
Edit
Fleshed out the example to show how you could write your own string_to_int function to simplify the use of std::stringstream.
I am trying to return a hex value inside this method. not sure where I'm going wrong. not sure how put the value into hex without using cout. have not been able to find a solution. Input value is always going to be 32 bits long
its like i want to return hex << x but thats not an option.
string StringToHex (myInstruction* RealList, int Pos)
{
string result = "11111111110000000000110011001100";
unsigned long x = strtoul(result.c_str(), &pEnd, 2);
cout<< hex << x<<endl;
return x;
}
You can use a stringstream instead of cout.
cout is just one special ostream that is created by default and is hooked up to the program's standard output. You can create other ostream objects that write to different things. std::stringstream writes to a std::string inside it.
#include <sstream>
std::string to_hex() {
unsigned int x = 256;
std::stringstream s;
s << std::hex << x;
return s.str();
}
Use std::stringstream
std::stringstream ss;
ss<< std::hex << x;
std::string res= ss.str();
If I understand your questinon, you want to return a hex value as a string, rigt? If so, then:
std::string intToHexStr (int val)
{
std::stringstream sstr;
sstr << hex << val;
std::string result;
sstr >> result;
return result;
}
Hope this helps!
int main()
{
ifstream infile;
infile >> std::noskipws;
size_t size = 0;
infile.open("tworecords.dat", ios::binary);
if(infile.is_open())
{
infile.seekg(0, ios::end);
size = infile.tellg();
infile.seekg(0, ios::beg);
char *buffer = new char [size];
infile.read(buffer, size);
infile.close();
for(int i=0; i <59; i++)
{
c1 = (*buffer);
buffer++;
cout << c1 << endl;
}
std::cout.write (buffer, size);
cout << endl;
delete[] buffer;
}
return 0;
}
I'm reading in the data values from the file, and they appear in ASCII format. How do I make it so that I can see the values as hex values?
My second question is how do I increment char pointers to increase 1 by one, so that it reads one value at a time, like I am attempting to do in the code?
This might get you started. Annotated code:
#include <iomanip>
#include <iostream>
int main() {
// set integer output to uppercase-, hex-mode
// with '0' as fill character for small byte values
std::cout << std::hex << std::uppercase << std::setfill('0');
// declare a buffer
// note that you could use a std::vector<char> for your reads as well
std::string input;
// read a sequence of bytes (TODO: replace with reading from file)
while(std::getline(std::cin, input)) {
// iterate over the bytes as unsigned chars (not signed!)
// to support characters in the negative byte value range (>7F)
// (using C++11 range-based for loop)
for (unsigned char i : input)
// set width format for each value to 2 (00 to FF)
// (setting is only active for the next insert operation)
// insert the value as a multibyte integer
// to get the proper basic_ostream::operator<< overload
std::cout << std::setw(2) << static_cast<int>(i);
std::cout << std::endl;
}
}
Usage Example:
$ g++ test.cc -std=c++11
$ echo "Hello World" | ./a.out
48656C6C6F20576F726C64
References:
http://en.cppreference.com/w/cpp/io/manip/hex
http://en.cppreference.com/w/cpp/io/manip/uppercase
http://en.cppreference.com/w/cpp/io/manip/setfill
http://en.cppreference.com/w/cpp/io/manip/setw
http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt
http://en.cppreference.com/w/cpp/language/range-for
As for your other question about how to iterate a character array, you have a couple of options. See this code example:
#include <iostream>
int main() {
// declare buffer and size
// intentionally left out null-termination and sizeof()
// for the purpose of this demonstration
char buf[] = {'a','b','c','d','e'};
std::size_t size = 5;
// iterate using array indexing
for (std::size_t i = 0; i < size; i++) std::cout << buf[i];
std::cout << "\n";
// iterate using pointer
for (char *p = buf; p != buf+size; p++) std::cout << *p;
std::cout << "\n";
}
Note that you can (and should) use a std::vector<char> as a buffer. This has some advantages. Biggest ones: trivial to pass in and out of functions, you can always call for the size() of the buffer, and, memory management is done by the standard library.
For example (untested code):
{
// declare buffer of the appropriate size
std::vector<char> buffer(size);
// read data into the buffer
infile.read(&(buffer[0]), buffer.size());
infile.close();
// iterate the buffer using std::vector<char>::iterator
for (auto it = buffer.begin(); it != buffer.end(), ++it) {
// do your output operations
}
} // <-- storage duration of buffer ends automatically where the scope ends
More references:
http://en.cppreference.com/w/cpp/container/vector
http://en.cppreference.com/w/cpp/container/vector/size
http://en.cppreference.com/w/cpp/container/vector/begin
http://en.cppreference.com/w/cpp/container/vector/end
http://en.cppreference.com/w/cpp/types/size_t
http://en.cppreference.com/w/cpp/language/auto
#include <iomanip>
for(int i=0; i <size; i++) // <-- size, not 59
{
c1 = buffer[i]; // copy the i'th element of buffer. If you increment
// buffer (as in your example), you can't delete
// it later because you lost the initial address
cout << hex << c1 << dec << endl;
}
Aside from the hex-conversion I think your loop should be like the one below (see the comments):
for(int i=0; i <size; i++) // <-- size, not 59
{
c1 = buffer[i]; // copy the i'th element of buffer. If you increment
// buffer (as in your example), you can't delete
// it later because you lost the initial address
cout << c1 << endl;
}
Depending on the format of the hex numbers, if you want to output digit by digit (e.g. turn an 'A' into 10, etc. a very basic way is this:
int dec;
if (c1>='0' && c1<='9') {
dec= c1 - '0'; // e..g for '0' (ascii 48) it will make dec= (int)0.
}
else
if (c1>='A' && c1<='F') {
dec= 10 + (c1 - 'A'); // e..g for 'A' (ascii 65) it will make dec= (int)10.
}
else {
// should not happen or handle lower chase characters too
}
Another way, using sscanf would be:
// convert one hex digit from c1 into a corresponding decimal number
char hex[2];
int dec;
hex[0]= c1;
hex[1]= '\0';
sscanf(hex, "%1x", &dec);