Number of vowels including "Y" - c++

I have to write a function that prints out all vowels in a given string line including Y, unless Y is followed by another vowel.
For example:
"test phrase" returns 3
"yes no why not?" returns 4
I've tried using getline(), but I'm not sure if there's a way to use it without requiring some type of input from the user. I need it to use an already declared string.
Here's my code that somewhat works, but takes an input.
#include <iostream>
#include <string>
using namespace std;
int numVowelsIncludingY(string line){
int v = 0;
getline(cin, line);
for(int i = 0; i < line.length(); ++i){
if(line[i] == 'A' || line[i] == 'E' || line[i] == 'I' || line[i] == 'O' || line[i] == 'U' || line[i] == 'Y' ||
line[i] == 'a' || line[i] == 'e' || line[i] == 'i' || line[i] == 'o' || line[i] == 'u' || line[i] == 'y'){
++v;
}
}
return v;
}
UPDATE
I've removed getline and reading the string works fine, but I'm still confused on how to count Y as a vowel only if it's not followed by another vowel.
#include <iostream>
#include <string>
using namespace std;
int numVowelsIncludingY(string line){
int v = 0;
for(int i = 0; i < line.length(); ++i){
if(line[i] == 'A' || line[i] == 'E' || line[i] == 'I' || line[i] == 'O' || line[i] == 'U' || line[i] == 'Y' ||
line[i] == 'a' || line[i] == 'e' || line[i] == 'i' || line[i] == 'o' || line[i] == 'u' || line[i] == 'y'){
++v;
}
}
return v;
}

I deleted my last answer as I didn't understand your question correctly. But now here's the code that should work as intended. And yeah you should not use using namespace std, it is considered a bad practice.
Look here: Why is "using namespace std;" considered bad practice?
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
int numVowelsIncludingY(std::string line) {
int v = 0;
std::vector<char> vovels{'a', 'e', 'i', 'o', 'u', 'y'};
for (size_t i = 0; i < line.length(); ++i) {
char ch = tolower(line[i]);
if (ch == 'y' && find(vovels.begin(), vovels.end(), tolower(line[i + 1])) !=
vovels.end()) {
} else if (find(vovels.begin(), vovels.end(), ch) != vovels.end()) {
++v;
}
}
return v;
}
int main(void) {
std::cout << numVowelsIncludingY("yy");
return 0;
}

You do not need to use getline inside the function when you pass the string as parameter. Though you can read the string outside of the function from some stream. For example to test with different input you could write:
void test(std::istream& input_stream) {
std::string line;
std::getline(input_stream,line);
std::cout << line << ": " << numVowelsIncludingY(line) << "\n";
}
int main(){
std::stringstream test1{"test phrase"};
test(test1);
std::stringstream test2{"yes no why not?"};
test(test2);
std::stringstream test3{"ya"};
test(test3);
std::stringstream test4("aa");
test(test4);
}
And expect output:
test phrase: 3
yes no why not?: 4
ya: 1
aa: 2
test can as well be called with std::cin to read input from the user.
For your special condition of Y not followed by a vowel you need to be careful at the boundaries to avoid out-of-bounds access. I suggest to spend a line of code extra for the last character then we can assert for the main part that every character has a next character.
Because we need to check a character for being a vowel at least twice, I decided to use a lambda expression, and while I was at it, I also wrote one to check for Y or y.
There are many ways to check if a character is a vowel. I consider it simple to search for the character in the string "AEIOUaeio". std::string::find returns std::string::npos when the character cannot be found, otherwise we know its a vowel.
#include <iostream>
#include <string>
#include <sstream>
int numVowelsIncludingY(const std::string& line){
if (line.size() == 0) return 0;
auto is_vowel = [](char c){
std::string vowels{"AEIOUaeiou"};
return vowels.find(c) != std::string::npos;
};
auto is_y = [](char c){ return c == 'Y' or c == 'y'; };
size_t counter = 0;
for (size_t i = 0; i < line.size() -1; ++i){
auto& c = line[i];
auto& next = line[i+1];
if (is_vowel(c) or ( is_y(c) and !is_vowel(next) )) ++counter;
}
if (is_vowel(line.back()) or is_y(line.back())) ++counter;
return counter;
}
Live Demo
^^ Try to experiment by calling test(std::cin) and type some input in godbolts stdin field.

