So I have a simple char variable which is as follows:
char testChar = 00000;
Now, my goal is to display not the unicode character, but the value itself (which is "00000") in the console. How can I do that? Is it possible to convert it to a string somehow?
To print the char's integer value:
std::cout << static_cast<int>(testChar) << std::endl;
// prints "0"
Without the cast, it calls the operator<< with char argument, which prints the character.
char is an integer type, and only stores the number, not the format ("00000") used in the definition. To print a number with padding:
#include <iomanip>
std::cout << std::setw(5) << std::setfill(' ') << static_cast<int>(testChar) << std::endl;
// prints "00000"
See http://en.cppreference.com/w/cpp/io/manip/setfill .
To convert it to a std::string containing the formatted character number, you can use stringstream:
#include <iomanip>
#include <sstream>
std::ostringstream stream;
stream << std::setw(5) << std::setfill(' ') << static_cast<int>(testChar);
std::string str = stream.str();
// str contains "00000"
See http://en.cppreference.com/w/cpp/io/basic_stringstream .
You are confusing values with representations. The character's value is the number zero. You can express this as "zero", "0", "00", or "1-1" if you want, but it's the same value and it's the same character.
If you want to output the string "0000" if a character's value is zero, you can do it like this:
char a;
if (a==0)
std::cout << "0000";
Related
I would like to convert a hex-value ("206564697374754f") to a string (from hex to ascii). These hex-values are from gdb, so the contents are "reversed" by every two. (So the exact hex-value I need to convert is "4f75747369..."). reverse2() reverses the string appropriately, but it needs to now be converted to hex (hence the "0x", then atoi()).
The following code is what I have so far, but I run into a runtime-error. What is the issue, and is there a better way of doing this?
#include <bits/stdc++.h>
using namespace std;
void reverse2s(string str)
{
for (int i=str.length()-2; i>=0; i-=2) {
string hx="0x"+str[i]+str[i+1];
cout << (char)(std::stoi( hx ));
}
}
// Driver code
int main(void)
{
string s = "206564697374754f";
reverse2s(s);
return (0);
}
The expression "0x"+str[i]+str[i+1]; does not do what you think. "0x" is a character array (not a string). Since str[i] is a character, the addition will add convert that character to an int, and perform a pointer addition. This results in Undefined Behavior.
To do the string concatenation you're expecting, you need to create a string object first:
string hx="0x"s+str[i]+str[i+1];
"0x"s will create an actual string literal to append characters to.
Well it seems like you're just trying to print it as hex,
so you could do
std::cout << std::hex << 5 << std::endl; // prints 0x5
If you don't care about performance:
std::stringstream s;
s << std::hex << num:
s.str(); // std::string containing your number as hex
If you do care about performance I have no clue
This should work:
#include <iostream>
#include <strstream>
#include <string>
int main()
{
std::strstream s1; // dynamic buffer
s1 << std::hex << 12345 << std::endl;
std::cout << "buffer: '" << s1.str() << "'\n";
s1.freeze(false);
return 0;
}
This question already has an answer here:
setw() does not affect reading integer fields
(1 answer)
Closed 3 years ago.
I'm trying to read bytes in hex notation from a string. The bytes may or may unfortunately not be separated by whitespace, e.g. " 00 ffab c " is a valid example and should result in 4 bytes read, 0x00, 0xff, 0xab and 0x0c. The problem is to skip whitespace but read only two adjacent digits, when present.
If the input were from a file, the task would be as easy as while(fscanf(f, "%2d", &i) == 1) ... because sscanf skips whitespace, the read position is tracked by the underlying FILE, and the maximum field width is only applied to the item read, not the raw input characters containing the whitespace. But the position tracking is not possible when reading from a string; I need to use the %n format conversion specifier which stores the number of characters read so far by this invocation into the associated variable, e.g. scanf(f, "%2d%n", &i, &readIncr), and manually maintain a read position by adding the respective increments.
This is somewhat cumbersome, hence I wanted to use std::istringstream which does keep track of a position in the underlying string.
But setting a width on the input stream does not have the desired (and expected) effect; below is a minimal demonstration; for simplicity I'm using decimal integers. Documentation and examples for an input field width are scarce.
Am I doing something wrong? I this use case simply not intended?
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
int i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << i << '\n';
}
if (sscanf(s, "%2d", &i) == 1)
{
cout << "scanf i: " << i << '\n';
}
}
The output is (with g++ and MSVC)
$ g++ -Wall -o fieldwidth fieldwidth.cpp && ./fieldwidth
stringstream i: 1234
scanf i: 12
Sadly cpp streams are far from perfect. AFAIK std::setw works only for reading strings. What you can do is:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
std::string i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << std::stoi(i) << '\n';
}
int j;
if (sscanf(s, "%2d", &j) == 1)
{
cout << "scanf i: " << j << '\n';
}
}
And you get expected output:
stringstream i: 12
scanf i: 12
Say I have a string as so:
std::string sc = "\\xfc\\xe8\\x82";
how could I convert the sc string into the equivalent of
unsigned char buf[] = "\xfc\xe8\x82";
I'm trying to convert a string containing shellcode into a unsigned char array.
I have tried the following:
char buf[5120];
strncpy(buf, sc.c_str(), sizeof(buf));
buf[sizeof(buf) - 1] = 0;
This seems to store strings into the char array I need the char array to store/represent bytes.
When I print:
//example 1
unsigned char buf[] = "\xfc\xe8\x82";
printf("%s", buf);
The console outputs:
ⁿΦé
When I print:
//example 2
char buf[5120];
strncpy(buf, sc.c_str(), sizeof(buf));
buf[sizeof(buf) - 1] = 0;
The Console outputs:
\xfc\xe8\x82
How do I convert the sc string into a unsigned char array so that when sc is printed sc will produce the same output of example 1.
The literal "\\xfc\\xe8\\x82" as a string uses "\" as an escape character. "\\" will be reduced to "\". As you would expect. So, if you print your given std::string, then the result will be:
\xfc\xe8\x82.
So, what you want to do now is: Create a char array containing those hex values, given in the original std::string.
Please note: Your statement char s[] = "\xfc\xe8\x82"; will create a C-Style array of char, with the size 4 and containing:
s[0]=fc, s[1]=e8, s[2]=82, s[3]=0
In the example below I show 2 proposals for conversion.
1. Straight forward conversion
2. Using C++ standard algorithms
#include <string>
#include <iostream>
#include <iomanip>
#include <regex>
#include <vector>
#include <iterator>
#include <algorithm>
// Hex digit String
std::regex hexValue{R"(\\[xX]([0-9a-fA-F][0-9a-fA-F]))"};
int main ()
{
// Source string
std::string s1 = "\\xfc\\xe8\\x82";
std::cout << "s 1: " << s1 << "\n";
// Proposal 1 ------------------------------------------------------
// Target array
unsigned char s2[3];
// Convert bytes from strings
for (int i=0; i<s1.size()/4; ++i ) {
// Do conversion. Isolate substring, the convert
s2[i] = std::strtoul(s1.substr(i*4+2,2).c_str(), nullptr,16);
// Result is now in s2
// Output value as tring and decimal value
std::cout << s1.substr(i*4+2,2) << " -> " << std::hex << static_cast <unsigned short>(s2[i])
<< " -> " << std::dec << static_cast <unsigned short>(s2[i]) << "\n";
}
// Proposal 2 ------------------------------------------------------
// Get the tokens
std::vector<std::string> vstr(std::sregex_token_iterator(s1.begin(),s1.end(),hexValue, 1), {});
// Convert to unsigned int
std::vector<unsigned int> vals{};
std::transform(vstr.begin(), vstr.end(), std::back_inserter(vals),
[](std::string &s){ return static_cast<unsigned>(std::strtoul(s.c_str(), nullptr,16)); } );
// Print output on std::cout
std::copy(vals.begin(), vals.end(), std::ostream_iterator<unsigned>(std::cout,"\n"));
return 0;
}
The second solution will eat any number of hex numbers given in a string
While learning some basics with OpenSSL I came across code to create an SHA256 hash:
using namespace std;
#include <openssl/sha.h>
string sha256(const string str)
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str.c_str(), str.size());
SHA256_Final(hash, &sha256);
stringstream ss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
ss << hex << setw(2) << setfill('0') << (int)hash[i];
}
return ss.str();
}
Can someone please explain what ss << hex << setw(2) << setfill('0') << (int)hash[i]; does in this specific example as simply as possible, while still explaining it efficiently?
As I can't seem to make sense of these answers, they aren't helping with understanding my specific snippet:
Using setw and setfill on string
How to use setw and setfill together in C++ to pad with blanks AND chars
C++ output formatting using setw and setfill
In C++ there are many different streams. You probably know about cout to write output to the console, and cin to read input. stringstream is a class whose object write to and read from string objects. Writing to a string stream (like the variable ss) is just like writing to cout, but writes to a string instead of the console.
You say you have programmed C? Then you should know about hexadecimal notation, right? That is what the hex manipulator tells the stream to use. This is similar to the printf format specifier "%x".
The setw manipulator sets the field width of the next output.
The setfill manipulator sets the fill character of the output.
Finally the casting of hash[i] to int is because hash[i] is a char and output to a stream will write it as a character and not a small integer.
In short,
ss << hex << setw(2) << setfill('0') << (int)hash[i];
is equivalent to the C code
sprintf(temporaryBuffer, "%02x", hash[i]);
strcat(ss, temporaryBuffer);
I need to output some data that may be UTF-8 multi-byte and I need to keep them formatted using setw().
When the characters are multi-byte sequences, aligement is lost and setw() doesn't work correctly.
//#include <stdio.h>
#include <locale>
#include <iostream>
//#include <fstream>
#include <iomanip>
//#include <sstream>
int main(int argc, char **argv)
{
std::locale l=std::locale("en_US.utf8");
std::locale::global(l);
std::cout.imbue(l);
std::cout<<std::endl;
std::cout<<std::setw(40)<<std::right<<"hi “my” friend"<<std::endl;
std::cout<<std::setw(40)<<std::right<<"hi -my- friend"<<std::endl;
return 0;
}
The output is:
hi “my” friend
hi -my- friend
What am I missing ?
I must point out that the characters “ and ” are not the normal " but instead two others, which in UTF-8 are expressed by three bytes each.
String literal "hi -my- friend" contains 14 characters. String literal "hi “my” friend" contains 18 characters: symbols “ and ” are encoded by 3 characters/bytes. cout outputs those characters as-is, it is target terminal which converts 3-byte sequence into single symbol.
So, from stream point of view everything is okay: it outputs (width - strlen(literal) ) fill characters, then strlen(literal) characters, width total. It does not handle possible multibyte sequences and doesn't know that target terminal transform several characters to one symbol.
You can accomplish this formatting by counting how many characters your string would be if it were in a wide representation, then taking the difference between the length of your string and the wide representation, then adding that difference to what you pass to setw, such as:
std::mbstate_t state = std::mbstate_t();
std::string s = "hi “my” friend";
const char *cp = s.c_str();
size_t len = mbsrtowcs(nullptr, &cp, s.size(), &state);
std::cout << setw(40 + (s.size() - len)) << std::right << s << std::endl;
You could encode this functionality into a function that takes the string as a parameter and just returns the difference to be added to the setw call:
size_t f(const std::string &s)
{
std::mbstate_t state = std::mbstate_t();
const char *cp = s.c_str();
size_t len = mbsrtowcs(nullptr, &cp, s.size(), &state);
return s.size() - len;
}
...
std::string s = "hi “my” friend";
std::cout << std::setw(40 + f(s)) << std::right << s << std::endl;