Checking for characters in string in a do...while - c++

do
{
e=0;
cout << "Enter input of base " << base << ": ";
cin >> input;
for ( i=0; i<input.length(); i++)
{
if (input[i]=='A')
value=10;
else if (input[i]=='B')
value=11;
else if (input[i]=='C')
value=12;
else if (input[i]=='D')
value=13;
else if (input[i]=='E')
value=14;
else if (input[i]=='F')
value=15;
else
value=input[i];
if(value>=base)
{
cout << "Invalid input data for your input base!!!" << endl << endl;
e=1;
}
}
}while (e==1);
When ever the user key in let's say 101101, and the base is 2, it will output Invalid for 6 times. What's the error?
I tried to use npos, find(), but they didn't work!

Here:
value=input[i];
You seem to be assuming that the value of the character '0' is 0 and the value of character '1' is 1 (and similarly for other digits). Your assumption is wrong for the character encoding that your system uses. In fact, '0' cannot possibly be represented by the value 0, because that is reserved for the null terminator character that designates the end of a character string.
Thanks But what should i do next?
Subtracting value of a character from another gives you the distance between the representations of those characters (subtracting character from itself gives you 0). Number digit characters are guaranteed to be sequential (0 is immediately before 1 is immediately before 2 ...). Given these axioms, it's easy to prove that subtracting the value of '0' from a character gives you the value that you're looking for.

Replace:
else
value=input[i];
With:
else
value=input[i] - '0';
Because:
'0' = 0x30 = 48

Related

Issue with str.push_back

I am trying to create a C++ function with the following behavior:
Input: "A4B5C3" ; Output: "AAAABBBBBCCC"
Input: "R1T3" ; Output: "RTTT"
And so on.
I have written the following function:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string foo(string s){
int count = 0;
string t = "";
char letter = 'a';
for (string::iterator it=s.begin(); it<s.end(); it++){
if(count%2==0)
{
cout << "count: "<<count << " *it: "<< *it << endl;
letter = *it;
}
else
{
cout <<"count: "<< count << " *it: " << *it << " letter: " << letter << endl;
int j = 0;
while (j<*it)
{
t.push_back(letter);
j++;
}
}
count++;
}
cout << endl<<endl;
return(t);
}
However , on calling foo("A1B4C2D8"), I get this output:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
For some reason, my while loop seems to be running 48 more times than I would like it to...
There are no character encodings where the integer 1 is equal to the character '1' (for example).
In the ASCII encoding the character '1' is equal to the integer 49.
That means the condition j<*it is flawed.
The C++ specification requires that all digits are encoded consecutively, so '0' will always come before '1', and '1' will always come before '2', and so on. With that knowledge, together with knowing that char is a simple integer type, you can always subtract '0' from any digit character to get its integer value.
For example '2' - '0' == 2.
To solve your problem the condition should be j < (*it - '0').
Here :
while (j< *it)
you are comparing an integer (int) with a character (char). The character '0' does not equal 0, but as digits have consecutive representations you can subtract '0' from the character to get the corresponding integer:
while (j< *it - '0')
Issue is in the line
int j = 0;
while (j<*it)
...
You are comparing the int value with the chacter.
The character '0' in ASCII encoding has the hexadecimal integer value 0x30 and the decimal integer value 48. The character '1' has the hexadecimal integer value 0x31 and the decimal integer value 49. And so on till '9' that has the hexadecimal integer value 0x39 and the decimal integer value 57.
Even not knowing those ASCII codes the shortest fix is changing int j = 0; to int j = '0'; or char j = '0';. Then the loop while (j < *it) will iterate correctly.

How can the symbols be bigger than each other? Or do I not understand something? Could you explain what this code does?