Here's a program that satisfies your test cases, and a couple others. I have two functions to this job. The first checks for a 'traditional' vowel. It was easier to do this than to try to add the conditions for 'Y' at this point.
Then, in count_vowels(), I check if I should count a 'Y' or not. There are two cases needed because the first case does not want to go out of bounds of the std::string. It can handle 'Y' anywhere in the word except the last position. The second case checks if 'Y' is the last letter, and counts it.
#include <cctype>
#include <iostream>
#include <string>
// Simple vowel check; the condition on 'Y' comes in count_vowels()
bool is_capital_vowel(char c) {
return c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U';
}
int count_vowels(std::string str) {
int count = 0;
for (auto& c : str) {
c = std::toupper(c);
}
for (std::size_t i = 0; i < str.length(); ++i) {
if (str[i] == 'Y' && (i + 1) < str.length() &&
!is_capital_vowel(str[i + 1])) {
++count;
} else if (str[i] == 'Y' && (i + 1) == str.length()) {
// The last character being 'Y' required some special consideration
++count;
} else if (is_capital_vowel(str[i])) {
++count;
}
}
return count;
}
int main() {
std::string wordOne = "backyard"; // Should count 2
std::string wordTwo = "cardigan"; // Should count 3
std::string wordThr = "telephoney"; // Should count 5
std::string testOne = "test phrase"; // Should return 3
std::string testTwo = "yes no why not?"; // Should return 4
std::cout << wordOne << ": " << count_vowels(wordOne) << " vowels.\n";
std::cout << wordTwo << ": " << count_vowels(wordTwo) << " vowels.\n";
std::cout << wordThr << ": " << count_vowels(wordThr) << " vowels.\n";
std::cout << testOne << ": " << count_vowels(testOne) << " vowels.\n";
std::cout << testTwo << ": " << count_vowels(testTwo) << " vowels.\n";
}

Related

How to fix not printing any character and just count vowels and characters and read every character in a file

I just want to read every character in a file where I put characters from A TO Z but the program prints A every time and count vowels 4 and character 25 but expectation was to printing vowels 5 and characters 26 how to fix this program fixing from last 4 hours but nothing progress?
Code:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {
int i, count = 0, vowel_count = 0;
string file_name;
cout << "enter file name:";
cin >> file_name;
ifstream fin;
fin.open(file_name);
char ch;
while (!fin.eof()) {
fin.get(ch);
cout << ch;
while (fin >> ch) {
i = ch;
if ((i > 63 && i < 91) || (i > 96 && i < 123))
count++;
if (i == 'a' || ch == 'A' || ch == 'e' || ch == 'E' || ch == 'i' || ch == 'I' || ch == 'o' || ch == 'O' || ch == 'u' || ch == 'U')
vowel_count++;
}
cout << "\n No. of Characters in a File : " << count;
cout << "\n No. of vowel characters in the File : " << vowel_count;
}
fin.close();
return 0;
}
You have some really minor erros in the code, which I fixed for you.
Additionally, I added a check, if the file could be opened or not. That is the problem in most cases.
Please see below:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {
int count = 0, vowel_count = 0;
string file_name;
cout << "\nEnter file name: ";
cin >> file_name;
ifstream fin(file_name);
if (fin) {
char ch;
while (fin.get(ch)) {
cout << ch;
if ((ch >= 'A' && ch <= 'Z') || (ch > 'a' && ch <= 'z'))
count++;
if (ch == 'a' || ch == 'A' || ch == 'e' || ch == 'E' || ch == 'i' || ch == 'I' || ch == 'o' || ch == 'O' || ch == 'u' || ch == 'U')
vowel_count++;
}
fin.close();
cout << "\n No. of Characters in a File : " << count;
cout << "\n No. of vowel characters in the File : " << vowel_count;
}
else std::cerr << "\n\n*** Error. Could notopen '" << file_name << "'\n\n";
return 0;
}

Stack around the variable "name" was corrupted C++

