C++ while loop, using if else statements to count in an array - c++

I'm having trouble with a basic c++ program assignment, and would greatly appreciate any help. The assignment is as follows:
Write a program that accepts input from the keyboard (with the input
terminated by pressing the Enter key) and counts the number of letters (A-Z and a-z), numerical digits (0-9), and other characters. Input the string using cin and use the following looping structure to examine each character in the string with an "if" statement and multiple "else if" statements.
My program thus far is:
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int numLet, numChars, otherChars = 0;
cout << "Enter a continuous string of characters" << endl;
cout << "(example: aBc1234!##$%)" << endl;
cout << "Enter your string: ";
cin >> s;
i = 0;
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z') || s[i] >= 'A' && (s[i] <= 'Z'))
{numLet++;
}
else if (s[i] >= 48 && s[i] <= 57)
{numChars++;
}
else if ((s[i] >= 33 && s[i] <= 4) || (s[i] >= 58 && s[i] <=64) || (s[i] >= 9 && s[i] <= 96) || (s[i] >= 123 && s[i] <= 255))
{otherChars++;
}
i++;
}
cout << numLet << " letters" << endl;
cout << numChars << " numerical characters" << endl;
cout << otherChars << " other characters" << endl;
return 0;
}
The letter count gives a value a little too low, and the number count gives a large negative number. Other chars seems to function fine.

As mentioned in the other answer, you need to initialize your variables, but you have also an error in this code:
if ((s[i] >= 'a' && s[i] <= 'z') || s[i] >= 'A' && (s[i] <= 'Z'))
the brackets are wrong. And as a result, you are not counting lowercase letters (i think) anyways it shoul be this (indented for visibility):
if (
(s[i] >= 'a' && s[i] <= 'z') ||
(s[i] >= 'A' && s[i] <= 'Z')
)
you can also use this. Since you're using c++ and not c, right ;) (people here get mad about the difference apparently)

You need to set each integer to 0. As it is, your code only sets otherChars = 0. Make that line numLet = 0, numChars = 0, otherChars = 0;.

Related

