I'm not getting errors, but the output is incorrect. I'm not sure what I'm doing wrong. I can only use functions from string library.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main() {
string message, pig_message;
getline(cin, message);
unsigned int x = message.find_first_of("aeiou");
if (message[x] == 'a' || 'e' || 'i' || 'o' || 'u' ) {
pig_message = message + "yay";
cout << pig_message;
}
else if (!(message[x] == 'a' || 'e' || 'i' || 'o' || 'u' )) {
pig_message = message.substr(1) + message[0] + "ay";
cout << pig_message;
}
system("pause");
return 0;
}
The first if statement is always true. You should change it to
if (message[x] == 'a' || message[x] == 'e' || message[x] == 'i' || message[x] == 'o' || message[x] == 'u' ) {
Also, you could change the else if (...) { line to just
else {
if you want it to be executed every time the first if statement is not true.
Your comparison statement is incorrect.
Make sure your function is actually iterating through the letters, and that you're concatenating the strings correctly.
So:
unsigned int x = message.find_first_of("aeiou"); // Returns the first match
if(message[x] == 'a' || message[x] == 'e'...) // Currently your code reads as only checking for a.
Think of it as IF message[x] = a, IF e, IF i
vs
if message[x] = a, IF message[x] = i
What does your code do after it finds a match?
pig_message = message + 'yay' would add "yay" to the whole message string.
It would then print it out and move on, without doing anything to the other vowels.
I'm new to C++ myself but that's how I've understood your code.
It might be better to go through the whole input string one letter at a time in a for loop with your if else statements to add the strings inside the loop.
Related
I want to iterate char by char in a vector of strings. In my code I created a nested loop to iterate over the string, but somehow I get an out of range vector.
void splitVowFromCons(std::vector<std::string>& userData, std::vector<std::string>& allCons, std::vector<std::string>& allVows){
for ( int q = 0; q < userData.size(); q++){
std::string userDataCheck = userData.at(q);
for ( int r = 0; r < userDataCheck.size(); r++){
if ((userDataCheck.at(r) == 'a') || (userDataCheck.at(r) == 'A') || (userDataCheck.at(r) == 'e') || (userDataCheck.at(r) == 'E') || (userDataCheck.at(r) == 'i') || (userDataCheck.at(r) == 'I') || (userDataCheck.at(r) == 'o') || (userDataCheck.at(r) == 'O') || (userDataCheck.at(r) == 'u') || (userDataCheck.at(r) == 'U')){
allVows.push_back(userData.at(r));
}
else if ((userDataCheck.at(r) >= 'A' && userDataCheck.at(r) <= 'Z') || (userDataCheck.at(r) >= 'a' && userDataCheck.at(r) <= 'z')){
allCons.push_back(userData.at(r));
}
else {
continue;;
}
}
}
}
The error here is in these lines:
allVows.push_back(userData.at(r));
allCons.push_back(userData.at(r));
the r variable is your index into the current string, but here you're using it to index into the vector, which looks like a typo to me. You can make this less error prone using range-for loops:
for (const std::string& str : userData) {
for (char c : str) {
if (c == 'a' || c == 'A' || ...) {
allVows.push_back(c);
}
else if (...) {
....
}
}
}
which I hope you'll agree also has the benefit of being more readable due to less noise. You can further simplify your checks with a few standard library functions:
for (const std::string& str : userData) {
for (char c : str) {
if (!std::isalpha(c)) continue; // skip non-alphabetical
char cap = std::toupper(c); // capitalise the char
if (cap == 'A' || cap == 'E' || cap == 'I' || cap == 'O' || cap == 'U') {
allVows.push_back(c);
}
else {
allCons.push_back(c);
}
}
}
Since this question is about debugging actually, I think it is a nice illustration of how the usage of std::algorithms of C++ can decrease the effort needed to see what is wrong with a non working code.
Here is how it can be restructured:
bool isVowel(char letter)
{
return letter == 'A' || letter == 'a' ||
letter == 'E' || letter == 'e'||
letter == 'O' || letter == 'o'||
letter == 'Y' || letter == 'y'||
letter == 'U' || letter == 'u';
}
bool isConsonant(char letter)
{
return std::isalpha(letter) && !isVowel(letter);
}
void categorizeLetters(const std::vector<std::string> &words, std::vector<char> &vowels, std::vector<char> &consonants)
{
for( const std::string &word : words){
std::copy_if(word.begin(), word.end(), std::back_inserter(vowels), isVowel);
std::copy_if(word.begin(), word.end(), std::back_inserter(consonants), isConsonant);
}
}
With a solution like this, you avoid the error-prone access-with-index that lead to your problem. Also, code is readable and comprehensive
To check at an index whether it's a consonant or a vowel , and having a bit of a problem with the writing of the logic in syntactical form?
Tried running it but the count variable wasn't incrementing.
if (s[i]!= ('a' || 'e' || 'i' || 'o' || 'u') && s[i+1] == ('a' || 'e' || 'i' || 'o' || 'u'))
It keeps giving 0 , i.e , the initialised value as the output.
Write a function. For example:
bool isvowel( char c ) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
Then you can simply say:
if ( !isvowel( s[i] ) && isvowel( s[i+1] ) ) {
// do something
}
Write a separate function that checks whether a given character is a vowel. For example
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
bool is_vowel( char c )
{
const char *vowels = "aeiou";
return c != '\0' && std::strchr( vowels, std::tolower( ( unsigned char )c ) );
}
int main( void )
{
std::string s( "Hi" );
if ( not is_vowel( s[0] ) && is_vowel( s[1] ) ) std::cout << s << '\n';
}
The program output is
Hi
I'm writing a programm which gives out the input string without its vowels.but it only gives the first charachter of the string .here is the code:
#include<iostream>
using namespace std;
int main(){
char ch;
while(cin.get(ch)){
cout<<ch;
char a=cin.peek();
while( a==65 || a==69 || a==73 || a==79 || a==85 || a==97 || a==101 || a==105 || a==111 || a==117)
cin.ignore(1 , a);
}
return 0;
}
To solve a problem like this, start by breaking the problem into smaller parts. A possible decomposition is:
Are there characters still to read from the input? No: Great, we are done!
Read in a character
Is the character a vowel? Yes: Goto 1.
Output the character
Goto 1.
Then in code, you can translate this into:
// 1) Are there characters still to read?
while (std::cin.good())
{
// 2) Read in a character
char ch;
std::cin.get(ch);
// 3) Is the character a vowel?
// For the test for a vowel, you can use something similar to
// what you have at the moment, or better still: consider
// writing a function like isVowel in #Shreevardhan answer.
if ( /* TODO: Test if the character is a vowel... */)
{
// Skip the rest of the loop and go back to 1
continue;
}
// 4) Output the good character
std::cout << ch;
// 5) Reached the end of the loop, so goto 1
}
It's a good habit to break your problem down into smaller parts. I often start a new project by first writing out a list/comments (or even drawing a flow diagram) to break up the problem into more manageable pieces.
Other answers show how to solve this problem in a more intuitive manner.
Anyway, when looking at your code consider the following:
while( a==65 || a==69 || a==73 || a==79 || a==85 || a==97 || a==101 || a==105 || a==111 || a==117)
cin.ignore(1 , a);
As you do a while loop with conditions around the value of a, and as cin.ignore(1 , a) does not change the value of a, you wont ever leave this loop unless an exception is thrown, right?
Maybe you can try to use the boost library.
#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");
Something like this
#include <iostream>
using namespace std;
bool isVowel(char c) {
c = tolower(c);
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
int main() {
char c;
while (cin.get(c))
if (!isVowel(c))
cout << c;
return 0;
}
Add your storing logic inside.
A more C++-ish code
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
string s;
getline(cin, s);
s.erase(remove_if(s.begin(), s.end(), [](char c) {
c = tolower(c);
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}), s.end());
cout << s;
return 0;
}
See a demo.
I wrote a program that reads input a word at a time until a lone 'q' entered.The
program then report the number of words that began with vowels,the number that began with consonants,and the number that fit neither of those categories.
#include <iostream>
#include <cstdlib>
int main()
{
char ch;
bool cont = true; //for controlling the loop
bool space = false; //see if there is a space in the input
int i = 0; //checking if the input is the first word
int consta, vowel, others;
consta = vowel = others = 0;
std::cout<<"Enter words (q to quit)\n";
while (cont && std::cin>>ch) //continue while cont is true and the input succeded
{
if (i == 0) //check if this is the first word
{
if (isalpha(ch))
if ((ch == 'a' ||ch == 'e' ||ch== 'i' ||ch== 'o' ||ch== 'u') || (ch == 'A' ||ch== 'E' ||ch== 'I' ||ch== 'O' ||ch== 'U'))
++vowel;
else
++consta;
else
++others;
++i; //add 1 to i so this if statement wont run again
}
if (space == true) //check if the last input was a space
{
if (!isspace(ch)) //check if the current input is not a space
{
if (ch != 'q') //and ch is not 'q'
{
if (isalpha(ch))
if ((ch == 'a' ||ch == 'e' ||ch== 'i' ||ch== 'o' ||ch== 'u') || (ch == 'A' ||ch== 'E' ||ch== 'I' ||ch== 'O' ||ch== 'U'))
++vowel;
else
++consta;
else
++others;
space = false;
}
}
else
cont = false;
}
if (isspace(ch)) //check if ch is a space
space = true;
}
std::cout<<"\n"<<consta<<" words beginnig with constants\n";
std::cout<<vowel<<" words beginnig with vowels\n";
std::cout<<others<<" words beginning with others\n";
system("pause");
return 0;
}
But it doesn't terminate when i input a space and a 'q'.
But if i in put '^Z' it does terminate but constantans are always 1 and the others are always 0.
The problem is that std::cin by default ignores all tabs and white spaces. So in your code
if (isspace(ch)) //check if ch is a space
space = true;
never sets space to true. One way to avoid this problem is to use std::cin.get(ch) instead of std::cin>>ch
Assuming that you want to use the same code structure, In the while loop use
while (cont && std::cin>> std::noskipws >>ch)
std::noskipws : This changes the behavior of the cin stream to not ignore spaces. It also adds a space at the end of the stream too. Beware of the end space. Fortunately your code handles spaces so you wont see its affect.
As you are handling spaces in the code this will work. Also, by default the behavior of cin is to ignore spaces.
However I think you can reduce the complexity of the code and you may not need this statement
Hope this helps you
#include<iostream>
#include<cstdlib>
#include<string>
int main()
{
char ch[50];
int consta, vowel, others;
consta = vowel = others = 0;
bool flag = false;
std::cout<<"Enter words (q to quit)\n";
while(1)
{
if(flag == true)
{
break;
}
gets(ch);
char* pch;
pch = strtok(ch," ");
if(strcmp("q",pch)==0)
{
break;
}
while (pch != NULL)
{
if(strcmp("q",pch)==0)
{
flag = true;
break;
}
if(isalpha(pch[0]))
{
if ((pch[0] == 'a' ||pch[0] == 'e' ||pch[0]== 'i' ||pch[0]== 'o' ||pch[0]== 'u') || (pch[0] == 'A' ||pch[0]== 'E' ||pch[0]== 'I' ||pch[0]== 'O' ||pch[0]== 'U'))
++vowel;
else
++consta;
}
else
++others;
pch = strtok (NULL, " ");
}
}
std::cout<<"\n"<<consta<<" words beginnig with constants\n";
std::cout<<vowel<<" words beginnig with vowels\n";
std::cout<<others<<" words beginning with others\n";
std::cin.ignore();
return 0;
}
Please refer this for strtok. This counts all the words whether separated by spaces or in separate lines.
I search the most concise and efficient way to find the first printf format sequence (conversion specification) in a C++ string (I cannot use std::regex as they are not yet implement in most in compilers).
So the problem is to write an optimized function that will return the beginning of the first printf-format sequence pos and its length n from an input string str:
inline void detect(const std::string& str, int& pos, int& n);
For example, for:
%d -> pos = 0 and n = 2
the answer is: %05d -> pos = 15 and n = 4
the answer is: %% %4.2f haha -> pos = 18 and n = 5
How to do that (clever and tricky ways are welcome)?
Scan forward for %, then parse the content from there. There are some quirky ones, but not THAT bad (not sure you want to make it an inline tho').
General principle (I'm just typing as I go along, so probably not the BEST form of code ever written - and I haven't tried to compile it at all).
inline void detect(const std::string& str, int& pos, int& n)
{
std::string::size_type last_pos = 0;
for(;;)
{
last_pos = str.find('%', last_pos)
if (last_pos == std::string::npos)
break; // Not found anythin.
if (last_pos == str.length()-1)
break; // Found stray '%' at the end of the string.
char ch = str[last_pos+1];
if (ch == '%') // double percent -> escaped %. Go on for next.
{
last_pos += 2;
continue;
}
pos = last_pos;
do
{
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'')
{
last_pos++;
ch = str[last_pos+1];
}
else
{
// The below string may need appending to depending on version
// of printf.
if (string("AacdeEfFgGiopusxX").find(ch) != std::string::npos)
{
// Do something about invalid string?
}
n = last_pos - pos;
return;
}
} while (last_pos < str.length());
}
}
edit2: This bit is probably better written as:
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'') ...
if (string("0123456789.-*+lLzhtj #'").find(ch) != std::string::npos) ...
Now, that's your homework done. please report back with what grade you get.
Edit: It should be noted that some things that a regular printf will "reject" is accepted by the above code, e.g. "%.......5......6f", "%5.8d", "%-5-6d" or "%-----09---5555555555555555llllld". If you want the code to reject these sort of things, it's not a huge amount of extra work, just need a little bit of logic to check "have we seen this character before" in the "check for special characters or digit", and in most cases the special character should only be allowed once. And as the comment says, I may have missed a couple of valid format specifiers. It gets further trickier if you also need to cope with "this 'l' is not allowed with 'c'" or such rules. But if the input isn't "malicious" (e.g. you want to annotate where on which line there are format specifiers in a working C source file), the above should work reasonably well.