I'm trying to use CStrings to do miscellaneous tasks in C++, such as remove all the vowels from the name provided. However, I can't seem to figure out why I'm getting this error:
Stack around the variable "name" was corrupted.
Why is this happening?
Here is the code:
#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
using namespace std;
void cStringDemo();
void stringDemo();
void removeCVowels(char myGuess[50]);
int main() {
cStringDemo();
cin.get();
cin.ignore();
}
void cStringDemo() {
char name[] = "Seth Smith";
char guess[50];
cout << "Guess my name! [First and Last, EX: Bobby Hall.]" << endl;
cin.get(guess, 20);
if (strcmp(name, guess) == 0) {
cout << "Correct!" << endl;
}
else {
cout << "Incorrect!" << endl;
}
cout << "You guessed " << guess << "." << endl;
removeCVowels(guess);
}
void removeCVowels(char myGuess[50]) {
char nameNoVowel[50];
strcpy_s(myGuess, 100, nameNoVowel);
for (int x = 0; x < 50; x++) {
if (nameNoVowel[x] == 'a' || nameNoVowel[x] == 'e' || nameNoVowel[x] == 'i' || nameNoVowel[x] == 'o' || nameNoVowel[x] == 'u' || nameNoVowel[x] == 'A' || nameNoVowel[x] == 'E' ||
nameNoVowel[x] == 'I' || nameNoVowel[x] == 'O' || nameNoVowel[x] == 'U')
{
nameNoVowel[x] = ' ';
}
}
}
This is undefined behavior:
void removeCVowels(char myGuess[50]) {
char nameNoVowel[50];
strcpy_s(myGuess, 100, nameNoVowel);
You are copying from uninitialized nameNoVowel to myGuess. You should swap the arguments of strcpy_s. Also, even if you swap the two arguments of strcpy_s, the limit of 100 is also too big, since nameNoVowel is only 50 chars. Try:
void removeCVowels(char myGuess[50]) {
char nameNoVowel[50];
strcpy_s(nameNoVowel, sizeof(nameNoVowel)-1, myGuess);
There are a few problems in the code that you posted. Below is code fixed with explanation in comments of what was wrong:
void cStringDemo() {
char name[] = "Seth Smith";
char guess[50] = {0}; //in here initialize the table with zeros
cout << "Guess my name! [First and Last, EX: Bobby Hall.]" << endl;
cin.get(guess, 20); // I am not sure why you want 20 characters and have array of size 50
if (strcmp(name, guess) == 0) {
cout << "Correct!" << endl;
}
else {
cout << "Incorrect!" << endl;
}
cout << "You guessed " << guess << "." << endl;
removeCVowels(guess);
}
void removeCVowels(char myGuess[50]) {
char nameNoVowel[50] = {0}; //it is always good to initialize variables
strcpy_s(myGuess, 50, nameNoVowel); //here lies the problem you tried to copy 100
// characters from array size of 50 this leads
//to undefined behaviour of your program and stack corruption
for (int x = 0; x < 50; x++) {
if (nameNoVowel[x] == 'a' || nameNoVowel[x] == 'e' || nameNoVowel[x] == 'i' || nameNoVowel[x] == 'o' || nameNoVowel[x] == 'u' || nameNoVowel[x] == 'A' || nameNoVowel[x] == 'E' ||
nameNoVowel[x] == 'I' || nameNoVowel[x] == 'O' || nameNoVowel[x] == 'U')
{
nameNoVowel[x] = ' ';
}
}
}

I want to replace all the vowels with z in string

This code is replacing all the characters. Not just vowels. What am I doing wrong?
using namespace std;
bool isVowel(char);
int main() {
string fName = "";
string lName = "";
cout << "Enter first name: " << endl;
cin >> fName;
cout << "Enter last name: " << endl;
cin >> lName;
string name = fName + " " + lName;
cout << name << endl;
for(int i = 0; i < name.length(); i++) {
if(isVowel(name.at(i))) {
name[i] = 'z';
}
}
cout << name << endl;
}
bool isVowel(char c) {
if(c == 'a' || 'e' || 'i' || 'o' || 'u' || 'A' || 'O' || 'E' || 'I' || 'U') {
return true;
}
else {
return false;
}
}
I did some research online and I think my problem lies in that I am passing the character as a reference? I didn't understand how that could be...
The isVowel() function checks if the char is a vowel I think that's where the problem lies, since the program is replacing all the characters I'm assuming that function is not working.
you need to put your if statement as (c == 'a' || c == 'e' || c == 'i'..., the way it is written currently it casts all of the characters on their own as boolean expressions.

Piglatin output won't work correctly still

#include <iostream>
using namespace std;
char firstLetter;
int pigLatin();
string word;
int wordFinder();
int firstVowel;
int x;
char vowel = ('a' && 'e' && 'i' && 'o' && 'u' && 'y' && 'A' && 'E' && 'I' && 'O' && 'U' && 'Y');
string engSentence;
char* letter = &engSentence[0];
bool vowelChecker (char c) // will check to see if there is a vowel
{
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'Y')
{
return true;
}
else
{
return false;
}
}
int pigLatin()
{
int lastLetter = word.length();
firstLetter = word[0];
if (vowelChecker(firstLetter)) //if the first letter of a word is a vowel...
{
cout << word << "way "; // print the word then way
}
else //if the first letter is not a vowel...
{
for (x = 1; x < lastLetter; x++) //in the loop of starting at the second letter and going to the last letter...
{
if (vowelChecker(x)) // check each letter to see if there is a vowel...
{
int firstVowel = x; //says that the first vowel is at point x
break;
}
}
string firstPortion = word.substr(0, firstVowel);
string secondPortion = word.substr(firstVowel, lastLetter);
cout << secondPortion << firstPortion << "ay";
//above is stating that it will first print the part of the word from the first vowel to the last letter,
//then it will print from the first letter to the first vowel and add 'ay' to the end
}
return 0;
}
int wordFinder() //will find words within a string
{
char* letter = &engSentence[0];
while ( *letter != '\0') //while the string isn't done...
{
if ( *letter == ' ' || *letter == '.' || *letter == ',' || *letter == '-' || *letter == '!' || *letter == '?') //if there is a space, comma or period...
{
pigLatin(); //run piglatin func
cout << " "; // add a space before the next word
word = ""; //sets the word back to empty
}
else
{
word += *letter; //adds letters to the word if no space comma or period is found.
}
letter++;
}
return 0;
}
int main()
{
cout << "Please enter a sentence for me to translate: " << endl;
cout << "**REMEMBER TO END SENTENCES WITH A PERIOD OR QUESTION MARK OR EXPLANATION MARK!**" << endl;
getline(cin, engSentence); //will get the whole line entered
wordFinder(); //runs wordfinder function
}
So far, it will only work for if the vowel is the first letter. ( if (vowelChecker(firstLetter)) { cout << word << "way ";} ) this portion of the text... The other part seems to not being ran through in the Piglatin Function. Also I'm Getting a warning that says that firstVowel isn't being used, which would explain why my program isn't running correctly. Not sure why though...
if (vowelChecker(x)) // check each letter to see if there is a vowel...
this is passing the loop variable x, not the character at that position. What you want is:
if (vowelChecker(word[x])) // check each letter to see if there is a vowel...

Need to read white space and other chars C++

I have been working on this all day with no luck. Its night now and don't know what to do. My assignment is to read number of vowels, number of white spaces, and number of other characters in a user inputted sentence. I know i need to use cin.get(ch) for whitespaces, but don't know how. I also need to output the sentence to a file. Heres what I have so far:
//Get data from user
cout << "Enter your sentence on one line followed by a # to end it: " << endl;
while (cin >> noskipws >> character && character != '#')
{
character = static_cast<char>(toupper(character));
if (character == 'A' || character == 'E' || character == 'I' ||
character == 'O' || character == 'U')
{
vowelCount++;
isVowel = true;
}
if (isspace(character))
{
whiteSpace++;
}
else if (isVowel == true && isspace(character))
{
otherChars++;
}
outFile << character;
}
outFile << "vowelCount: " << vowelCount << endl;
outFile << "whiteSpace: " << whiteSpace << endl;
outFile << "otherchars: " << otherChars << endl;
This line
if (character == 'A' || 'E' || 'I' || 'O' || 'U');
Is not doing what you think. It will always return true.
you need
if (character == 'A' || character == 'E' || character == 'I' || character == 'O' || character =='U')
and remove the semicolon as well at the end of that line
Here:
while (cin >> character && character != '#')
You are skipping all white space. To prevent the operator >> from skiiping white space you need to explicitly specify this with the noskipws modifier.
while(std::cin >> std::noskipws >> character && character != '#')
Alternatively the same affect can be achieved with get
while(std::cin.get(character) && character != '#')
Next you are reading more characters outside the loop condition.
cin.get(character);
You already have a value in the variable 'character'. So remove both of these. The next iteration of the loop (in the while condition) will get the next character (as it is executed before the loop is entered).
Then fix you test as Tim pointed out.
You can then add another test for white space with:
if (std::isspace(character)) // Note #include <cctype>
{ /* STUFF */ }
#include <iostream>
using namespace std;
int main()
{
char ch;
int vowel_count = 0;
int space_count = 0;
int other_count = 0;
cout << "Enter a string ends with #: " << endl;
while(1)
{
cin.get(ch);
if(ch == '#')
{
break;
}
if(ch == 'A' || ch == 'a'
|| ch == 'E' || ch == 'e'
|| ch == 'I' || ch == 'i'
|| ch == 'O' || ch == 'o'
|| ch == 'U' || ch == 'u')
{
++vowel_count;
}
else if(ch == ' ')
{
++space_count;
}
else
{
++other_count;
}
}
cout << "Vowels: " << vowel_count << endl;
cout << "White spaces: " << space_count << endl;
cout << "Other: " << other_count << endl;
return 0;
}
No arrays
You can check for whitespace the exact same way. Common whitespace characters are space (' '), and horizontal tab ('\t'). Less-common are newline ('\n'), carriage return ('\r'), form feed ('\f') and vertical tab ('\v').
You can also use isspace from ctype.h.