C++ place char in corresponding slot in array - c++

I need to store a letter a-z char to its corresponding slot in a size 0 - 25 array in c++. What's the best way to do this without a lot of if statements?

You can determine character index the following way:
int index = yourCharacter-'a';
And then use that index to store what you need

To work out the index just subtract 'a' from a char variable that holds the characters a-z. For example:
char c='x';
int index=(int)(c-'a');

Is this what are you looking for?
char c;
...
arrayName[c - 'a'] = value;

Edit
Not homework, so I'll clarify my answer.
const char * letters = "abcdefghijklmnopqrstuvwxyz";
Stores the letters from 'a' to 'z' in in an array. (Note that the array size is 27, not 26, because of the null character at the end of the string.)

Characters are just integers, so you can do arithmetic on them.
char c = ...;
array[c - 'a'] = c.
Note that upper case characters are distinct from lower case ones, so you'll need to handle them separately (if required).
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A'; // make lower case

If you want to be portable, you can't use the solution proposed by most
others: 'a' to 'z' are not necessarily contiguous. The surest
solution is to look the letter up in a table, and use the index of that
table, e.g.:
char letters[] = "abcdefghijklmnopqrstuvwxyz";
int index = std::find( begin( letters ), end( letters ) - 1, ch )
- begin( letters );
if ( index < size( letters ) - 1 )
// it's good
else
// character wasn't a (lower case) letter.
Note the - 1 for end and size: this is because letters has an
additional '\0' at the end.
Note that in a lot of cases, on a modern machine, it may be just simpler
to use an array of 256 entries; the difference in space isn't likely to
cause you to run out of memory, and the code to manage it will be a lot
simpler.

char letters[26];
for (char c = 'a'; c <= 'z'; c++)
{
letters[c - 'a'] = c;
}

Related

ROT13 Implementation using Char Arrays

I'm a newbie programmer who has been working on a ROT13 implementation as part of a tutorial and came across the following code. It outputs the correct characters however I'm not quite sure how it works and there is no explanation attached.
char rot13[] = { 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M' };
std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < alphabet.length(); i++) {
std::cout << rot13[alphabet[i] - 'A'];
}
Specifically, I dont quite understand how minusing the 'A' from a character within the string alphabet provides us with our ROT13 number. I initially thought that 'A' corresponded to an index within rot13[] and minusing that would provide us with a new index, however wouldn't that indicate that any numbers beneath A's index (Z,Y,X...) would become negative indexes as a result and throw errors.
Is anyone able to explain the logic behind this code to me?
Granted that alphabet[i] is an uppercase letter (which is the case in your example), alphabet[i] - 'A' will compute the distance to the letter 'A' in the ASCII table. So 'A'-'A' will be 0, 'B'-'A' will be 1 and so on, up to 'Z'-'A' which is 25.
Your character array rot13 is written so that the index 0 has the letter 'N', the index 1 is the letter 'O' and so on up to index 12 with the letter 'Z' and then index 13 is 'A', index 14 is 'B' and so on up to index 25 which is 'M'
To make things clearer, let’s rewrite this line:
std::cout << rot13[alphabet[i] - 'A'];
As:
char letterBeforeRot13 = alphabet[i];
int index = letterBeforeRot13 - 'A';
char letterAfterRot13 = rot13[index];
std::cout << letterAfterRot13;
This is pretty much what your compiler does, but with more details.
If we pick an example where alphabet[i] equals to the letter 'A', letterBeforeRot13 is assigned to the letter 'A', index is assigned to 'A'-'A' which is 0, letterAfterRot13 is assigned to the element of the array rot13 at index 0, which is 'N'. So the letter 'A' is transformed into 'N'.
You can do the same for any letter and you will see that everything is fine, including the edge cases when you thought that things would be out of bounds. You cannot have negative indexes with this technique.

What approach should I take towards converting ascii chars to other chars in c++

