c++ string element conversion to int - c++

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

Related

Looping through string of integers gives me completely different numbers?

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.

Joining two characters in c++

My requirement is to join two characters. For example
int main()
{
char c1 ='0';
char c2 ='4';
char c3 = c1+c2;
cout<< c3;
}
The value which I am expecting is 04. But what I am getting is d.
I know that char is single byte. My requirement is that in the single Byte of C3 is possible to merge/join/concat the c1,c2 and store the value as 04
A char is not a string. So you can first convert the first char to a string and than add the next ones like:
int main()
{
char c1 ='0';
char c2 ='4';
auto c3 = std::string(1,c1)+c2;
std::cout<< c3;
}
What is "magic" std::string(1,c1):
It uses the std::string constructor of the form: std::string::string (size_t n, char c);. So it "fills" the string with one single character of your given c1 which is the 0.
If you add chars you get the result of adding the numeric value of it which is:
int main() {
std::cout << (int)c1 << std::endl;
std::cout << (int)c2 << std::endl;
std::cout << (int)c1+c2 << std::endl;
std::cout << char(c1+c2) << std::endl;
}
The numeric value as int from 0 is 48, from 4 it is 52. Add both you get 100. And 100 is a d in ascii coding.
What you want is called a string of characters. There are many ways to create that in C++. One way you can do it is by using the std::string class from the Standard Library:
char c1 = '0';
char c2 = '4';
std::string s; // an empty string
s += c1; // append the first character
s += c2; // append the second character
cout << s; // print all the characters out
A char is no more than an integral type that's used by your C++ runtime to display things that humans can read.
So c1 + c2 is a instruction to add two numbers, and is an int type due to the rules of type conversions. If that's too big to fit into a char, then the assignment to c3 would have implementation-defined results.
If you want concatenation, then
std::cout << ""s + c1 + c2;
is becoming, from C++11's user defined literals, the idiomatic way of doing this. Note the suffixed s.
Each char in C (and C++) has the length of one byte. What you are doing is adding the actual byte values:
'0' = 0x30
'4' = 0x34
-> '0' + '4' = 0x30 + 0x34 = 0x64 = 'd'
If you want to concatenate those two you will need an array:
int main()
{
char c1 ='0';
char c2 ='4';
char c3[3] = {c1,c2,0}; // 0 at the end to terminate the string
cout<< c3;
return 0;
}
Note that doing those things with chars is C but not C++. In C++ you would use a string, just as Klaus did in his answer.
Basics first
In C++ and C, a string ends with '\0' which is called null character.
Presence of this null character at the end differentiates between a string and char array. Otherwise, both are contigous memory location.
While calculating string.length() not counting the null character at the end is taken care.
Joining/Concatenating two characters
If you join two character using + operator, then handling the null character in both strings end will be taken care.
But if you join two char with + operator and wish to see it as an string, it will not happen, because it has no null character at the end.
See the example below:
char c1 = 'a';
char c2 = 'b';
string str1 = c1 + c2;
cout << str1; // print some garbled character, as it's not valid string.
string str2; // null initialization
str2 = str2 + c1 + c2;
cout << str2; // prints ab correctly.
string s1 = "Hello";
string s2 = "World";
string str3 = s1 + s2;
cout << str3; //prints Hello World correctly.
string str4 = s1 + c1;
cout << str4; //prints Hello a correctly.
What you named "joining" is actually arithmetics on char types, which implicitly promotes them to int. The equivalent integer value for a character is defined by the ASCII table ('0' is 48, '4' is 52, hence 48 + 52 = 100, which finally is 'd'). You want to use std::string when concatenating textual variables via the + operator.
You can do somthing like that:
#include <vector>
#include <iostream>
using namespace std;
int main()
{
char a = '0';
char b = '4';
vector<char> c;
c.push_back(a);
c.push_back(b);
cout << c.data() << endl;
return 0;
}
Simple addition is not suitable to "combine" two characters, you won't ever be able to determine from 22 if it has been composed of 10 and 12, 11 and 11, 7 and 15 or any other combination; additionally, if order is relevant, you won't ever know if it has been 10 and 12 or 12 and 10...
Now you can combine your values in an array or std::string (if representing arbitrary 8-bit-data, you might even prefer std::array or std::vector). Another variant is doing some nice math:
combined = x * SomeFactorLargerThanAnyPossibleChar + y;
Now you can get your two values back via division and modulo calculation.
Assuming you want to encode ASCII only, 128 is sufficient; considering maximum values, you get: 127*128+127 == 127*129 == 2^14 - 1. You might see the problem with yourself, though: Results might need up to 14 bit, so your results won't fit into a simple char any more (at least on typical modern hardware, where char normally has eight bits only – there are systems around, though, with char having 16 bits...).
So you need a bigger data type for:
uint16_t combined = x * 128U + y;
//^^
Side note: if you use 256 instead, each of x and y will be placed into separate bytes of the two of uint16_t. On the other hand, if you use uint64_t and 127 as factor, you can combine up to 9 ASCII characters in one single data type. In any case, you should always use powers of two so your multiplications and divisions can be implemented as bitshifts and the modulo calculations as simple AND-operation with some appropriate mask.
Care has to be taken if you use non-ASCII characters as well: char might be signed, so to prevent unwanted effects resulting from sign extension when values being promoted to int, you need to yet apply a cast:
uint16_t combined = static_cast<uint8_t>(x) * 128U + static_cast<uint8_t>(y);
Since a basic char doesn't have operator+ to concatenate itself with another char,
What you need is a representation of a string literal using std::string as suggested by others
or in c++17, you can use string_view,
char array[2] = {'0', '4'};
std::string_view array_v(array, std::size(array));
std::cout << array_v; // prints 04
https://github.com/bite-rrjo/STG-char-v2/blob/main/stg.h
without external libraries it would be like this
#include "iostream"
#include "lib-cc/stg.h"
using namespace std;
int main(){
// sum two char
char* c1 = "0";
char* c2 = "4";
stg _stg;
_stg = c1;
_stg += c2;
cout << _stg() << endl;
// print '04'
}

