So I recently started learning C++, been watching a lot of tutorials and stumbled upon a tricky question. I want to enter a max number n and enter two numbers stored in a char array. Then I would want to pass them into my add function to do simple addition. It would always return a letter though. I know it has to do with the char ASCII, but is there any way besides using strings to accomplish this?
#include <iostream>
using namespace std;
void add(char m1[], char m2[], int n);
int main()
{
int n = 0;
cin >> n;
const char CAPACITY = 100;
char m1[CAPACITY] = {0};
char m2[CAPACITY] = {0};
for(int i = 0; i < n; i++)
{
cin >> m1[i];
}
for(int i = 0; i < n; i++)
{
cin >> m2[i];
}
add(m1, m2, n);
}
void add(char m1[], char m2[], int n)
{
char sum[100] = {0};
for(int i = 0; i < n; i++)
{
sum[i] = m1[i] + m2[i];
}
for(int i = 0; i < n; i++)
cout << sum[i];
}
It's important to know the difference between '3' and 3. The first is a character, a symbol. The second is a number formed of one digit. In C++ unfortunately and confusing for beginners characters can sometimes appear to act as numbers. They are implicitly convertible to integers and operations like summing them are allowed, although it doesn't make any sense to add two symbols. When a character is acting up as a number its numeric value is the character representation code. I.e. each character has a code (or number) associated with it as part of the character encoding scheme. The most used character encoding scheme for char is ASCII.
When you do '3' + '0' you are actually adding the character codes. If you look in an ASCII table you will see that the code for '3' is 51 and the code for '0' is 48 so the result is 99. Due to the implicit (hidden) conversions happening in '3' + '0' the result (99) is of type int, not char.
More formally, '3' + '0' is equivalent to:
static_cast<int>('3') + static_cast<int>('0')
When you store the result (remembers the result it's an int) to a char (like you do in sum[i] = m1[i] + m2[i] then the integer is implicitly converted to a char. Again, if you look in the ASCII table you see that the code 99 corresponds to the character 'e'.
It helps a lot if you think of characters as symbols. There are alpha characters: 'a', 'b', etc.; digit characters: '0', '1', etc.; punctuation and whitespace characters: ' ', ';', '-' etc. and control characters: '\0' etc. It helps a lot if you think of all of them being in the same boat. It helps if you think as 'a' and '3' being both symbols, being of same type. Then you will see that '3' + '0' doesn't make sense any more than 'a' + 'b' makes sense.
I, but is there any way besides using strings to accomplish this?
You mean to add two numbers? Sure:
int a, b;
std::cin >> a >> b;
int sum = a + b;
std::cout << sum << std::endl;
Mind. Blown.
Related
i am trying to make a project,to experiment and learn C++, i didnt finish making it,but what it does is you type in a 3 or 4 (the variable noc) word and the program runs through all the possible (noc) letter words or nonsense, until it finds yours,so there are 2 factors: the length of the word or nonsense and what characters it can type,in my case i just want the alphabet
so here is my code:
#include <iostream>
#include <unistd.h>
using namespace std;
const int noc = 3;
int main() {
string used[noc];
string inp;
cin >> inp;
char albet[] = {'a','b','c'};
cout << "Starting..." << endl;
usleep(1);
string aiput = "";
while(aiput != inp){
for(int i = 0; i <= noc; i++){
aiput = aiput +
}
}
return 0;
}
currently i need the alphabet in the array called 'albet' (i come up with short words for what they mean its easy to forget tho)
so please can you get me a way to generate the alphabet in C++ quickly instead of having to type all of them one by one
When you need a character array you do not have to use individual character literals one by one, as in
char albet[] = {'a','b','c','d','e','f',... uff this is tedious ...};
You can use a string literal instead:
const std::string albet{"abcdefghijklmnopqrstuvwxyz"};
Took me ~10 seconds to type and compared to other answers, this does not rely on ASCII encoding (which is not guaranteed).
You could use std::iota, which is a great algorithm for this use case:
char albet[26] {};
std::iota(std::begin(albet), std::end(albet), 'a');
Here's a demo.
Note that this is not guaranteed to work in c++, unless you have ASCII encoding, but if you can rely on that you'll be fine.
Because all characters can be represented in ASCII codes ('a' starts at 97, all ASCII codes are int), you can simply make a loop to do that. For example:
char albet[26];
for (int ch = 'a'; ch <= 'z'; ch++) {
//do ch-'a' because we start at index 0
albet[ch-'a'] = ch;
}
and you are done!
Each letter has an ASCII representation. More about that here.
They are processed as numbers, being cast, and transformed into characters. For example, the letter a would be represented by the number 97 in decimal.
int aInAscii = 97;
printf("%c", (char)aInAscii);
The upper code would print, as you expect, the letter a. Why? Because we have just converted the number 97 to it's ASCII corresponding character.
So, in this way, we could generate the alphabet, using only numbers. A short example would be here (I preferred casting it before so that the starting and ending points are more clear.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<char> alphabet;
int aLetterCode = (int)'a'; // ASCII code for letter a (97)
int zLetterCode = (int)'z'; // ASCII code for letter z (122)
for (int charAsciiCode = aLetterCode; charAsciiCode <= zLetterCode; charAsciiCode++) {
alphabet.push_back((char)charAsciiCode);
}
for (char c : alphabet) {
cout << c << " ";
}
return 0;
}
You just can also make a function that returns a char, without generating an array, like this:
char get_alphabet_letter(unsigned int index, bool is_upper = false)
{
char letter = 97 + index;
if(is_upper) return letter - 32;
return letter;
}
from the given below code, you can generate uppercase alphabets of English. Uppercase alphabhets starts in ASCII from A = 65 to Z = 90. And, then, typecast the
integral value of uppercase alphabets into character using char().
#include <iostream>
using namespace std;
int main () {
char a[26];
for (int i=65 ; i<91 ; i++) {
int a[65-i] = char(i);
cout<<a<<endl;
return 0;
}
This question already has answers here:
What's the real use of using n[c-'0']?
(13 answers)
Closed 2 years ago.
I am confused with this line:
sum += a[s[i] - '0'];
To give some context, this is the rest of the code:
#include <iostream>
using namespace std;
int main() {
int a[5];
for (int i = 1; i <= 4; i++)
cin >> a[i];
string s;
cin >> s;
int sum = 0;
for (int i = 0; i < s.size(); i++)
sum += a[s[i] - '0'];
cout << sum << endl;
return 0;
}
- '0' (or less portable - 48, for ASCII only) is used to manually convert numerical characters to integers through their decimal codes, C++ (and C) guarantees consecutive digits in all encodings.
In EBCDIC, for example, the codes range from 240 for '0' to 249 for '9', this will work fine with - '0', but will fail with - 48). For this reason alone it's best to always use the - '0' notation like you do.
For an ASCII example, if '1''s ASCII code is 49 and '0''s ASCII code is 48, 49 - 48 = 1, or in the recommended format '1' - '0' = 1.
So, as you probably figured out by now, you can convert all the 10 digits from characters using this simple arithmetic, just subtracting '0' and in the other direction you can convert all digits to it's character encoding by adding '0'.
Beyond that there are some other issues in the code:
The array does not start being populated at index 0, but at index 1, so if your string input is, for instance, "10" the sum will be a[1] + a[0], but a[0] has no assigned value, so the behaviour is undefined, you need to wach out for these cases.
for (int i = 0; i < 5; i ++)
cin >> a[i];
would be more appropriate, indexes from 0 to 4, since the array has 5 indexes, if you want input numbers from 1 to 5, you can subract 1 from the to the index later on.
As pointed out in the comment section, a bad input, with alpabetic characters, for instance, will also invoke undefined behaviour.
From the C++ Standard (2.3 Character sets)
... In both the source and execution basic character sets, the value of
each character after 0 in the above list of decimal digits shall be
one greater than the value of the previous.
So if you have a character for example '4' then to get value 4 you can write '4' - '0'.
If you will write like for example
sum += a[s[i]];
where i is the character '0' then in fact you will have either
sum += a[s[48]];
if the ASCII coding is used or
sum += a[s[240]];
if the EBCDIC coding is used.
The reversed operation of getting a character from a digit you can write for example
int digit = 4;
char c = digit + '0';
Pay attention to that indices of arrays in C++ start from 0.
Thus this loop
for (int i = 1; i <= 4; i ++)
cin >> a[i];
should be written like
for (int i = 0; i < 5; i ++)
cin >> a[i];
Also to avoid such an error you could use the range based for loop like
for ( auto &item : a ) std::cin >> item;
For my university computer science course, our professor wants us to use a method of converting a string to an int (and int to string) without the use of any libraries such as sstream. I can't exactly find it anywhere in the notes/online and am hoping someone could show/tell me what it is and tell me how afterwards I would know that it has successfully been converted. All I know is that it involves using static_cast and also ASCII. He went over it quickly in class and I copied the code down quickly so there's a chance I could be missing something important or mistyped something, but here's what I got.
void intToStr(){
string numString = "2019";
int num = 0;
for(int i =0; i < numString.length(); i++){
char c = numString[i];
num = num * 10 + static_cast<int>(c) - static_cast<int>('0');
}
}
You don't have to create c as a char as that adds an extra step for conversion and can look overwhelming with static_cast
c++ will assign the ASCII value for a char if you assign it to an int so for example the char version of '2' has an ascii code of 50 to get it's integer value you subtract the char version of '0' as that is the first ascii value corresponding to digits, similarily if you want to get the number value of a letter say you're doing something like converting a string to a number you would first assign the letter to an int to get its ascii value and subtract the char 'a' or 'A' depending on what case you are working with and it would return that letters index in the alphabet, below is the code demonstrating what i'm taling about for numbers
// Example program
#include <iostream>
#include <string>
using namespace std;
int main(){
string numString = "2019";
int num = 0;
for(int i =0; i < numString.size(); i++){
int c = numString[i] -'0';
cout << c << endl;
num = num * 10 + c;
}
cout << num << endl;
}
So, I am trying to figure out the best/simplest way to do this. For my algorithms class we are supposed read in a string (containing up to 40 characters) from a file and use the first character of the string (data[1]...we are starting the array at 1 and wanting to use data[0] as something else later) as the number of rotations(up to 26) to rotate letters that follow (it's a Caesar cipher, basically).
An example of what we are trying to do is read in from a file something like : 2ABCD and output CDEF.
I've definitely made attempts, but I am just not sure how to compare the first letter in the array char[] to see which number, up to 26, it is. This is how I had it implemented (not the entire code, just the part that I'm having issues with):
int rotation = 0;
char data[41];
for(int i = 0; i < 41; i++)
{
data[i] = 0;
}
int j = 0;
while(!infile.eof())
{
infile >> data[j+1];
j++;
}
for(int i = 1; i < 27; i++)
{
if( i == data[1])
{
rotation = i;
cout << rotation;
}
}
My output is always 0 for rotation.
I'm sure the problem lies in the fact that I am trying to compare a char to a number and will probably have to convert to ascii? But I just wanted to ask and see if there was a better approach and get some pointers in the right direction, as I am pretty new to C++ syntax.
Thanks, as always.
Instead of formatted input, use unformatted input. Use
data[j+1] = infile.get();
instead of
infile >> data[j+1];
Also, the comparison of i to data[1] needs to be different.
for(int i = 1; i < 27; i++)
{
if( i == data[1]-'0')
// ^^^ need this to get the number 2 from the character '2'.
{
rotation = i;
std::cout << "Rotation: " << rotation << std::endl;
}
}
You can do this using modulo math, since characters can be treated as numbers.
Let's assume only uppercase letters (which makes the concept easier to understand).
Given:
static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const std::string original_text = "MY DOG EATS HOMEWORK";
std::string encrypted_text;
The loop:
for (unsigned int i = 0; i < original_text.size(); ++i)
{
Let's convert the character in the string to a number:
char c = original_text[i];
unsigned int cypher_index = c - 'A';
The cypher_index now contains the alphabetic offset of the letter, e.g. 'A' has index of 0.
Next, we rotate the cypher_index by adding an offset and using modulo arithmetic to "circle around":
cypher_index += (rotation_character - 'A'); // Add in the offset.
cypher_index = cypher_index % sizeof(letters); // Wrap around.
Finally, the new, shifted, letter is created by looking up in the letters array and append to the encrypted string:
encrypted_text += letters[cypher_index];
} // End of for loop.
The modulo operation, using the % operator, is great for when a "wrap around" of indices is needed.
With some more arithmetic and arrays, the process can be expanded to handle all letters and also some symbols.
First of all you have to cast the data chars to int before comparing them, just put (int) before the element of the char array and you will be okay.
Second, keep in mind that the ASCII table doesn't start with letters. There are some funny symbols up until 60-so element. So when you make i to be equal to data[1] you are practically giving it a number way higher than 27 so the loop stops.
The ASCII integer value of uppercase letters ranges from 65 to 90. In C and its descendents, you can just use 'A' through 'Z' in your for loop:
change
for(int i = 1; i < 27; i++)
to
for(int i = 'A'; i <= 'Z'; i++)
and you'll be comparing uppercase values. The statement
cout << rotation;
will print the ASCII values read from infile.
How much of the standard library are you permitted to use? Something like this would likely work better:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
int rotation = 0;
std::string data;
std::stringstream ss( "2ABCD" );
ss >> rotation;
ss >> data;
for ( int i = 0; i < data.length(); i++ ) {
data[i] += rotation;
}
// C++11
// for ( auto& c : data ) {
// c += rotation;
// }
std::cout << data;
}
Live demo
I used a stringstream instead of a file stream for this example, so just replace ss with your infile. Also note that I didn't handle the wrap-around case (i.e., Z += 1 isn't going to give you A; you'll need to do some extra handling here), because I wanted to leave that to you :)
The reason your rotation is always 0 is because i is never == data[1]. ASCII character digits do not have the same underlying numeric value as their integer representations. For example, if data[1] is '5', it's integer value is actually 49. Hint: you'll need to know these values when handle the wrap-around case. Do a quick google for "ANSI character set" and you'll see all the different values.
Your determination of the rotation is also flawed in that you're only checking data[1]. What happens if you have a two-digit number, like 10?
Below is an example code that is not working the way I want.
#include <iostream>
using namespace std;
int main()
{
char testArray[] = "1 test";
int numReplace = 2;
testArray[0] = (int)numReplace;
cout<< testArray<<endl; //output is "? test" I wanted it 2, not a '?' there
//I was trying different things and hoping (int) helped
testArray[0] = '2';
cout<<testArray<<endl;//"2 test" which is what I want, but it was hardcoded in
//Is there a way to do it based on a variable?
return 0;
}
In a string with characters and integers, how do you go about replacing numbers? And when implementing this, is it different between doing it in C and C++?
If numReplace will be in range [0,9] you can do :-
testArray[0] = numReplace + '0';
If numReplace is outside [0,9] you need to
a) convert numReplace into string equivalent
b) code a function to replace a part of string by another evaluated in (a)
Ref: Best way to replace a part of string by another in c and other relevant post on SO
Also, since this is C++ code, you might consider using std::string, here replacement, number to string conversion, etc are much simpler.
You should look over the ASCII table over here: http://www.asciitable.com/
It's very comfortable - always look on the Decimal column for the ASCII value you're using.
In the line: TestArray[0] = (int)numreplace; You've actually put in the first spot the character with the decimal ASCII value of 2. numReplace + '0' could do the trick :)
About the C/C++ question, it is the same in both and about the characters and integers...
You should look for your number start and ending.
You should make a loop that'll look like this:
int temp = 0, numberLen, i, j, isOk = 1, isOk2 = 1, from, to, num;
char str[] = "asd 12983 asd";//will be added 1 to.
char *nstr;
for(i = 0 ; i < strlen(str) && isOk ; i++)
{
if(str[i] >= '0' && str[i] <= '9')
{
from = i;
for(j = i ; j < strlen(str) && isOk2)
{
if(str[j] < '0' || str[j] > '9')//not a number;
{
to=j-1;
isOk2 = 0;
}
}
isOk = 0; //for the loop to stop.
}
}
numberLen = to-from+1;
nstr = malloc(sizeof(char)*numberLen);//creating a string with the length of the number.
for(i = from ; i <= to ; i++)
{
nstr[i-from] = str[i];
}
/*nstr now contains the number*/
num = atoi(numstr);
num++; //adding - we wanted to have the number+1 in string.
itoa(num, nstr, 10);//putting num into nstr
for(i = from ; i <= to ; i++)
{
str[i] = nstr[i-from];
}
/*Now the string will contain "asd 12984 asd"*/
By the way, the most efficient way would probably be just looking for the last digit and add 1 to it's value (ASCII again) as the numbers in ASCII are following each other - '0'=48, '1'=49 and so on. But I just showed you how to treat them as numbers and work with them as integers and so. Hope it helped :)