Well currently I am re creating my own version of enigma as a little project but if you understand how the enigma machine works it has rotors which connect a character to a completely different character for example A might be connected to F or U may be connected to C and this is done three times. Currently I am getting the char for the rotor by using this function:
char getRotorOne(char i) {
if(i == 'a') {
return 'g';
}if(i == 'b') {
return 'A';
}if(i == 'c') {
return 'o';
}
The main problem with this is it takes a long time to write and it seems inefficient and I think there must be a better way. The other problem with this is on the original enigma machine there were only the 26 letters of the alphabet on this there are the 94 tapeable characters of ascii (32-126) is there any other simpler way that this can be done? If you think this question is unclear or you don't understand please tell me instead of just flagging my post, then you can help me improve my question.
Use tables! Conveniently, C string literals are arrays of characters. So you can do this:
// abc
const char* lower_mapping = "gAo";
// ABC
const char* upper_mapping = "xyz";
char getRotorOne(char i) {
if (i >= 'a' && i <= 'z') return lower_mapping[i - 'a'];
if (i >= 'A' && i <= 'Z') return upper_mapping[i - 'A'];
assert(false && "Unknown character cannot be mapped!");
}
Since chars are really just small integers, and ASCII guarantees contiguous ranges for a-z and A-Z (and 0-9) you can subtract from a given character the first one in its range (so, 'a' or 'A') to get an index into that range. That index can then be used to look up the corresponding character via a table, which in this case is just a simple hardcoded string literal.
This is an improvement on Cameron's answer. You should use a simple char array for each rotor, but as you said you want to process ASCII characters in the range 32-126, you should build each mapping as an array of 95 characters:
char rotor1[95] ="aXc;-0..."; // the 95 non control ascii characters in arbitrary order
Then you write your rotor function that way:
char getRotorOne(char i) {
if ((i < 32) || (i > 126)) return i; // do not change non processed characters
return rotor1[i - 32]; // i - 32 is in range 0 - 94: rotor1[i - 32] is defined
}

remove non alphabet characters from string c++ [duplicate]

This question already has answers here:
How to strip all non alphanumeric characters from a string in c++?
(12 answers)
Closed 6 years ago.
I'm trying to remove all non alphabet characters from an inputed string in c++ and don't know how to. I know it probably involves ascii numbers because that's what we're learning about. I can't figure out how to remove them. We only learned up to loops and haven't started arrays yet. Not sure what to do.
If the string is Hello 1234 World&*
It would print HelloWorld
If you use std::string and STL, you can:
string s("Hello 1234 World&*");
s.erase(remove_if(s.begin(), s.end(), [](char c) { return !isalpha(c); } ), s.end());
http://ideone.com/OIsJmb
Note: If you want to be able to handle strings holding text in just about any language except English, or where programs use a locale other than the default, you can use isalpha(std::locale).
PS: If you use a c-style string such as char *, you can convert it to std::string by its constructor, and convert back by its member function c_str().
If you're working with C-style strings (e.g. char* str = "foobar") then you can't "remove" characters from a string trivially (as a string is just a sequence of characters stored sequentially in memory - removing a character means copying bytes forward to fill the empty space used by the deleted character.
You'd have to allocate space for a new string and copy characters into it as-needed. The problem is, you have to allocate memory before you fill it, so you'd over-allocate memory unless you do an initial pass to get a count of the number of characters remaining in the string.
Like so:
void BlatentlyObviousHomeworkExercise() {
char* str = "someString";
size_t strLength = ... // how `strLength` is set depends on how `str` gets its value, if it's a literal then using the `sizeof` operator is fine, otherwise use `strlen` (assuming it's a null-terminated string).
size_t finalLength = 0;
for(size_t i = 0; i < strLength; i++ ) {
char c = str[i]; // get the ith element of the `str` array.
if( IsAlphabetical(c) ) finalLength++;
}
char* filteredString = new char[ finalLength + 1 ]; // note I use `new[]` instead of `malloc` as this is C++, not C. Use the right idioms :) The +1 is for the null-terminator.
size_t filteredStringI = 0;
for(size_t i = 0; i < strLength; i++ ) {
char c = str[i];
if( IsAlphabetical(c) ) filteredString[ filteredStringI++ ] = c;
}
filteredString[ filteredStringI ] = '\0'; // set the null terminator
}
bool IsAlphabet(char c) { // `IsAlphabet` rather than `IsNonAlphabet` to avoid negatives in function names/behaviors for simplicity
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
I do not want to spoil the solution so I will not type out the code, only describe the solution. For your problem think of iterating through your string. Start with that. Then you need to decide if the currently selected character is part of the alphabet or not. You can do this numerous different ways. Checking ASCII values? Comparing against a string of the alphabet? Once you decide if it is a letter, then you need to rebuild the new string with that letter plus the valid letters before and after that you found or will find. Finally you need to display your new string.
If you look at an ascii table, you can see that A-Z is between 65-90 and a-z is between 97-122.
So, assuming that you only need to remove those characters (not accentuated), and not other characters from other languages for example, not represented in ascii, all you would need to do is loop the string, verify if each char is in these values and remove it.

Homemade Vigenere cipher; working with acsii character manipulation

As the post title suggests, I'm working to strengthen my grasp on C++ and character manipulation, this time through creating a Vigenere Cipher. For those unfamiliar with it, it's a fairly simple way to encrypt a text file.
The basic way it works is that there exists a string "key", and each character (in my case at least) is a lowercase alphabetical character. These are stored into an array and are used to "shift" the value of the file being encoded. A character of 'a' will shift the target by 0, while 'z' will shift it by 25. The "shift" is cyclical, meaning that if 'z' is shifted by 'b' (1) it should result in an 'a'.
My current method is found below:
//Assume cipher[] contains "[a][b][c][x ][y ][z ]" Cipher is a <string> object
//Assume ptr[] contains "[0][1][2][23][24][25]
#A whole bunch of includes
char c;
ifstream is;
ofstream os;
is.open(argv[3]) //"myinput.txt"
os.open(argv[4]) //"myoutput.txt"
int i = 0;
while( is.good() ) {
c = is.get();
if( is.good() ) { //did we just hit the EoF?
c = tolower( c - 0 ); //just make sure it's lowercase
c = c + ptr[ i % cipher.size() ] % 26;
if( c> 122 )
c = ( c % 123 ) + 97;
i++;
os.put( c );
}
}
My problem lies in my modulo operations, I believe. Maybe it's because I've spent so much time hashing this out, but I spent hours last night writing this, and then another hour lying in bed trying to wrap my mind around how to effectively create what I want:
grab char.
check char. //let char = 'z'
check the cipher. //let the cipher = 'y'
eval cipher shift //'y' shift value = 24
shift z 24 places (cyclically) //'z'==25, 25+24=49, 49%26=23. 23='x'
HERE IS THE ISSUE: How to do this with ACSII? ('a'=97, z='121')
Imagine that you want to "shuffle" the "ones" digits 0-9 between 20 and 29 by two steps, such that 20 becomes 22, and 29 becomes 21,. How would you do that?
Well, I would subtract 20 [our base number], and then shuffle the remaining digit, and then add 20 back in again.
newnum = num - 20;
newnum %= 10;
newnum += 20;
The same principle would apply for ascii - just that of course the base isn't 20.

Caesar cipher in C++

To start off, I'm four weeks into a C++ course and I don't even know loops yet, so please speak baby talk?
Okay, so I'm supposed to read a twelve character string (plus NULL makes thirteen) from a file, and then shift the letters backwards three, and then print my results to screen and file. I'm okay with everything except the shifting letters. I don't want to write miles of code to take each character individually, subtract three, and re-assemble the string, but I'm not sure how to work with the whole string at once. Can someone recommend a really simple method of doing this?
If you are dealing with simple letters (A to Z or a to z), then you can assume that the internals codes are linear.
Letters are coded as numbers, between 0 and 127. A is coded as 65, B as 66, C as 67, Z as 90.
In order to shift letters, you just have to change the internal letter code as if it were a number, so basically just substracting 3 from the character. Beware of edge cases though, because substracting 3 to 'A' will give you '>' (code 62) and not 'X' (code 88). You can deal with them using "if" statements or the modulo operator ("%").
Here is an ASCII characters table to help you
Once you've loaded your string in, you can use the modulous operator to rotate while keeping within the confines of A-Z space.
I'd keep track of whether the letter was a capital to start with:
bool isCaps = ( letter >= 'A' ) && ( letter <= 'Z' );
if( isCaps )
letter -= 'A'-'a';
and then just do the cipher shift like this:
int shift = -3;
letter -= 'a'; // to make it a number from 0-25
letter = ( letter + shift + 26 ) % 26;
// add 26 in case the shift is negative
letter += 'a'; // back to ascii code
finally finish off with
if( isCaps )
letter += 'A'-'a';
so, putting all this together we get:
char *mystring; // ciphertext
int shift = -3; // ciphershift
for( char *letter = mystring; letter; ++letter )
{
bool isCaps = ( *letter >= 'A' ) && ( *letter <= 'Z' );
if( isCaps )
*letter -= 'A'-'a';
letter -= 'a';
letter = ( letter + shift + 26 ) % 26;
letter += 'a';
if( isCaps )
letter += 'A'-'a';
}
You're going to have to learn loops. They will allow you to repeat some code over the characters of a string, which is exactly what you need here. You'll keep an integer variable that will be your index into the string, and inside the loop do your letter-shifting on the character at that index and increment the index variable by one until you reach NULL.
Edit: If you're not expected to know about loops yet in your course, maybe they want you to do this:
string[0] -= 3; // this is short for "string[0] = string[0] - 3;"
string[1] -= 3;
string[2] -= 3;
...
It will only result in 12 lines of code rather than miles. You don't have to "reassemble" the string this way, you can just edit each character in-place. Then I bet after making you do that, they'll show you the fast way of doing it using loops.
Iterate over the characters with a for loop. And do what you want with the char*. Then put the new char back.
for(int i=0; i<12; i++){
string[i] = string[i] - 3;
}
Where string is your character array (string). There is a bit more involved if you want to make it periodic (I.E. have A wrap round to Z, but the above code should help you get started)
I'm a little unclear what you mean by "shift the letters backwards 3"?
Does that mean D ==> A?
If so, here's a simple loop.
(I didn't do reading from the file, or writing to the file... Thats your part)
#include <string.h>
int main(void)
{
char input[13] = "ABCDEFGHIJKL";
int i;
int len = strlen(input);
for(i=0; i<len; ++i)
{
input[i] = input[i]-3;
}
printf("%s", input); // OUTPUT is: ">?#ABCDEFGHI"
}