How to create a user created Character a array while printing it out

Whenever I run this code. I get the least understandable output I probably have ever received. Please help I've been struggling with this for a very long time. Thanks.
int main()
{
char letters[50];
char y;
char Character;
char test='t';
for(int x=0;x<50;x++)
{
while (isalpha(test))
{
cout<<"Enter letters to add to the array and any number to stop"<<endl;
cin>>letters[x];
test=letters[x];
}
x=51;
cin.ignore();
cin.clear();
}
for (int x=0;x<50;x++)
{
cout<<letters[x]<<" ";
}
cout<<endl;
return 0;
}
Your while (isalpha(test)) loop is inside the for(int x=0;x<50;x++) loop, so x is always 0 and you keep replacing the first character until you input a digit, and all other characters don't ever get initialized.
A C-style string is simply an array of characters that uses a null
terminator. A null terminator is a special character (‘\0’, ascii code
0) used to indicate the end of the string. More generically, A C-style
string is called a null-terminated string.
When you use character arrays to store C-style strings, You should know something about it
1.Array of character is pointer to a character that point to the address array started from
2.That's contain some character and cpp don't initial values of array and be contain some data
If you want to initial data you have many way
the best way to fill it with zero
char letters[50] = {0};
Or you can initialize a character array with a string literal (i.e. a string in double quotes), as long as you leave room for the null character in the allocated space.
char letters[50] = "Johnny";
Notice that this would be equivalent to:
char letters[50] = {'J', 'o', 'h', 'n', 'n', 'y', '\0'};
3.The functions like printf in c and cout in argument get pointer to character that point the start of character array start.And print array to '\0' character for example
int main()
{
char letters[50] = {'A', 'M' , 'I' , 'N' , '\0' , '1'};
/*
------------------------------------------
| A | M | I | N | \0 | | | | | |
------------------------------------------*/
cout << letters; //output: AMIN
return 0;
}
And Last for solving the problem
Only assign '\0' (A null terminator) to end of your C-style string.Like below for your question
int main()
{
char letters[50];
char y;
char Character;
char test = 't';
int x = 0;
while ( isalpha(test) && x<49)
{
cout << "Enter letters to add to the array and any number to stop" << endl;
cin >> letters[x];
test = letters[x];
x++;
}
cin.ignore();
cin.clear();
letters[x] = '\0';
cout << letters<< " ";
cout << endl;
return 0;
}

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.

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.