I have an array of characters populated by cin, but im trying to find a way to check each character individually to make sure its only one of a set number of characters (a-z,A-Z,0-9,[space]).
The easiest way I thought this could be done is to check if the code of the character fell within a certain range. But not sure how to get it.
Alternatively if anyone knows any other ways of doing it, that would be great.
The easiest way is to use isalpha(), isdigit() or isalnum():
char ch = ... // The character
// Original solution
if (isalpha(ch) || isdigit(ch)){
}
// Better solution by fefe (see comments)
if (isalnum(ch)){
}
These are defined in ctype.h: http://www.cplusplus.com/reference/clibrary/cctype/
Otherwise you can also use comparisons:
if ('a' <= ch && ch <= 'z' ||
'A' <= ch && ch <= 'Z' ||
'0' <= ch && ch <= '9'
){
}
This latter approach using comparisons will generalize to arbitrary ranges.
You can easily access a specific character code by using the character you want in single quotes, for example, 'A'. Therefore, if you wanted to check if a character is in a certain range:
char c = //some character
if ( c >= 'A' && c <= 'Z' ) {
//do something
}
should work as you would expect. Additionally, if you are concerned about alpha-numerics specifically, there is a helper function called isalnum, defined in <ctype.h> that checks if a character is an alphanumeric character.
You can determine if the number falls within the range you are looking for within an ASCII table: http://www.asciitable.com/index/asciifull.gif. So >= 48 && < 123.
Related
I am writing a program that takes a char and compares it to see if it's in a range of certain chars. For instance, if the char I get is an n I go to state 3, if its a - m or o - z I go to state 4. I'm new to C++ so I'm still learning.
Can I say something like:
char c = file.next_char();
...
if (c in 'a'...'m', 'o'...'z')
{
state = 3;
} else {
state = 4;
}
There is no such syntax in C++. The options are:
Use a switch statement, when the list of values is generally not contiguous, or
Convert the list of explicit character values into contiguous ranges into equivalent boolean expressions. As you know, alphabetic characters consist of a contiguous range of octets in ASCII, so your pseudo-code is equivalent to:
if ( (c >= 'a' && c <= 'm')
||
(c >= 'o' && c <= 'z'))
If you are using ascii (English), you can rely on the fact that all the lower case letters are adjacent. Just check 'a' <= c && c <= 'z'
after ruling out 'n'.
You never said what happens if the state is not one of those, so I left it alone.
// 3 and 4 mean nothing. Give your states meaningful names
enum state_type {FirstState, SecondState, ThirdState, FourthState};
state_type state = FirstState;
char c = get_next_char();
if ('n' == c){
state = FourthState;
} else if ('a' < c && c < 'z'){
state = ThirdState;
} else {
// no change?
}
You could maybe use a for loop to compare it to see if it's a letter in the first or second range. The code would be something this:
char range1[/*amount in array here*/] = "abcdefghijklmnopqrstuvwxyz";
//Substitute range on line above(the characters in the string)
for(int i = 0; i <= /*amount in array here*/; i++) {
if(range1[i] == /*nameoflettervariablehere*/){
//Code here
}
}
I'm sorry but I don't know of a more efficient way.
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
}
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;
}
I am writing a C++ program. I have an array of char array trans[20][100]. Actually each string of trans is a transition of a grammar(Programming language translators). I want to check for each string in trans whether there is a Non-terminal after a '.' i.e. i want to check if in the strings there is a '.' followed by any capital letter. Can anyone please tell me how to do it??
-Thanks in advance
You can use any RegExp library (e.g. this one). The test regular expression is /\.[A-Z]/.
Or for ASCII string you can use:
int strHasDotCap(const char *s)
{
while (*s) {
if (*s++ == '.') {
if (*s >= 'A' && *s <= 'Z') return 1;
}
}
return 0;
}
You can use the functions in ctype.h isAlpha(), isUpper() etc. if the characters are ASCII type.
If you operate on ASCII char, then you could test if the int value of the char is between 65 and 90. See the ASCII table.
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"
}