Converting to lowercase at end of statement? - c++

Slight issue. (Not using toupper() and tolower() functions) I understand what converting to uppercase and lowercase using numerical values is but following my C++ book, why is the conversion at the end of this statement and not before?:
if (letter >= 'A') //test for 'A' or larger
if (letter <= 'Z') //test for 'Z' or smaller
{
cout << endl
<< "You entered a capital letter."
<< endl;
letter += 'a' - 'A'; //Convert to lowercase
return 0;
}
if (letter >= 'a') //test for 'a' or larger
{
if (letter <= 'z') //test for 'z' or smaller
{
cout << endl
<< "You entered a small letter."
<< endl;
return 0;
}
}
Why would it convert the uppercase to lowercase at this point of code execution since the second if statement deals with lowercase input?

The given snippet could be the body of the function:
int convert(char& letter)
{
if (letter >= 'A' && letter <= 'Z')
{
letter += 'a' - 'A';
return 0; // go out of this function...
}
else if (letter >= 'a' && letter <= 'z')
{
letter += 'A' - 'a';
return 0; // go out of this function...
}
return -1; // it wasn't a letter as we expected
}
Note, that there's a possible path that doesn't match none of these 2 situation. Let's say that letter is '?', since you're returning int value, there should be an indication that something is wrong (it's up to you how you deal with error handling).
Possible usage of your this function could look like this:
char letter = '!';
if (convert(letter) == 0)
// success ...
else
// error ...
If the question is really about leaving the scope of function, then this question could be helpful too:
How to break out of a function
Concrete example:
void convertLetterAndPrintResult(char& letter)
{
if (convert(letter) == 0)
std::cout << letter << std::endl;
else
std::cout << "ERROR: '" << letter << "' is not valid character!" << std::endl;
}
int main()
{
char letter = '!';
convertLetterAndPrintResult(letter);
letter = 'g';
convertLetterAndPrintResult(letter);
letter = 'L';
convertLetterAndPrintResult(letter);
}
Output:
ERROR: '!' is not valid character!
G
l

Because there's a return 0; statement in the first part. If the original character was uppercase, the control flow doesn't even reach the second nested if () { if () { } } part.

Why would it convert the uppercase to lowercase at this point of code
execution since the second if statement deals with lowercase input?
That is because
return 0
means that the function is finished. The lines
if (letter >= 'a') //test for 'a' or larger
{
if (letter <= 'z') //test for 'z' or smaller
{
cout << endl
<< "You entered a small letter."
<< endl;
return 0;
}
}
will not be executed if letter was originally an upper case letter. It would print out "You entered a capital letter.", then convert it to lower case, then exit.
why is the conversion at the end of this statement and not before?
It would make no difference if the conversion were before the cout statement.

Related

Counting syllables in a word C++

I have created a program to count the syllables in a word inputted by the user. The user is to enter any amount of words followed by the enter key until the (#) key is entered, then the program is to display the words in a table followed by the syllable count for each word.
I am having issues with the "silent e" portion of my program.
if (word_length - 1 == 'e')
{
vowels = vowels - 1;
It seems as though it is not able to pick up the last letter in the string of words. I have tried to move some of the if statements around to see if that helps and to better identify where the problem lies, and from what I have noticed, as stated earlier i believe it to be with the silent e portion of the code.
It is difficult to find even the smallest errors in my code, so I am asking for another set of eyes to gaze over my code.
Any help will be greatly appreciated.
Also, I have yet to complete the formatting of my results table, so please over look that.
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
string word_1 = "create list";
int vowels = 0;
int word_length; // better to set .length() into variable to eliminate warnings
int words_to_print = 0; // this will count how many words to print to use in for loop later
/*
vector <variable type> name_of_vector[size of vector];
creating vectors
leaving them empty for now
*/
vector <string> words_saved;
vector <int> number_of_syllables_saved;
cout << "Enter 4 words from the English dictionary, to determine the amount of syllables each word has." << endl;
cout << "Please enter [#] when finished, to create a list." << endl;
cin >> word_1;
while (word_1 != "#") // as long as user doesnt enter # you can enter a word and
{ // have it run thru the syllable logic
word_length = word_1.length();
words_to_print++;
words_saved.push_back(word_1);
// ^ this saves the word into the next availabe index of vector for strings.
for (int i = 0; i < word_length ; i++) // length is a variable now instead of function syntax this
{ // eliminates the <: signed/usnsigned mismatch warning below
if ((word_1[i] == 'a') || (word_1[i] == 'e') || (word_1[i] == 'i') || (word_1[i] == 'o') || (word_1[i] == 'u') || (word_1[i] == 'y'))
{
vowels = vowels + 1;
if ((word_1[i + 1] == 'a') || (word_1[i + 1] == 'e') || (word_1[i + 1] == 'i') || (word_1[i + 1] == 'o') || (word_1[i + 1] == 'u') || (word_1[i + 1] == 'y'))
{
vowels = vowels - 1;
if (word_length - 1 == 'e')
{
vowels = vowels - 1;
if (vowels == 0)
{
vowels = vowels + 1;
}
}
}
}
}
number_of_syllables_saved.push_back(vowels);
//^ this puts number of syllables into vector of ints
vowels = 0; // this resets the amounts so it can count vowels of next word and not stack from previous word
cin >> word_1; // this will reset the word and controls loop to print out chart if # is entered
}
// use a for loop to print out all the words
cout << endl << endl << endl;
cout << "Word: " << setw(30) << "Syllables: " << endl;
for (int x = 0; x < words_to_print; x++)
{
cout << words_saved[x] << setw(20) << number_of_syllables_saved[x] << endl;
}
//system("pause");
return 0;
}
You are comparing the character 'e' to the integer word_length - 1 instead of comparing it to the last character of your string as you intended.
You should replace if (word_length - 1 == 'e') with if (word_1[word_length - 1] == 'e').
Your nested if-statements don't get evaluated at the anticipated index.
Say the input is "state".
At i = 0, word_1[i] = 's', doesn't pass the first if statement.
At i = 1, word_1[i] = 't', doesn't pass the first if statement.
At i = 2, word_1[i] = 'a', vowels becomes 1. The program does not proceed further down the nested if statements since word_1[i+1] is 't'.
At i = 3, word_1[i] = 't', doesn't pass the first if statement.
At i = 4, word_1[i] = 'e', vowels becomes 2. The program does not proceed further down the nested if statements since word_1[i+1] is garbage value.
As you can see, it never reaches the nested if-statements as you intended

C++ how to cout once instead of multiple times in a for loop

void f3(string x){
for (int i=0; i < x.length(); i++){
if ('A'<=x[i] && 'z'>=x[i]){
cout << "English Alphabet" << endl;
}
else {
cout << "NOT English Alphabet" << endl;
break;
}
}
}
how to get only one result (cout)? like "English Alphabet" instead of 4 times for "abcd".
examples:
gimme a string:
abcd
English Alphabet
English Alphabet
English
Alphabet
English Alphabet
or
gimme a string:
abc!
English Alphabet
English Alphabet
English
Alphabet
NOT English Alphabet
and if I input space the program does not work.
How could I fix it?
Thanks for the help!
I am not sure if I got what you want, and I do not know C++, but something that may help you is using a boolean to define whether or not the input has non-English characters in it. You would define it as true from the beginning, and as soon as you find a character that isn't an English character, you set it to false. When you step out of the for loop, you use an if to check if your input has only English characters. It would be something like this:
void f3(string x) {
bool isEnglish = true;
for (int i=0; i < x.length(); i++){
if ('A'>x[i] || 'z'<x[i]){
isEnglish = false;
break;
}
}
if (isEnglish) {
cout << "English Alphabet" << endl;
} else {
cout << "NOT English Alphabet" << endl;
}
}
If you input space the program should run OK, but it will always return "not english alphabet" for it. That's because the test you're making takes into consideration if the current character of the input is between characters A and z of the ASCII character space. See the image below:
See how space is character number 32, which is smaller than 'A', and therefore, will not enter your if block, and fall inside the else, thus returning 'NOT English alphabet'. Numbers, the # sign, the & sign and everything before 'A' and everything after 'z' will also fail the test. Also, brackets ('[' and ']') will pass as English alphabet input.
If you want to only include letters, your if should look like:
if (x[i] < 'A' || (x[i] > 'Z' && x[i] < 'a') || x[i] > 'z')
If you want to include spaces, add another &&:
if ((x[i] < 'A' || (x[i] > 'Z' && x[i] < 'a') || x[i] > 'z') && x[i] != ' ')
The same logic can be used to add any characters to your verification.
Good luck!
Since you've tagged this as C++, I'm going to assume you're prefer a solution written in real C++.
First, I'd look up std::isalpha. It's defined specifically to determine whether a character is alphabetic1.
Second, I'd look up std::all_of and std::any_of. They're defined to determine whether any/all of a collection fits a particular requirement.
Putting those together, you could do something like this:
if (!std::all_of(x.begin(), x.end(),
[](unsigned char c) { return std::isalpha(c); })
std::cout << "Not ";
std::cout << "English alphabet\n";
1. Note that the result of isalpha isn't necessarily based on the English alphabet. Rather, it's based on the the current locale, so with (for example) a French locale, it would say that not only was an "a" alphabetic, but also that "â" and "à' were alphabetic as well (which your test would not). Likewise, for a German locale it would say "ß" was alphabetic (and so on). The default locale is named "C"; for things like determining whether something is alphabetic, it follows the English alphabet.
Here two solutions:
With a bool variable:
void f3(string x)
{
bool notEnglish = false;
for (int i=0; i < x.length(); i++)
{
if ( ('A' > x[i] || 'z' < x[i]) && x[i] != ' ' )
{
notEnglish = true;
break;
}
}
if (notEnglish) std::cout << "NOT ENGLISH" << std::endl;
else std::cout << "ENGLISH" << std::endl;
}
Without a bool and with int as return value:
int f3(string x)
{
for (int i=0; i < x.length(); i++)
{
if ( ('A' > x[i] || 'z' < x[i]) && x[i] != ' ' )
{
std::cout << "NOT ENGLISH" << std::endl;
return -1;
}
}
std::cout << "ENGLISH" << std::endl;
return 1;
}
I prefer the second one since you have a feedback (the return value) of what is occured inside the function.
You can declare a local Boolean variable so as soon as non-English detected the loop breaks immediately setting the the variable to false.
The matter is trickier: Checking for non-English characters:
void f3(string x){
bool IsEng = true;
for(int i = 0; i < x.length(); i++){
if ( !( x[i] >= 'A' && x[i] <= 'z') ){
IsEng = false;
break;
}
}
if(IsEng)
cout << "English Alphabet" << endl;
else
cout << "Not English Alphabet" << endl;
}
This is very simple and logical way to execute a line of code once:
int x=1
if (x==1)
{
//your cout-code here;
x++;
}
x becomes 2, so next time it won't be executed

Encrypting a text file by incrementing chars

I need to encrypt a simple text file by incrementing each character by 1 i.e 'a' becomes 'b', 'b' becomes 'c' etc. with 'z' becoming 'a'.
I have done this as per the code below, and although majority of my output is correct, it seems to have trouble at the end of each file.
For example, when the input file contains 'a b c d' the output generated is 'b c d ef' as opposed to the answer which should be 'b c d e'. I cannot seem to figure this out.
This is my code for the encrypt function:
void encrypt(char* inFileName, char* outFileName) {
out_stream.open(outFileName);
in_stream.open(inFileName);
if(in_stream.fail()) {
cout << "Failed to open input file." << endl;
exit(1);
}
else {
while(!in_stream.eof()) {
in_stream.get(letter);
if (letter == 'z') {
letter = 'a';
}
if (letter == 'Z') {
letter = 'A';
}
if (letter == ' ') {
letter = letter;
}
else {
letter = letter + 1;
}
out_stream << letter;
}
}
}
Shift ciphers can be achieved using this way:
while(!in_stream.eof()) {
if (letter>='a' && letter<='Z')
letter = (letter+1)%'Z' + 'a';
out_stream << letter;
}
Reduce redundancy from your code and make it as compact as possible, there are so many useless conditions in your code.
The main logic lies in ciphering characters from a...Z, you cannot predict other characters in text file such as \n \0 etc, so they shouldn't be dealt with at all.
I can suggest this piece of code
while(!in_stream.eof()) {
if ((letter>='A' && letter<='Y')|| (letter>='a' && letter<='y'))
letter = (letter+1);
else if(letter== 'Z' || letter== 'z')
letter =(letter-25);
out_stream << letter;
}

debugging c++ program with <set> containers

The problem is to find all vowels all even words in a sentence share, in other words these vowels have to be met in any even word in the sentence.
But i when i enter for example: "ewedyua aiuye dswidje ieuayj eeee eeeui dajhdfjcne aodijsbfe".
I get: e i u
but "e i" is expected as the last even word doesn't contain 'u' (I use " " just for separation here in the text and don't use them in the output)
The program:
int main(){
string str;
char ch = ' ';
set<char> strSet;
set<char> resultSet;
set<char> tempSet;
int count = 1;
int i = 0;
cout << "Enter a line: ";
getline(cin, str);
str = delOverSpace(str); // delete excessive gaps<br>
do {
ch = str.at(i);
if(((count % 2) == 0) && (ch != ' ')){ // this is an even word and not a gap
if(isVowel(upperToLower(ch))) // this is a vowel
tempSet.insert(upperToLower(ch));
}
if (ch == ' ') { // if we've passed through the word add inforamtion on it
if(((count % 2) == 0) && (count / 2) == 1)
strSet.insert(tempSet.begin(), tempSet.end());
else if (((count % 2) == 0) && (count / 2) != 1){
set_intersection(
strSet.begin(),strSet.end(), tempSet.begin(), tempSet.end(),
insert_iterator<set<char> >(resultSet, resultSet.begin())
);
strSet.clear();
tempSet.clear();
strSet.insert(resultSet.begin(), resultSet.end());
resultSet.clear();
}
count++;
}
i++;
}while(ch != '.');
if (count == 2) cout << "Only one word was entered" << endl;
else if (strSet.empty()) cout << "No vowels were found" << endl;
else {
copy(strSet.begin(), strSet.end(), ostream_iterator<char>(cout, " "));
cout << endl;
}
return 0;
}
Try not to use one counter variable for multiple purposes.
For example you could use count for the current character count within the current word and words for word count.
In your example, you're making count work too hard.
Decide what you are counting. Do you want to count every character?
Or do you want to count the characters in the current word?
When incrementing a counter, try to put this next to the logic that needs it.
Eg, i++ should go right after you've used it to get the next character.
And count should be incremented in the block that handles letters (ie not space, not dot).
If the counters get too far away from what they are keeping track of, you can introduce bugs.
Move the space check up first and also check for end of sentence with .
Clear indentation helps to follow the code - I use 4 characters, but 2 or 3 is ok.
1 character indents are hard to read.
Use blank lines to separate different chunks of logic.
You might want to add logic to handle punctuation like ,, ?, ! etc.
When you're processing an input string which is separated into words, it's often easier to handle the end of input condition outside the loop.
In this case, the loop exits after it picks up the last letter.
If that is not a . then you'll have an unprocessed word sitting in tempSet.
You can try and anticipate this within the loop, but it seems more natural to exit the loop and check if there is anything left to process.
If you separate your logic into clearly separated blocks, you can set breakpoints inside each block.
You'll then know what situation you're handling. You can break inside end-of-word logic and check tempSet and count.
Are they what you expect?
And in the else part you can check ch going in and verify that it is classified as a vowel properly.
int main() {
string str;
char ch = ' ';
set<char> strSet;
set<char> tempSet;
int count = 0, words = 0, i = 0;
cout << "Enter a line: ";
getline(cin, str);
str = delOverSpace(str); // delete excessive gaps<br>
while ( i < str.size() && ch != '.' ) {
// Get next character
ch = str.at(i);
i++;
if (ch == ' ' || ch == '.' ) { // if we've passed through the word add inforamtion on it
if( count > 0 && ((count % 2) == 0)) {
strSet.insert(tempSet.begin(), tempSet.end());
words++;
}
count = 0; // reset the char counter
tempSet.clear(); // clear the temp vowel set
}
else {
// letter - not a space or a dot, increase the character count
count++;
if(isVowel(upperToLower(ch))) // this is a vowel
tempSet.insert(upperToLower(ch));
}
}
// pick up any unprocessed word if we hit end of input without seeing '.'
if (count > 0 && ((count % 2) == 0)) {
strSet.insert(tempSet.begin(), tempSet.end());
words++;
}
if (words == 0)
cout << "No words entered" << endl;
else if (words == 1)
cout << "Only one word was entered" << endl;
else if (strSet.empty())
cout << "No vowels were found" << endl;
else {
copy(strSet.begin(), strSet.end(), ostream_iterator<char>(cout, " "));
cout << endl;
}
return 0;
}

Code keeps printing "1" when everything is correct

The code runs and all but it doesn't print out the vowels, but instead prints a "1".
#include <iostream>
#include <string>
using namespace std;
int countVowels(string sentence,int numVowels)
{
for(int i =0; i<sentence.length(); i++)
{
if((sentence[i]==('a'))||(sentence[i]==('e'))||(sentence[i]==('i'))||(sentence[i]==('o'))||(sentence[i]==('u'))||(sentence[i]==('A'))||(sentence[i]==('E'))||(sentence[i]==('I'))||(sentence[i]==('O'))||(sentence[i]==('U')))
numVowels=numVowels+1;
}
}
int main()
{
string sentence;
int numVowels = 0;
do{
cout << "Enter a sentence or q to quit: ";
cin >> ws;
getline(cin,sentence);
}
if(sentence == 'q'|| sentence == 'Q');
cout << "There are " << countVowels << " vowels in your sentence." << endl;
return 0;
}
The output should be like this:
Enter a sentence or a to quit: I like apples!
There are 4 vowels in your sentence, and 11 letters.
Enter a sentence or q to quit: q
Bye!
My problem:
Can someone explain to me why it keeps printing a "1", and my "if" statement where I am supposed to assign the hotkey "q" to exit the program isn't working. When I run the program I get an error at the if statement saying "no match for operators=="
I usually don't like just providing a full solution, but since your question shows you have made a good effort, here's how I would write it (well, not quite, I simplified a little to be more beginner friendly):
#include <algorithm>
#include <iostream>
#include <string>
bool isVowel(char c)
{
// A simple function that returns true if the character passed in matches
// any of the list of vowels, and returns false on any other input.
if ( 'a' == c ||
'e' == c ||
'i' == c ||
'o' == c ||
'u' == c ||
'A' == c ||
'E' == c ||
'I' == c ||
'O' == c ||
'U' == c) {
return true; // return true if it's a vowel
}
return false; // remember to return false if it isn't
}
std::size_t countVowels(std::string const& sentence)
{
// Use the standard count_if algorithm to loop over the string and count
// all characters that the predicate returns true for.
// Note that we return the resulting total.
return std::count_if(std::begin(sentence),
std::end (sentence),
isVowel);
}
int main() {
std::string sentence;
std::cout << "Please enter a sentence, or q to quit: ";
std::getline(std::cin, sentence);
if ( "q" == sentence ||
"Q" == sentence) {
// Quit if the user entered a string containing just a single letter q.
// Note we compare against a string literal, not a single character.
return 0;
}
// Call the counting function and print the result.
std::cout << "There are "
<< countVowels(sentence) // Call the function on the input.
<< " vowels in your sentence\n";
return 0;
}
Hopefully the comments make it all clear.
Now you might have been told that you can't use the standard algorithms (std::count_if), since part of the exercise seems to be to write that. Well I'll leave that to you. Your current version is close to correct, but remember to return the result. And you don't really need to pass in the numVowels count, just create that within the function, and remember to return it.