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.
Related
while (temp->left->oper == '+' ||
temp->left->oper == '-' ||
temp->left->oper == '*' ||
temp->left->oper == '/' ||
temp->right->oper == '+' ||
temp->right->oper == '-' ||
temp->right->oper == '*' ||
temp->right->oper == '/')
{
// do something
}
For clarity: temp is a pointer that points to following node structure:
struct node
{
int num;
char oper;
node* left;
node* right;
};
Sure, you could just use a string of valid operators and search it.
#include <cstring>
// : :
const char* ops = "+-*/";
while(strchr(ops, temp->left->oper) || strchr(ops, temp->right->oper))
{
// do something
}
If you are concerned about performance, then maybe table lookups:
#include <climits>
// : :
// Start with a table initialized to all zeroes.
char is_op[1 << CHAR_BIT] = {0};
// Build the table any way you please. This way using a string is handy.
const char* ops = "+-*/";
for (const char* op = ops; *op; op++) is_op[*op] = 1;
// Then tests require no searching
while(is_op[temp->left->oper] || is_op[temp->right->oper])
{
// do something
}
Yes, indeed you can!
Store the valid-characters to a std::array or even a plain array and apply the standard algorithm std::any_of to it for checking the condition.
#include <array> // std::array
#include <algorithm> // std::any_of
static constexpr std::array<char, 4> options{ '+', '-', '*', '/' };
const auto tester = [temp](const char c) { return temp->left->oper == c || temp->right->oper == c; };
const bool isValid = std::any_of(options.cbegin(), options.cend(), tester);
while(isValid) // now the while-loop is simplified to
{
// do something
}
This can be more cleaned by packing into a function, which accepts the node object to be checked.
#include <array> // std::array
#include <algorithm> // std::any_of
bool isValid(const node *const temp) /* noexcept */
{
static constexpr std::array<char, 4> options{ '+', '-', '*', '/' };
const auto tester = [temp](const char c) { return temp->left->oper == c || temp->right->oper == c; };
return std::any_of(options.cbegin(), options.cend(), tester);
}
which can be called in the while-loop
while (isValid(temp)) // pass the `node*` to be checked
{
// do something
}
Create a sub function,
bool is_arithmetic_char(char)
{
// Your implementation or one proposed in another answers.
}
and then:
while (is_arithmetic_char(temp->left->oper)
|| is_arithmetic_char(temp->right->oper))
{
// do something
}
C-style:
int cont = 1;
while(cont)
switch(temp->left->oper) {
case '+':
case '-':
...
case '/':
// Do something
break;
default:
cont = 0;
}
You might need to enclose // Do something with curly braces if you're going to declare variables.
You can construct a string that contains the options and search for the character:
#include <string>
// ...
for (auto ops = "+-*/"s; ops.find(temp-> left->oper) != std::string::npos ||
ops.find(temp->right->oper) != std::string::npos;)
/* ... */;
The "+-*/"s is a C++14 feature. Use std::string ops = "+-*/"; before C++14.
Programming is the process of finding redundancies and eliminating them.
struct node {
int num;
char oper;
node* left;
node* right;
};
while (temp->left->oper == '+' ||
temp->left->oper == '-' ||
temp->left->oper == '*' ||
temp->left->oper == '/' ||
temp->right->oper == '+' ||
temp->right->oper == '-' ||
temp->right->oper == '*' ||
temp->right->oper == '/') {
// do something
}
What's the "repeated unit" here? Well, I see two instances of
(something)->oper == '+' ||
(something)->oper == '-' ||
(something)->oper == '*' ||
(something)->oper == '/'
So let's factor that repeated part out into a function, so that we only have to write it once.
struct node {
int num;
char oper;
node* left;
node* right;
bool oper_is_arithmetic() const {
return this->oper == '+' ||
this->oper == '-' ||
this->oper == '*' ||
this->oper == '/';
}
};
while (temp->left->oper_is_arithmetic() ||
temp->right->oper_is_arithmetic()) {
// do something
}
Ta-da! Shortened!
(Original code: 17 lines, 8 of which are the loop condition. Revised code: 18 lines, 2 of which are the loop condition.)
"+" "-" "*" and "/" are ASCII decimal values 42, 43, 45 and 47
thus
#define IS_OPER(x) (x > 41 && x < 48 && x != 44 && x != 46)
while(IS_OPER(temp->left->oper || IS_OPER(temp->right->oper){ /* do something */ }
Trading space against time, you could build two "Boolean" arrays indexed by temp->left->oper and temp->left->oper, respectively.
The corresponding array contains true when the condition is met, false otherwise.
So:
while (array1[temp->left->oper] || array1[temp->right->oper]) {
// do something
}
As the sets for left and right seem identical, one array will actually do.
Initialization would be like this:
static char array1[256]; // initialized to "all false"
...
array1['+'] = array1['-'] = array1['*'] = array1['/'] = '\001';
Similar for array2.
As jumps are bad for modern pipelining CPUs, you could even use a larger table like this:
while (array1[temp->left->oper << 8 | temp->right->oper]) {
// do something
}
But initialization is more tricky:
static char array1[256 * 256]; // initialized to "all false"
...
void init(char c) {
for (unsigned char i = 0; i <= 255; ++i) {
array1[(c << 8) | i] = array1[(i << 8) | c] = '\001';
}
}
init('+');
init('-');
init('*');
init('/');
Regex to the rescue!
#include <regex>
while (
std::regex_match(temp->left->oper, std::regex("[\+\-\*\/]")) ||
std::regex_match(temp->right->oper, std::regex("[\+\-\*\/]"))
) {
// do something
}
EXPLANATION: Regex brackets [] denote a regex "character class." This means "match any character listed inside the brackets." For example, g[eiou]t would match "get," "git," "got," and "gut," but NOT "gat." The backslashes are needed because plus (+) minus (-) and star (*) and forward-slash (/) have meaning within a character class.
DISCLAIMER: I don't have time to run this code; you might have to tweak it, but you get the idea. You might have to declare/convert oper from a char to a std::string.
REFERENCES
1. http://www.cplusplus.com/reference/regex/regex_match/
2. https://www.rexegg.com/regex-quickstart.html
3. https://www.amazon.com/Mastering-Regular-Expressions-Jeffrey-Friedl/dp/0596528124/ref=sr_1_1?keywords=regex&qid=1563904113&s=gateway&sr=8-1
Putting the operators in the unordered_set will be lot efficient and will provide O(1) access to operators.
unordered_set<char> u_set;
u_set.insert('+');
u_set.insert('*');
u_set.insert('/');
u_set.insert('-');
if((u_set.find(temp->left->oper) != u_set.end()) || (u_set.find(temp->right->oper) != u_set.end())) {
//do something
}
Lambda & std::string_view
string_view gives lots of functionality of std::string and can operator on literals and it doesn't own the string.
Use Lambda instead of function for a highly local code which is not of use for the rest of the file. Also, no need to pass variables when lambda can capture them. Also get inline benefits without specifying it for a function you'd otherwise create.
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rf-capture-vs-overload
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rstr-view
Make char const:
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rconst-immutable
auto is_arithm = [](const char c) {
return std::string_view("+-/*").find_first_of(c) != std::string::npos;
};
while (is_arithm(temp->left->oper) || is_arithm(temp->right->oper)) {
}
You can change const char c to const node *t access its oper member inside the lambda. But that is not a good idea since members of left/right of temp can be modified.
auto is_arithm2 = [](const node *t) {
return std::string_view("+-/*").find_first_of(t->oper) != std::string::npos;
};
while(is_arithm2(temp->left) || is_arithm2(temp->right)){
}
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.
I have an assignment which requires "Recursively reads one character at a time from the text file until a separator is encountered" -
Those non-separator characters are then displayed in reverse order, with the last character displayed being capitalized
Let's say file has below line and separator is !, white space and so on.
abc! ndtv
Expected output is:
Cba! Vtdn
I have written below code and I am getting the expected output — but one condition is I am supposed to do it using only two variables, and I am not able to do it with less than 3. Any pointers how to achieve it with 2 variables only?
int Reverse(ifstream &inFile, int level)
{
int myInput;
static int returnValue;
static int levelofinterest;
myInput = inFile.get();
if (!(isspace(myInput) || ((char)myInput == '.') ||
((char)myInput == '!') || ((char)myInput == ',') ||
((char)myInput == '?') || ((char)myInput == ';') ||
((char)myInput == ':') || ((char)myInput == '\0')||
myInput == EOF))
{
level++;
Reverse(inFile,level);
}
else
{
levelofinterest = level;
returnValue = myInput;
}
if(!(isspace(myInput) || ((char)myInput == '.') ||
((char)myInput == '!') || ((char)myInput == ',') ||
((char)myInput == '?') || ((char)myInput == ';') ||
((char)myInput == ':') || ((char)myInput == '\0')||
myInput == EOF))
{
level--;
if ((levelofinterest - 1) == level)
{
cout << (char)toupper(myInput);
}
else
{
cout.put((char)myInput);
}
}
return returnValue;
}
This code almost meets your requirements (but I'm not completely happy with it). It has only one extra variable over and above the arguments to the function. However, I altered the function signature — the code doesn't use the return value, so the function is defined as returning void. It probably can be modified to meet your alternative calling convention and the loop structure outlined in your (transcribed) comments.
#include <iostream>
#include <cctype>
using namespace std;
static void Reverse(istream &inFile, int level)
{
int c = inFile.get();
if (c == EOF)
return;
if (isalpha(c))
{
Reverse(inFile, level + 1);
if (level == 0)
cout << (char)toupper(c);
else
cout << (char)c;
}
else if (level > 0)
inFile.unget();
else
cout << (char)c;
}
int main()
{
while (cin)
Reverse(cin, 0);
return 0;
}
I call the source code recrevstr.cpp and compiled the program (using make) with the command:
g++ -O3 -g -std=c++11 -Wall -Wextra -Werror recrevstr.cpp -o recrevstr
and then run it:
$ ./recrevstr <<< 'abc! ndtv'
cbA! vtdN
$
It takes various short cuts. In particular, all non-alphabetic characters are delimiters. It uses an istream rather than an ifstream, and the main() is configured so standard input (aka cin) is processed. Like your sample code, it relies on a loop in the calling code to make sure the job is complete. I start with level 0; it's trivial to start with level 1 instead.
Note that any code using cout with << operators to produce output is inherently C++ and not directly applicable to C. This effect can be neutralized by using <cstdio> and FILE * (and stdin), plus appropriate I/O functions, which could then make it bilingual, though there'd need to be conditional compilation to get the std namespace out of the way.
I'm having trouble implementing a feature that counts and displays the number of vowels from a file.
Here is the code I have so far.
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>
using namespace std;
int main(void)
{int i;
string inputFileName;
string s;
ifstream fileIn;
char ch;
cout<<"Enter name of file of characters :";
cin>>inputFileName;
fileIn.open(inputFileName.data());
assert(fileIn.is_open() );
i=0;
while (!(fileIn.eof()))
{
????????????
}
cout<<s;
cout<<"The number of vowels in the string is "<<s.?()<<endl;
return 0;
}
Note the question marks in the code.
Questions: How should I go about counting the vowels? Do I have to convert the text to lowercase and invoke system controls (if possible)?
Also, as for printing the number of vowels in the end, which string variable should I use, (see s.?)?
Thanks
auto isvowel = [](char c){ return c == 'A' || c == 'a' ||
c == 'E' || c == 'e' ||
c == 'I' || c == 'i' ||
c == 'O' || c == 'o' ||
c == 'U' || c == 'u'; };
std::ifstream f("file.txt");
auto numVowels = std::count_if(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>(),
isvowel);
You can using <algorithm>'s std::count_if to achieve this :
std::string vowels = "AEIOUaeiou";
size_t count = std::count_if
(
std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>(),
[=]( char x)
{
return vowels.find(x) != std::string::npos ;
}
);
Or
size_t count = 0;
std::string vowels = "AEIOUaeiou";
char x ;
while ( in >> x )
{
count += vowels.find(x) != std::string::npos ;
}
Also read Why is iostream::eof inside a loop condition considered wrong?
I am trying to read a sequence which is supposed to be in the form of:
variable operator variable operator variable. . . and so on, where the 'variable' consists is either A , B , or C and the 'operators' are one of the four basic operators + - / * , and simply print valid if it conforms to that given form and invalid if it doesn't. Also, the conditions are that the sequence must start with a single variable and be followed (spaces are allowed in between) by an operator.
I have already made up some code where I take the string input and just have a function called 'check' to see if it returns false, making the program print 'Invalid'. Here is my main function:
using namespace std;
int main() {
string m;
cout<<"Please enter a sequence: "<<endl;
getline(cin,m);
bool allow = check(m);
if(allow == true){
cout<<"\n\nCorrect format "<<endl;
}
else{
cout<<"\n\nIncorrect format \n"<<endl;
}
system("PAUSE");
return 0;
}
And here is my check function:
bool check(string mi){
int c=0; //using c as an index,
mi.append("0"); //append a 0 as a signal to when the string ends
while(c < mi.length()){
if(mi.at(c)=='0'){}
else if(isblank(mi.at(c))){} //So it will accept spaces between the input
else if(mi.at(c) == 'A' ||mi.at(c) == 'B' ||mi.at(c) == 'C'){
//The sequence must start with a variable...
c +=1; //increment to start at the next character...
while(c < mi.length()){ //This whole loop is to check if the next
//significant character is one of the operators
if(isblank(mi.at(c))){}
else if(mi.at(c) !='+' ||mi.at(c) != '-' ||mi.at(c) != '/' || mi.at(c) != '*' || mi.at(c) !='0'){
cout<<"\n(Log) Character at "<<c<<" was not an operator? Value: "<<mi.at(c);
//Why does it always come here even if the value was an operator?
return false;
}
c++;
}
}
c++;
}
return true; //Assume true if there are no errors...
}
Even if I input a correct sequence, say A+B+C , it still comes up as being invalid. I have traced the problem to the particular line of code above. Why does it do this?
Because your boolean logic is incorrect.
The expression:
mi.at(c) !='+' || mi.at(c) != '-' || mi.at(c) != '/' || mi.at(c) != '*' || mi.at(c) !='0'
will evaluate as true every time. For example, if mi.at(c) is a '-', then mi.at(c) != '+' evaluates to true and your into that part of the code you don't want to be in. Likewise, if i.at(c) is a '+' then mi.at(c) != '-' evaluates true and again your conditional evaluates as true again.
I believe you want to change your boolean or's (||) to boolean and's (&&).
For some unsolicited advice, personally I would suggest taking a moment to think of the problem as a state machine. This will enable you to clean up and think about what it is doing in a supportable and expandable fashion. I'm not a c++ coder, but here is how I would approach it in c as a state machine. You should be able to translate it to c++:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
main() {
char* VARS = "ABC";
char* OPS = "+-/*";
char c = EOF;
int state = 0;
while (((c = getchar()) != EOF) && (state < 3)) {
// move on to next character if we have a blank or end-of-line
if (c == ' ' || c == '\n')
continue;
// test to see if the character is a var or op
int isvars = (strchr(VARS, c) != NULL);
int isops = (strchr(OPS, c) != NULL);
// based upon character type and current state, determine next state
if (!isvars && !isops) // character is neither a valid var nor op
state = 3;
else if (isvars) // character is a var
if ((state == 0) || (state == 2))
state = 1;
else if (state == 1)
state = 3;
else if (isops) // character is an op
if ((state == 0) || (state == 2))
state = 3;
else if (state == 1)
state = 2;
}
puts((state > 1) ? "bad" : "good");
}
And, here is the result after compiling it to 'varop':
$ echo "" | ./varop
good
$ echo "A" | ./varop
good
$ echo "+" | ./varop
bad
$ echo "A+" | ./varop
bad
$ echo "AA" | ./varop
bad
$ echo "A+" | ./varop
bad
$ echo "A+A" | ./varop
good
$ echo "A++" | ./varop
bad
$ echo "A + B" | ./varop
good
$ echo " A + B" | ./varop
good
$ echo "D" | ./varop
bad
$ echo "%" | ./varop
bad
You are correct in where your problem is, however problem is your basic logic. Because you use || and not &&, that means that your statement will always evaluate to true (i.e. '+' will evaluate to false in the first condition, but will evaluate to true when checking for not -). What you need to do is replace the || operators in the culprit line with && and your check function should behave as expected.
Also, as a style note, on line 8 of your check function, instead of c += 1, you should use c++ for the sake of consistancy.
Try this out, it compiles and gives the desired output. However it still not enforcing that an operator should be followed by a character for example. But i guess you can figure that out.
using namespace std;
To help, i made an array of possible operators along with a function that checks if a character is an operator or not.
unsigned char operators[] = { '+','-','/','*' };
bool isOperator(const unsigned char &m) {
for (int n = 0; n < 4; n++) if (m == operators[n]) return true;
return false;
}
In your check there is only one loop needed and a for loop is much more conveniant. Notice the logic, i continue when the character is a A or B or C or when it is blank.
bool check(string mi){
for (int c = 0; c < mi.size(); c++) {
cout << mi.at(c);
if (isblank(mi.at(c))) continue;
if (mi.at(c) == 'A' || mi.at(c) == 'B' || mi.at(c) == 'C') continue;
if (!isOperator(mi.at(c))) {
cout<<"\n(Log) Character at " << c <<" was not an operator? Value: "<<mi.at(c);
return false;
}
}
return true; //Assume true if there are no errors...
}
int main() {
string m;
cout<<"Please enter a sequence: "<<endl;
getline(cin,m);
cout << "\n\n" << string(check(m) ? "Correct":"Incorrect") << " format." << endl;
system("PAUSE");
return 0;
}
Output:
Please enter a sequence:
A+B+C
A+B+C
Correct format.
Press any key to continue . . .
I would suggest using std::istringstream and using std::copy to get the separate components into a std::vector of characters. Then it's simple to iterate over the vector to check for only the valid components.
To help with getting the components into the vector with std::copy, I suggest you read about std::istream_iterator and std::back_inserter.