Is it ok to compare symbols with each other?
#include <iostream>
using namespace std;// For Example, Why if "k = 4" it outputs "r o" ? //
int main() {
char word[] = "programming";
int k;
cin >> k;
for (int i = 0; i < k; i++)
if (word[i] > word[i + 1]) {
cout << word[i] << endl;
}
}
The char data type is an integral type, meaning the underlying value is stored as an integer. Moreover, the integer stored by a char variable is intepreted as an ASCII character.
ASCII specifies a way to map english characters(and some other few symbols) to numbers between 0 and 127. That is, each english character(and some other few symbols) has a corresponding number between 0 and 127. This number is formally called a code point.
For example, the code point for the english character a is 97. Similarly, the code point for the english character H is 72. You can find the list of code points for all the characters here.
The important thing to note here is that the underlying value of a char variable is stored as an integer. Lets take some examples to clarify this,
char var1 = 'a'; //here var1 is stored as the integer 97
char var2 = 'H'; //here var2 is stored as the integer 72
In the above snippet, var1 is stored as the integer 97 because the code point for the english character a is 97. Similarly, var2 is stored as the integer 72 because the english character H corresponds to the code point 72.
Now lets come back to your original question. In particular what happens when k =4.
For k = 4, the for loop will be executed 4 times.
Iteration 0: Here i = 0
The if block basically translates to:
if (word[0] > word[0 + 1]) {
cout << word[0] << endl;
}
which is:
if ('p' > 'r') {
cout << 'p' << endl;
}
which is(using the ascii table):
if (112 > 114) {
cout << 'p' << endl;
}
since the condition inside if is false, the body of the if block will not be executed and you'll get no output.
Iteration 1: Here i = 1
The if block basically translates to:
if (word[1] > word[1 + 1]) {
cout << word[1] << endl;
}
which is:
if ('r' > 'o') {
cout << 'r' << endl;
}
which is(using the ascii table):
if (114 > 111) {
cout << 'r' << endl;
}
since the condition inside if is true, the body of the if block will be executed and you'll get r as output(which is followed by a newline).
Iteration 2: Here i = 2
The if block basically translates to:
if (word[2] > word[2 + 1]) {
cout << word[2] << endl;
}
which is:
if ('o' > 'g') {
cout << 'o' << endl;
}
which is(using the ascii table):
if (111 > 103) {
cout << 'o' << endl;
}
since the condition inside if is true, the body of the if block will be executed and you'll get o as output(which is followed by a newline).
Iteration 3: Here i = 3
The if block basically translates to:
if (word[3] > word[3 + 1]) {
cout << word[3] << endl;
}
which is:
if ('g' > 'r') {
cout << 'g' << endl;
}
which is(using the ascii table):
if (103 > 114) {
cout << 'g' << endl;
}
since the condition inside if is false, the body of the if block will not be executed and you'll get no output.
Hence you get the output:
r
o
Is it ok to compare symbols with each other?
Yes, it is OK.
Why if "k = 4" it outputs "r o" ?
Character types are integers. Each integer value of the character type is mapped to a symbol1. This mapping is called a character set or character encoding.
In the character encoding of the system where you ran the program, the value of the character that maps to the symbol 'r' has a greater value than the character that maps to the symbol 'o', while that 'o' character has smaller value than the character that maps to 'g'.
1 This is a simplification. There are special non-printable charcters such as null terminator which aren't symbols as such. Furthermore, the mapping isn't so simple in case of variable length encodings (Unicode).

converting a char variable in an array to an int C++

I have an array ( char location[2]; ) This needs to receive two values from the user. The first is a letter the other a number, in that order. This is used to select a location in a 9 x 9 grid.
The grid appears
A B C D E F G H I
1
2
3
4
5
6
7
8
9
When I try to store the second value as an int, The method I would think would work is being set to -48.
int row = location[1] - 48;
48 is the ASCII value of '1'. Shouldn't this have created an int with the value of one less than whatever number was input by the user? '2' (aka 49) - 48 = 1? It always comes out as -48 no matter what the input is.
My full function:
#include <iostream>
using namespace std;
void getLocation(int &column, int &row)
{
int row = 0;
int column = 0;
char location[2];
cout << "location: ";
cin.getline(location,2);
cin.ignore();
cin.clear();
switch (location[0])
{
case 'A':
cout << "case A\n";
column = 0;
break;
case 'B':
cout << "case B\n";
column = 1;
break;
case 'C':
cout << "case C\n";
column = 1;
break;
}
row = location[1] - 48;
cout << "column: "
<< column
<< " row: "
<< row
<< "\n";
}
location[1] - 48 will always be -48 if positive-length string is given because terminating null-character will be stored there. Allocate enough length to store the input. You are using C++, so using std::string is better to store strings than using arrays of char.
cin.getline(location,2) does not behave in the way you expect.
It writes a nul-terminated string to location i.e. location[0] is read from cin, and location[1] receives a character with value of 0 (numeric zero, not '0').
0 - 48 always produces a result of -48 as an int.
Note, also, that '1' is not guaranteed to have a value of 48. '0' does in ASCII and compatible character sets. Other character sets will give different values.
You would be better off using std::string - that eliminates the need to worry about arrays of char and nul termination.
The size of the stream for cin.getline needs space for a null terminator. Therefore, increase the size of the stream buffer and terminate input on the carriage return:
cin.getline(location, 3, '\r');

