Looping through string of integers gives me completely different numbers? - c++

I'm a beginner to C++ so forgive me if I'm making a stupid mistake here.
I want to loop through a string of integers in the following code:
#include <string>
using namespace std;
int main() {
string str = "12345";
for (int i : str) {
cout << i << endl;
}
return 0;
}
But I receive the output:
49
50
51
52
53
I know that I get normal output if I use char instead of int, but why do I receive an output of integers 48 more than they should be?

When you loop through a string you get elements of type char. If you convert a char to an int you get the ASCII value of the char, which is what happens when you do:
string str = "12345";
for (int i : str) { // each char is explicitly converted to int
cout << i << endl; // prints the ascii value
}
The ASCII value of '0' is 48, and '1' is 49, etc, which explains the output you get.

Just what #cigien said, You just need to change it from int to char i.e
string str = "12345";
for (char i : str) {
cout << i << endl;
}
Or one solution for all auto keyword
string str = "12345";
for (auto i : str) {
cout << i << endl;
}

The first thing you need to know is that a string is an array/sequence of chars.
You can think of a char as a single character.
But the way it is encoded is as a number.
For example, the char 'a' is encoded (in ASCII) as the number 97.
Now your for loop says int i: str.
You're telling it to look for integers in the string.
But a string is an array/sequence of chars, not of integers.
So the loop takes each char,
and instead of looking at what the character itself is,
it gives you the integer encoding value of the char,
the ASCII value.
Now the numbers are encoded with the char '0' having the lowest encoding value,
'1' having the next value,
'2', having the next,
and so on through digit '9'.
I can never remember what the actual ASCII value for '0' is . . . .
But because the digit chars are encoded consecutively in this way,
you can convert any digit char to its int value by subtracting the underlying integer encoding value of '0'.
#include <string>
using namespace std;
int main() {
string str = "12345";
for (char c: str) {
cout << (c - '0') << endl; // gives you the actual int value, but only works if the char is actually a digit
}
return 0;
}