Dynamically allocated array always set to size 1 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 months ago.
Improve this question
I am making a program to calculate the value of words for a friend who is interested in numerology.
In my program, I ask the user how many words they want to calculate, so I can dynamically allocate the size of the array to store the words.
It works perfectly the first time they run the program, but when I ask if they want to test more words, and if they hit yes, it reruns the while loop and it asks them for how many words to evaluate, but this time, no matter what number they type, it always sets the size of the array to 1, due to the number variable being set to 1 and not changing after user input. My friend has to rerun the program to make it work again.
I really want to fix this problem to make it easier for my friend.
(Yes, I do plan on fixing my code, and if you have seen this code in another question, that was me, and yes, I am going to improve my code based on the suggestions I got, but I want it to at least work before I improve on it.)
Here is my code:
#include <iostream>
#include <string>
#include <sstream>
void clear()
{
system("clear");
}
int main(int argc, char* argv[])
{
int number{1};
int total{0};
int value{0};
std::string number_str;
std::string response;
std::stringstream ss;
bool isDigit;
while (true)
{
clear();
number = 1;
total = 0;
value = 0;
number_str = "";
response = "";
isDigit = true;
clear();
std::cout << "How many words to evalute? (Default: 1):\n> ";
//std::cin >> number;
std::getline(std::cin, number_str);
//std::cin.ignore();
clear();
for (int i = 0; i < number_str.size(); ++i)
{
if (!(std::isdigit(number_str[i])))
isDigit = false;
break;
}
if (isDigit)
{
if (number_str.empty()) {
number = 1;
} else {
ss << number_str;
ss >> number;
}
}
if (std::isdigit(number)) {
if (number <= 0) {
number = 1;
}
}
std::string* pPhrase = new std::string[number];
int* pValue = new int[number]{}; // Initialized each element to 0
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
{
(i == 0) ? std::cout << "Enter Word #" << i+1 << " (or type your full phrase):\n> " :
std::cout << "Enter Word #" << i+1 << ":\n> ";
std::cin >> pPhrase[i];
for (char j : pPhrase[i])
{
value = 0;
if (std::isalnum(j) && j != '0')
{
if (std::isalpha(j))
j = std::tolower(j);
} else {
continue;
}
if (j == 'a' || j == 'i' || j == 'j'
|| j == 'q' || j == 'y' || j == '1')
value += 1;
if (j == 'b' || j == 'k' || j == 'r' || j == '2')
value += 2;
if (j == 'c' || j == 'g' || j == 'l'
|| j == 's' || j == '3')
value += 3;
if (j == 'd' || j == 'm' || j == 't' || j == '4')
value += 4;
if (j == 'e' || j == 'h' || j == 'n'
|| j == 'x' || j == '5')
value += 5;
if (j == 'u' || j == 'v' || j == 'w' || j == '6')
value += 6;
if (j == 'o' || j == 'z' || j == '7')
value += 7;
if (j == 'f' || j == 'p' || j == '8')
value += 8;
pValue[i] += value;
value = 0;
std::cout << '\n';
clear();
}
}
std::cin.ignore();
std::cin.clear();
std::cout << "\n\n";
for (int i = 0; i < number; ++i)
{
std::cout << "Value of \"" << pPhrase[i] << "\": " << pValue[i] << '\n';
total += pValue[i];
}
std::cout << "Total value: " << total << "\n\nPress \'Enter\' or \'Return\' to Continue... ";
//std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
//std::cin.clear();
std::cout << "\n\n\nWould you like to evaluate another phrase? (Y/n):\n> ";
std::getline(std::cin, response);
delete[] pPhrase;
delete[] pValue;
if (response[0] == 'y' || response[0] == 'Y'
|| response.empty() || response[0] == ' ')
continue;
break;
}
std::cout << "Exiting...";
try {
//system("killall Terminal");
} catch (std::exception& ex) {}
std::cout << "\n\n\n";
return 0;
}
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
Actually, you can't use the sizeof(array)/sizeof(array[0]) trick on a pointer to an array. It only works when you use it directly on the actual array itself. There are numerous questions on StackOverflow that explain this, including (just to name a few):
How to get the size of an array using a pointer to the first element and properties of "\0"?
Pointer to an array get size C++
getting size of array from pointer c++
In any case, one problem I do see in your code is that on each iteration of the outer while loop, you are not resetting the std::stringstream that you use to convert the user's input to the number variable. Each iteration is just pushing more and more data into the stream without removing the old data first.
Also, using std::isdigit(number) is useless. You already validated the user entered only digits, and then converted those digits to the number variable. What you didn't do is validate that the conversion to int was actually successful before using number. You must validate that the extraction of the number from the stringstream is successful, ie in case the user enters a large value that can't fit into an int.
Try this instead:
while (true)
{
clear();
number = 1;
total = 0;
value = 0;
number_str = "";
response = "";
isDigit = true;
// ADD THIS!
ss.str("");
ss.clear();
//
...
if (isDigit)
{
ss << number_str;
if (!(ss >> number) { // <-- ADD THIS!
number = 1;
}
}
...
}
That being said, you could just get rid of the stringstream altogether, you don't actually need it. You can extract the number value directly from std::cin itself (which you are already aware of, because you commented out that code), eg:
std::cout << "How many words to evalute? (Default: 1):\n> ";
if (!(std::cin >> number)) {
number = 1;
std::cin.clear();
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// no need for the `isdigit() check at all...

logical operators in if statements c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
The current code at the bottom works but I can't combine the if statements without shifting the ascii values to a position that I don't want them to be. The encryption is supposed to be only alphabet values. Capital and lowercase z's are supposed to loop around to an A. I have a teacher but she doesn't know so I would be grateful for any help. Thanks <3
This doesn't work...
if (sentence[i] == 'z' || 'Z')
{
sentence[i] = sentence[i] - 26;
}
And this doesn't work
if (sentence[i] == 'z' || sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
This works.
if (sentence[i] == 'z')
{
sentence[i] = sentence[i] - 26;
}
if (sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
Full code.
#include <iostream>
#include <string>
using namespace std;
class EncryptionClass
{
string sentence;
public:
//constructors
EncryptionClass(string sentence)
{setString(sentence);}
EncryptionClass()
{sentence = "";}
//get and set
string getString()
{return sentence;}
void setString(string sentence)
{this-> sentence = sentence;}
//encrypt
void encryptString()
{
for(int i = 0; i < sentence.length(); i++)
{
if (isalpha(sentence[i]))
{
if (sentence[i] == 'z')
{
sentence[i] = sentence[i] - 26;
}
if (sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
sentence[i] = sentence[i] + 1;
}
}
}
};
int main()
{
string sentence;
cout << "Enter a sentence to be encrypted. ";
getline(cin, sentence);
cout << endl;
EncryptionClass sentence1(sentence);
cout << "Unencrypted sentence." << endl;
cout << sentence1.getString() << endl << endl;
sentence1.encryptString();
cout << "Encrypted sentence." << endl;
cout << sentence1.getString() << endl;
cin.get();
return 0;
}
In your case both If statements should both be equally.
if (sentence[i] == 'z' || sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
And:
if (sentence[i] == 'z')
{
sentence[i] = sentence[i] - 26;
}
if (sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
This is not always the case.
Snippet 2: if you change the value if i or sentence[i], the 2nd if will behave different.
If you would decrement by value 32, then both snippets will behave different
char myChar = 'z'
if (myChar == 'z' || myChar == 'Z')
{
myChar = myChar - 32;
}
// myChar is now 'Z'
And:
char myChar = 'z'
if (myChar == 'z')
{
myChar = myChar - 32;
}
// myChar is now 'Z'
if (myChar == 'Z')
{
myChar = myChar - 32;
}
// myChar is now ':'
The problem is you should be deducting 25 from your value, not 26! That's because there are 26 letters in the alphabet, relatively numbered from 0 to 25 (inclusive). To arrive at the first letter (number 0) from the last letter (number 25) you need to deduct 25.
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
But every version except the first version should give the same results.
#include <iostream>
int main()
{
char sentance[] = "Zz";
for(int i = 0; i < 2; ++i)
{
if(sentance[i] == 'Z' || sentance[i] == 'z')
{
sentance[i] = sentance[i] - 25;
std::cout << "letter " << i << " = " << sentance[i] << '\n';
}
}
}
Run it here

Having trouble grasping simple boolean loop if/else program in C++

I need a little help figuring out a couple of parts from a C++ assignment. I am asked to write a program as follows:
Write a program that accepts input from the keyboard (with the input
terminated by pressing the Enter key) and counts the number of letters (A-Z and a-z), numerical digits (0-9), and other characters. Input the string using cin and use the following looping structure to examine each character in the string with an "if" statement and multiple "else if" statements.
char s[50];
int i;
. . .
i = 0;
while (s[i] != 0) { // a string is terminated with a null (0) value
. . .
i++;
}
Your program should make use of the relational operators (e.g., == < > <= >= !=) to determine whether a particular character is a letter, number, or other character. You may only #include and
may not use any other include files.
The program should have an output similar to the following:
Enter a continuous string of characters with no blank spaces (example: aBc1234!##$%)
enter your string: aBc1234!##$%
your string has 12 total characters
3 letters
4 numerical characters
5 other characters
Here is an example program that counts lower case letters:
// PROG07.CPP example
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int lowercase = 0;
//get string from the user
cout << "Enter a continuous string of characters with no blanspaces\n"
cout << "(example: aBc1234!##$%)" << endl << endl;
cout << "Enter your string: ";
cin >> s;
cout << endl;
// loop through the string, lower case letters
// note, strings (character arrays) have an invisible
// zero value at their end
i = 0;
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z'))
lowercase++;
i++;
}
cout << "Your string has " << lowercase << " lower case letters" << endl;
// including the next line for Dev-C++:
system("pause"); // not needed for CodeBlocks
return 0;
}
So far, I have come up with this:
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int lowercase, uppercase, numChars, otherChars = 0;
cout << "Enter a continuous string of characters" << endl;
cout << "(example: aBc1234!##$%)" << endl;
cout << "Enter your string: ";
cin >> s;
cout << endl;
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z'))
lowercase++;
i++;
}
while (s[i] != 0)
{
if ((s[i] >= 'A' && s[i] <= 'Z'))
uppercase++;
i++;
}
cout << lowercase + uppercase << " letters" << endl;
i = 0;
while (s[i] != 0)
{
if ((s[i] >= '0' && s[i] <= '9'))
numChars++;
i++;
}
cout << numChars << " numerical characters" << endl;
return 0;
}
Any help would be greatly appreciated.
You have to reset i to 0 before every loop:
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int lowercase, uppercase, numChars, otherChars = 0;
cout << "Enter a continuous string of characters" << endl;
cout << "(example: aBc1234!##$%)" << endl;
cout << "Enter your string: ";
cin >> s;
cout << endl;
i = 0; //missing
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z'))
lowercase++;
i++;
}
i = 0; // missing
while (s[i] != 0)
{
if ((s[i] >= 'A' && s[i] <= 'Z'))
uppercase++;
i++;
}
cout << lowercase + uppercase << " letters" << endl;
i = 0;
while (s[i] != 0)
{
if ((s[i] >= '0' && s[i] <= '9'))
numChars++;
i++;
}
cout << numChars << " numerical characters" << endl;
return 0;
}
Looks good so far, just a few things
First off, you only need the one while loop:
while (s[i] != 0)
{
//All your if checks can go in here
}
Then, according to the output you need, you will need 4 variables:
int total, lettters, numbers, otherCharacters;
At the start of your loop, add to total:
while (s[i] != 0)
{
total++;
}
Then you will need 3 if checks inside your while loop, one for letters, one for numbers, and one for other characters:
if ((s[i] > 'a' && s[i] < 'z') || (s[i] > 'A' && s[i] < 'Z')) { ... }
else if (s[i] > '0' && s[i] < '9') { ... }
else { ... }
Then just output all your variables according to the output you mentioned:
cout << "your string has " << total << " total characters, " << letters << " letters, " << numbers << " numerical characters, and " << otherCharacters << " characters.";

Encrypting and decrypting part of the ASCII table

I have made small encryption program that uses to keys rot7 and rot13. Everything works fine except two 6 letters uvwxyz.
If I type ABCDEFGHIJKLMNOPQRSTUVWXYZ it encrypts and decrypts no problem. However, if I enter the same in lower case letters then uvwxyz do not work.
Having said this, I have allowed all the writable characters within the ascii table as the valid range as follows:
// allow all writable characters from 32 to 255
if ((str[i] >= 32 ) && (str[i] <=255))
{
str[i] -= key;
}
Here is the process of encryption:
cout << endl;
cout << "Encrypting process started " << endl << endl;
cout << "--------------------------- " << endl;
//get the string length
int i = 0;
int length = str.length();
int key = rot13 ;
int k = 5;
int multiple = 0;
int count = 0;
cout << "the text to encrypt is: " << str << endl;
cout << "text length is: " << length << endl;
cout << "using rot13"<<endl;
cout <<"---------------------------" << endl;
cout << "using rot13" << endl;
//traverse the string
for(i = 0; i < length; i++)
{
count ++;
cout << left;
//if it is a multiple of 5 not the first character change the key
if((multiple = (( i % 5 ) == 0)) && (count != 1) && (key == rot13)){
key = rot7;
}
//if it is a multiple of 5 not the first character change the key
else if((multiple = (( i % 5 ) == 0)) && (count != 1) && (key == rot7) ) {
key = rot13;
}
// Capital letters are 65 to 90 (a - z)
if ((str[i] >= 32) && (str[i] <= 255))
{
str[i] += key;
}
}
return str;
How is it possible that the capital letters work and not the lower case if I have allowed this range? Can it be because of something else? I have added these captures with what happens step by step... hopefully this helps
In your code :
if ((str[i] >= 32) && (str[i] <= 255))
{
if (str[i] + key > 255)
str[i] = ((str[i] + key) % 255 )+ 32;
else
str[i] += key;
}
if key has a value of 13 and str[i] is 'u' or greater, str[i] has a value higher than 255.
You should use modulo % operator in this case, this is rotation, not only a shift

Can I chain comparisons together in an IF statement?

I am currently making a naught's and crosses program for college. I have finished the bare bones of this assignment however I am having some trouble creating a win condition to end the game. Below is all of the code I have used so far:
#include <iostream>
#include <string>
using namespace std;
class Player
{
private:
char NorX;
public:
char Choose(char InitialValue)
{
NorX = InitialValue;
return InitialValue;
}
char GetNorX()
{
return NorX;
}
};
int main()
{
Player Player1;
Player Player2;
Player1.Choose('O');
Player2.Choose('X');
cout << "The board is being drawn please wait..." << endl;
const int Rows = 4;
const int Columns = 4;
char Board[Rows][Columns] = { {' ', ' ', ' ', ' ' },
{' ', '_', '_', '_' },
{' ', '_', '_', '_' },
{' ', '_', '_', '_' } };
for (int i = 0; i < Rows; ++i)
{
for (int j = 0; j < Columns; ++j)
cout << Board [i][j];
cout << endl;
}
cout << endl << endl;
int row;
int column;
do
{
do
{
cout << "Please enter the value of the row you would like to take ";
cin >> row;
}while (row != 0 && row != 1 && row != 2 && row != 3);
do
{
cout << "Please enter the value of the column you would like to take ";
cin >> column;
}while (column != 0 && column != 1 && column != 2 && column != 3);
Board [row][column] = Player1.GetNorX();
for (int i = 0; i < Rows; ++i)
{
for (int j = 0; j < Columns; ++j)
cout << Board [i][j];
cout << endl;
}
/*int row;*/
do
{
cout << "Please enter the value of the row you would like to take ";
cin >> row;
}while (row != 0 && row != 1 && row != 2 && row != 3);
/*int column;*/
do
{
cout << "Please enter the value of the column you would like to take ";
cin >> column;
}while (column != 0 && column != 1 && column != 2 && column != 3);
Board [row][column] = Player2.GetNorX();
for (int i = 0; i < Rows; ++i)
{
for (int j = 0; j < Columns; ++j)
cout << Board [i][j];
cout << endl;
}
if (Board[1][1] == Board[1][2] == Board[1][3] == 'O')
{
cout << endl << "Well done you win";
}
}while (column != 4 && row != 4);
system("pause");
}
The problem occurs in the if statement as it doesn't seem to have any affect on the running of the program.
The result of chaining comparison operators in C++ is not what one expects. The correct way to do this is to connect them with a "logical and" &&
if (Board[1][1] == 'O' && Board[1][2] == 'O' && Board[1][3] == 'O')
For the given example
if (Board[1][1] == Board[1][2] == Board[1][3] == 'O')
you must consider operator precedence, which is left to right for equality operator ==. This means, the example is the same as (note the additional parenthesis)
if ((Board[1][1] == Board[1][2]) == Board[1][3]) == 'O')
and works as follows:
Board[1][1] == Board[1][2]
gives either true or false. This will be compared to the next part
true == Board[1][3]
which gives false, because true or false is never equal to a character. This will be compared to the character zero
false == '0'
which again will result in false.
You cannot do this stringing together of comparisons:
Board[1][1] == Board[1][2] == Board[1][3] == 'O'
All that will happen is Board[1] == Board[1][2] is first evaluated to either true or false and then that boolean value is compared toBoard[1][3]` and so on.
What you want is:
Board[1][1] == 'O' && Board[1][2] == 'O' && Board[1][3] == 'O'
Your if condition is wrong.
You should replace it with the code below:
if ((Board[1][1] == Board[1][2]) &&
(Board[1][2] == Board[1][3]) &&
(Board[1][3] == 'O'))
When you are checking for horizontal winning condition, all three blocks in the horizontal line must have a value of 0.
You should use
if (Board[1][1] == Board[1][2] &&
Board[1][1] == Board[1][3] &&
Board[1][1] == 'O')
or
if (Board[1][1] == 'O' &&
Board[1][2] == 'O' &&
Board[1][3] == 'O')
In its current form your statement, for example, compares Board[1][2] to the result of Board[1][3]=='O' comparsion, not to Board[1][3].
You should run this in a debugger such as gdb. Google "gdb cheatsheet" to get started. You will see exactly what lines of code are executing and in particular can verify the "if" is being evaluated.