How to reset .get()

I'm trying to find the amount of letters of the alphabet from a file I have. I can get the first letter A to give me the correct number, but when the for loop goes through it only gives me 0 for the rest of the letters. I feel like it has to do with my .get() not starting at the beginning of the file again. What do I need to do to fix this? Thanks!
ifstream openFile("data.txt");
int numberOfLetters(0);
char letter;
for (int i = 0; i < 26; i++)
{
numberOfLetters = 0;
openFile.clear();
while (!openFile.eof())
{
openFile.get(letter);
if (letter == char(i + 97) || letter == char(i + 65))
{
numberOfLetters++;
}
}
cout << numberOfLetters;
}
The problem is your outer loop: It looks like you want to use this loop to check if the characters taken from the file are equal to certain characters from a certain range. If this is the case, performing the input within the loop is not the way to go.
On the first iteration of the loop, the file will be read completely such that by the second iteration openFile.get(letter) won't extract anything into letter, leaving it with its previous value, same for the rest of the outer iterations. It must be that the last value previous had didn't pass the if() statement test, so numberOfLetter didn't increment.
The solution is to change the way you check if the character is alphabetic. Characters are represented using the ASCII format, which are just integers mapped to characters. Since characters are really integers, you can use arithmetic operations on them. Moreover, characters are represented alphabetically in ASCII, so you can simply compare their values to see if they are in the range of alphabetic characters:
while (openFile.get(letter))
{
if (('a' <= letter && letter <= 'z') || ('A' <= letter && letter <= 'Z'))
{
numberOfLetters++;
}
}
cout << numberOfLetters;
Fortunately the standard library provides a function std::isalpha() that does this for you.
...
if (std::isalpha(letter))
{
numberOfLeters++;
}
...
Based on your comment, checking if a character is alphabetic is not enough. Instead, use a data structure like std::map in order to keep a total count of the number of certain characters:
#include <map>
std:map<char, std::size_t> alpha_count;
while (openFile.get(letter))
{
if (std::isalpha(letter))
alpha_count[letter]++;
}
Now to print how many specific characters there are, loop through the map and print the character's count():
for (auto&& c : alpha_count)
{
std::cout << "# of " << c << ": " << alpha_count.count(c) << '\n';
}

Code adding \n and 1, and I don't know why

This is a bit complicated, but basically I'm making a program and one of my functions is acting a bit strange. The function is fed an array of characters, the first time it's
new_sensor_node SN42 42 3.57 5.0 7.
right now the function just prints out each individual "token" (each set of characters separated by spaces). Then prints a space, and then prints the number of characters in the token. But for some reason, the last token is always printed weird, and 1 character extra is counted.
Here's the function:
int parseCommandLine(char cline[], char *tklist[]){
int i;
int length;
int count = 0; //counts number of tokens
int toklength = 0; //counts the length of each token
length = strlen(cline);
for (i=0; i < length; i++) { //go to first character of each token
if (((cline[i] != ' ' && cline[i-1]==' ') || i == 0)&& cline[i]!= '"') {
while ((cline[i]!=' ')&& (cline[i] != '\0')){
toklength++;
cout << cline[i];
i++;
}
cout << " " << toklength << "\n\n";
cout << "\n";
toklength = 0;
count ++;
}
if (cline[i] == '"') {
do {
i++;
} while (cline[i]!='"');
count++;
}
}
//cout << count << "\n";
return 0;
And here's the output (for that first array):
new_sensor_node 15
SN42 4
42 2
3.57 4
5.0 3
7.
3
Any thoughts on what could be causing this? I suspect it might have to do with how I'm dealing with the null character
It's very likely that the input string actually contains the newline at the end. Depending on how you read the input, it may or may not be in the input. For example, the fgets function reads the newline and leaves it in the buffer.
Especially since you don't actually do any actual tokenization or modification of the input string, you just print character by character, this is a very likely scenario.