for (int i : str) { is infact syntactic sugar for
for (auto iterator = str.begin(); iterator != str.end(); iterator++) {
int i = (int) *iterator;
But the *-operator from string::iterator is infact an overload which returns the current char. It will as such be casted to an int. What you then see is this number. It is the integer value of the byte. Not necessarily ASCII. It could be ANSI too.

Related

c++ string element conversion to int

int main() {
vector<string> tab;
tab.push_back("1234");
cout << tab[0][0];// -> 1
if (int(tab[0][0]) == 1) {
cout << "test";
}
}
why does this comparison not work? what am I doing wrong?
'1' the character is not the same as 1 the integer.
To do your comparison write
if (tab[0][0] == '1') {
Specifically when you convert a character to an integer what you get is the encoding of the character. If you are using ASCII (which is very likely) then the encoding of '1' is 49.
You're confusing numbers (1, 2, 3, ...) and digits ('1', '2', '3', ...).
They look the same when you print them, but they are not the same.
The expression tab[0][0] will evaluate to the first character of the first string in the tab vector. Note that this is a character representation (probably ASCII, but not necessarily so), which will not have the numerical value of 1 (it will have the value 49 if your system uses ASCII).
So, in your if test, you need to compare the value with a character literal rather than an integer literal, like so:
int main() {
vector<std::string> tab;
tab.push_back("1234");
std::cout << tab[0][0];// -> 1
if (int(tab[0][0]) == '1') { // Compare to the character '1'!
std::cout << "test";
}
}
If You Want To Convert A String To A Number Use The Function Atoi()
std::string str = "12345";
int num = std::atoi(str.c_str());
// num = 12345
If You Want one Single Character Not a char*
std::string str = "12345";
int num = str[0] - '0';
// num = 1

ASCII to dec stored in string

The string str_hex contains the hex-values for the letters A-J, which corresponds to the decimal values 65-74. I'm trying to cast each hex-value to its decimal value following this example. It works nice for the std::cout case inside the for-loop, but the output-std::string still has the ascii-values. Why does this not work or is there a nicer/more proper way to build my output string?
#include <string>
#include <iostream>
#include <stdint.h>
int main()
{
std::string str_hex("\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b", 10);
std::string str_output = "";
for (int i = 0; i < 10; ++i)
{
uint8_t tmp = str_hex[i];
str_output.append(1, (unsigned)tmp);
std::cout << "cout+for: " << (unsigned)tmp << std::endl;
if(i<9)
str_output.append(1, '-');
}
std::cout << std::endl << "cout+str_append: " << str_output << std::endl;
return 0;
}
Compiling and running the program gives the following output:
cout+for: 65
cout+for: 66
cout+for: 67
...
cout+str_append: A-B-C-D-E-F-G-H-I-J
The desired output is:
cout+str_append: 65-66-67-68-...
The method string::append accepts, among the various overload, a size_t and a char, see reference.
string& append (size_t n, char c);
Therefore, in your code line
str_output.append(1, (unsigned)tmp);
you are implicitly converting the unsigned tmp to a char, i.e., to a single letter. To obtain the output you want, you have to convert tmp to a string containing the number, and then append it to str_output. You can do that by using
str_output+=std::to_string(tmp);
instead of str_output.append(1, (unsigned)tmp);.
You have to change your string append to for the change from a number to its "string":
str_output.append(std::to_string(tmp));
It's not one character that you want to add, but a string representing the number.

Changing the character inside a string to number

I have a string a = "Hello world!", now for fun I wish to change the first letter in the string a to a number of my choosing. for example
string a = "Hello world!";
int x;
std:cin>>x;
a[0] = x;
cout << a;
Now what i want it to produce is "xello world!" x being the number i typed in, but instead I get a little smiley face.
Anyone seen anything similar and know how to fix it?
Also: Why can you even access a string like this string[] ? it's not a char array o.o
If x is a single digit number, do this instead:
a[0] = x + '0';
EDIT:
Why this works:
Each element in string is a char. A char is represented by an integer. You can check this up in the ASCII table. For example, integer 48 represents char '0', integer 49 represents char '1', etc. Thus, by adding your integer x to char '0', you can get the digit 'x' that you want.
Why it might be dangerous:
One reason that I could think of would be when writing to unallocated memory in an empty string, which might invoke undefined behavior.
You can then check if a string is empty with string::empty(). In this case,
if (!a.empty()) {...}
Using string::replace and std::to_string, this will work regardless if x is a single or multiple digit number:
string a = "Hello world!";
int x;
std:cin>>x;
a.replace(0, 1, std::to_string(x));
Live Example
As an additional answer you could use the at() method in a try block as it is performing bounds checking and throws exception of type std::out_of_range if the access is invalid:
If you add x + '0' and x is higher than 9 it won't give you a number.Look at the ascii table
int main()
{
std::string a { "Hello World" };
int x {};
std::cin >> x;
try {
a.at(0) = '0' + x; // OOPS: '0' + 10 will give you ':'
std::cout << a << '\n';
}
catch(std::out_of_range& e) {
std::cout << e.what();
}
}
A better solution is what #PaulMcKenzie answered, to use std::to_string and string::replace.

Converting from ASCII back to char

I have a function that already converts a string to ASCII ints, but how to I do the reverse? Thanks
You question is not clear. Giving you solution based on assumption that your ASCII ints (in your terms) stored in a vector<int>
Below function will convert it into string:
std::string
AsciiIntToString ( std::vector<int> const& ascii_ints )
{
std:: string ret_val;
std::vector<int>:: const_iterator it = ascii_ints. begin ();
for ( ; it != ascii_ints. end (); ++it ) {
if ( *it < 0 || *it > 255) throw std::exception ("Invalid ASCII code");
ret_val += static_cast<char>(*it);
}
return ret_val;
}
Here are some examples that convert between number and the textual representation of the number in binary format using std::bitset (only works for character sets that can be represented by 7 bits (as US-ASCII for example)):
char c = 'a';
// char to int.
int i = static_cast<int>(c);
// int to string (works for char to string also).
std::string bits = std::bitset<8>(i).to_string();
// string to (unsigned long) int.
unsigned long ul = std::bitset<8>(bits).to_ulong();
// int to char.
c = static_cast<char>(ul);
Here is a much simpler way!
void convertToString()
{
char redo;
int letter;
int length;
do{
cout<< "How long is your word \n";
cin >> length;
cout << "Type in the letter values \n";
for (int x = 0; x < length; x++)
{
cin >> letter;
cout << char (letter);
}
cout << "\n To enter another word hit R" << endl;
cin >> redo;
} while (redo == 'R');
}
The use of the neologism "ASCII 'int'" was an imprecise--but not an unclear--reference to ASCII codes. The reference was clear because all of the ASCII codes are whole numbers, just like integers.
The original poster was able to translate an ASCII character into decimal, presumably using a function.
In MySQL, this would be: SELECT ASCII('A') [FROM DUAL];, which returns 65.
To reverse direction, use the char() function:
SELECT CHAR(65) [FROM DUAL];
Perhaps this would be a good work-around for you.
I would recommend using non-GUI client.
The best way to convert static to cast is
int it=5;
char W = static_cast<char>(*it);
You just have to store it in a char variable:
//Let's say your original char was 'A'...
int asciivalue = int('A');
// Now asciivalue = 65
//to convert it back:
char orig = asciivalue;
cout << orig << endl;
It'll output 'A'.

Why does my string get empty values appended to it when subtracting characters?

I am attempting to solve a problem from topcoder.com and it's driving me crazy. I am learning C++ after a long break from C and am having trouble with strings.
The purpose of the program is to decode a string of 0s and 1s that has gone through an encryption algorithm that consists of adding each adjacent digit to the digit in question.
So 010111 becomes 112232 (LSB and MSB are considered to have zeros next to them). Below is my algorithm to decode the string:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class BinaryCode {
public:
vector<string> decode(string message);
};
vector<string> BinaryCode::decode(string message) {
vector<string> decoded(2);
int i;
string myTempString;
myTempString.append("0");
myTempString.append(1,message[0] - myTempString[0]);
for(i=2; i<message.size(); i++) {
myTempString.append(1,message[i-1] - myTempString[i-1] - myTempString[i-2]);
}
decoded[0] = myTempString;
myTempString = "";
myTempString.append("1");
myTempString.append(1,message[0] - myTempString[0]);
for(i=2; i<message.size(); i++) {
myTempString.append(1, message[i-1] - myTempString[i-1] - myTempString[i-2]);
}
decoded[1] = myTempString;
return decoded;
}
int main () {
string message("123210122");
BinaryCode *code = new BinaryCode;
vector<string> result = code->decode(message);
cout << "Decoded strings are "+result[0]+" and "+result[1];
getchar();
return 0;
}
The output is nonsense:
Decoded strings are 01
This is just a guess, since you don't show what output you're getting, but it looks like you're doing math on the character values and ending up with characters in the control range. For example, '1' - '0' is not '1' (character 49), it is 1, or Control-A. This is not printable and will typically be invisible in the output. Similarly, '1' + '2' is 49 + 50, or 99, which is 'c'. C++ is not going to magically convert these characters to integers for you. Hopefully this will give you the information you need to fix your code.
A character is an 8-bit integral type. It has the special property that, when printed, it will appear as the character that matches the ASCII value that it contains.
For example:
int valueAsInt = 65;
char valueAsChar = valueAsInt;
std::cout << valueAsChar << "\n";
valueAsInt = 'A';
std::cout << valueAsInt << "\n";
A
65
Take the value of the character literal '0'. This corresponds to the ASCII value 48. '1' is 49, etc.
If you subtract 48 from 49, you get 1. But that's not what you're looking for.
The ASCII value 1 corresponds to a non-printable character, called "start of heading". It was once used on old printers as a sort of markup. It would not print, but it would modify how further characters are printed.
When you subtract one numeric character from another, you get a delta, not a printable character. To turn this delta back into a printable character, you have to add it to a base character:
char value = '5' - '3';
value += '0';
std::cout << "5 - 3 = " << value << "\n";
5 - 3 = 2
So, your code such as message[0] - myTempString[0] must be changed to message[0] - myTempString[0] + '0' in order to work the way you intend it to.