I'm working on a project to convert from postfix to infix expressions. I was stuck for a while but I had part of it working then I realized I needed to inlcude a space between each of the operands when I input it to the user.I'm not sure how to take in a string and not include spaces how would I go about doing that. getline doesn't work as it includes spaces. therefore instead of ab+ I need to accept it as: a b +. i'm not sure how to do this not include the strings. Here is my code so far.
#include "stack.h"
void convert(string expression){
stack c;
string post =" ";
string rightop="";
string leftop="";
string op ="";
for (int i =0; i<=expression.length()-1;i++){
c.push(expression[i]);
c.print();
if (expression[i] == '*' ||
expression[i] == '+' ||
expression[i] == '-' ||
expression[i] == '/'){
cout<<c.top()<<endl;
leftop=c.top();
cout<<leftop<<endl;
c.pop();
rightop=c.top();
cout<<rightop<<endl;
c.pop();
op=c.top();
cout<<op<<endl;
c.top()=expression[i+1];
//c.pop();
post="(" + leftop + " " + op + " " + rightop + ")";
cout<<post<<endl;
}
//c.push(post);
}
}
int main(){
string expression;
cout<<" Enter a Post Fix expression: ";
getline(cin,expression);
convert(expression);
return 0;
}
In C, strings are essentially a bunch of character pointers. You can refer to this SO post for a few examples of how to remove white space from your input string by moving pointers.
You can test explicitely each character against " \t\r", or you can use the isspace function declared in cctypes :
for (int i =0; i<=expression.length()-1;i++){
if (isspace(expression[i])) continue;
// remaining unchanged ...
I've update my answer to your other question with that.
Related
Instructions:
using a value returning function
Write a program that prompts the user to input a sequence of characters and outputs the number of vowels.
This is the problem given by the instructor..
#include <iostream>
using namespace std;
bool isVowel(char ch);
int main() {
char ch;
cout << "Enter a character: ";
cin >> ch;
cout << ch << " is a vowel: " << isVowel(ch) << endl;
return 0;
}
bool isVowel(char ch){
if (ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U' ||
ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u'){
return true;
} else
return false;
}
char is a single character, not a sentence. For a sentence use a string.
string s;
cout << "Enter a sentence: ";
cin >> s;
Then use a loop to loop through each character of the sentence
for (char ch : s)
{
...
}
Then use isVowel to test a single character, and increment the count if found. The clue is in the name isVowel, not countVowels, so isVowel should test a single vowel and return true or false, not count the number of vowels.
int vowels = 0;
for (char ch : s)
{
if (isVowel(ch))
vowels++;
}
finally write isVowel to test a single character.
bool isVowel(char ch)
{
return ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U' ||
ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u';
}
There are several problems here.
Firstly, you don't initialize vowels. You presumably mean int vowels = 0; or int vowels {0};.
Secondly, you are reading a single character with cin >> ch;. I suspect you mean to loop over an input string.
Thirdly, your signature for isVowel is bool isVowel(int vowels, char ch);, which returns a bool. But you have written your function as thought it is manipulating an integer total of vowels. This inconsistency doesn't make sense.
Fourthly, you assign the result of isVowel to a character in ch = isVowel(vowels,ch);. Then you call isVowel again with this updated ch in cout << isVowel(vowels, ch) << .... I'm not sure what you're attempting to do here, but this also doesn't make any sense.
You need to revisit all of this code. You probably want isVowel to actually return a boolean. You probably want to iterate over an entire input string, and adjust the value of vowels appropriately (after initializing it).
Your program is running an undefined behavior; you are using vowels without being initialized.
You can make function that takes the counter of vowels as a reference to an integer for example.
void isVowel(int& counter, char ch) {
std::string vowels{ "AaEeIiOoUu" };
for (auto c : vowels)
if(ch == c)
counter++;
}
int main(){
char ch;
int counter{};
while (std::cin >> ch)
isVowel(counter, ch);
std::cout << counter << endl << " vowels in this sentence." << endl;
}
#include <iostream>
using namespace std;
bool isVowel(int vowels, char ch);
So isVowel returns a bool. That would make sense if its purpose was to tell us whether a single character was a vowel or not. For some reason, we pass an integer called vowels to it. That doesn't seem to make any sense. What would it do with an integer value?
int main() {
char ch;
So ch is a single character. Okay.
int vowels;
And vowels is an integer with no particular value.
cout << "Enter a sentence: ";
cin >> ch;
Uh oh. We ask the user to enter a sentence but then we read in a single character. Remember, ch was a char.
ch = isVowel(vowels,ch);
Uh oh. We didn't assign vowels any particular value, so we've passed no particular value to isVowel. Also, we took the boolean value returned and assigned to a variable of type char. Why would we do that?
cout << isVowel(vowels, ch) << " vowels in this sentence." << endl;
Then for some reason we call isVowel again. That doesn't make much sense. Also, isVowel returned a bool (a yes or no). Why are we outputting that as if it was the number of vowels?
return 0;
}
// build a string counter and make it callable
bool isVowel(int vowels, char ch){
Okay, so isVowel returns a boolean and takes as input an integer and a character.
for (int i = 0; i < ch; i++){
if (ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U' ||
ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u'){
vowels++;
}
We are looping from zero to the value of the single character? That doesn't make sense.
}
return vowels;
}
Lots of problems here. Because there are so many fundamental problems with this code, it seems you've attempted a problem that's way beyond your C++ knowledge and you should attempt something much simpler first, such as accepting a sentence as input and repeating it back to the user without using any additional functions.
I'm currently working on a project to convert from postfix to infix using a stack in the form of a singly linked list. I've managed to convert expressions such as ab+ to (a+b) however when the expression gets longer such as ab+cd*-. It doesn't work. I'm considering pushing the previously converted expression back onto the stack however the stack is of type char and the expression is a string and it complains when I try to push it back. Should I make it a template and if so how would I do it or is there anyway else to solve this problem.
Here is my code:
#include "stack.h"
void convert(string expression){
stack c;
string post = " ";
string rightop = "";
string leftop = "";
string op = "";
for (int i = 0; i <= expression.length(); i++){
c.push(expression[i]);
c.print();
if (expression[i] == '*' ||
expression[i] == '+' ||
expression[i] == '-' ||
expression[i] == '/'){
cout << c.top() << endl;
leftop = c.top();
cout << leftop << endl;
c.pop();
rightop = c.top();
cout << rightop << endl;
c.pop();
op = c.top();
cout << op << endl;
//c.pop();
post = "(" + leftop + " " + op + " " + rightop + ")";
cout << post << endl;
}
//c.push(post);
}
}
int main(){
string expression;
cout << " Enter a Post Fix expression: ";
getline(cin, expression);
convert(expression);
return 0;
}
The original code is lacking following declarations to compile :
#include "stack"
#include "string"
#include "iostream"
using namespace std;
Next, the type of the stack should be a string to be able to store full expressions onto it.
You did not take the elements in proper order from the stack : it is first op, next rightop and finally leftop
The currently commented out last c.pop() is necessary to remove 3rd element from the stack, but it must be followed inside the loop with the (again commented out) c.push(post);
The loop on expression goes one step too far : it should be for (int i =0; i<expression.length();i++) (note the < instead of <=)
When this is done, it is enough to make the convert function to return the last post as a string for the program to give expected result.
As you asked in this other question, it would be much better to ignore spaces in the input string : you should add if (isspace(expression[i])) continue; immediately after the for.
With all those fixes, the code could be :
#include <stack>
#include <string>
#include <iostream>
#include <cctypes>
using namespace std;
string convert(string expression){
stack<string> c;
string post =" ";
string rightop="";
string leftop="";
string op ="";
for (int i =0; i<expression.length();i++){
if (isspace(expression[i])) continue;
c.push(string(expression.c_str() + i, 1));
//c.print();
if(expression[i] == '*' ||
expression[i] == '+' ||
expression[i] == '-' ||
expression[i] == '/'){
cout<<c.top()<<endl;
op=c.top();
cout<<leftop<<endl;
c.pop();
rightop=c.top();
cout<<rightop<<endl;
c.pop();
leftop=c.top();
cout<<op<<endl;
c.pop();
post="(" + leftop + " " + op + " " + rightop + ")";
cout<<post<<endl;
c.push(post);
}
}
return post;
}
int main(){
string expression;
cout<<" Enter a Post Fix expression: ";
getline(cin,expression);
string converted = convert(expression);
cout << "Converted expression : " << converted << endl;
return 0;
}
And when given ab+cd*- you get at the end ((a + b) - (c * d))
You just have to comment out all the traces form convert method ;-)
i get the impression your "stack" is not used properly. e.g. if ab+* is pushed on the stack your variables become leftop = +, rightop = b, op = a, in order to convert a postfix expression it is easiest to create a binary evaluation tree to get the operator precedence right
e.g.
for ab+c* you want
*
/ \
+ c
/ \
a b
and then evaluate the tree either recursively or not. everytime the operator is + or - use parenthesis around it,
This question already has answers here:
Reversing order of words in a sentence
(8 answers)
Closed 9 years ago.
So.. I'm sorry I doubleposted. I really didn't know how this site works. However, I'm changing my whole question here so that it's more understandable. And here it is:
char s[1002];
cin.getline(s, 1002, '\n');
int k;
int p = strlen(s);
strcat(s, " ");
for (int i = 0; i <= p; i++)
{
if (s[i] == ' ')
{
for (k = i - 1; (k != -1) && (s[k] != ' '); k--)
cout << s[k];
cout << " ";
}
}
' ' , ',' , '.' and ';' should be delimiters but I've managed to pull it to work only with ' ' (intervals).
I cannot use std::string as I'm doing this for a homework where I need to make a very specific function - char const* reverseWordsOnly(const char*).
What should the code do?
Input: Reversing the letters, is; really hard.
Output: gnisreveR eht srettel, si; yllaer drah.
While I still feel this is a duplicate, the thought process for solving this would be this:
Write a function that returns true for alphabet characters (a-z and A-Z), and false otherwise.
Start at the beginning of the string
Find the next alphabet character, note its location (start)
Find the next non-alphabet character, note its location (end)
Reverse the characters in the range [start, end)
Repeat steps 3-5 until the end of the string
All of this becomes very easy when you use std::string and algorithms like std::reverse instead of using raw arrays and custom. Since you are allowed to use std::cin and std::cout (<iostream>), the argument against using <string> is a silly one.
You can store the string in another array without the symbols first and then reverse the new array. For example if you want to ignore a comma (,) or semicolon (;) you can write something like
while(i <= p)
{
if (s[i] == ',' || s[i] == ';')
{
i++;
}
else
{
temp[j]=s[i];
j++;
i++;
}
}
Then you can reverse the temp array.
Instead of just printing the letters like this
for (k = i - 1; (k != -1) && (s[k] != ' '); k--)
cout << s[k];
cout << " ";
Check to see if you need to ignore the letter, like this
for (k = i - 1; (k != -1) && (s[k] != ' '); k--)
if((s[k] != ',') && (s[k] != ';') && ...other ignored chars...)
cout << s[k];
cout << " ";
#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
int main(){
char s[1001],ch;
int c=0; // for counting how many words are in the array
while((ch = getchar()) != '\n'){ // input string until new line
if ((ch>='a' && ch<='z') || (ch>='A' && ch<='Z')) // check if the input character is a letter or symbol
s[c++] = ch; // if its a letter then insert into the array
}
for (int i=c-1;i>=0;i--) // print the array in reverse order
cout<<s[i]<<" ";
return 0;
}
I am doing infix to postfix notation. My program compiles, although, for some reason it will not take in any infix expressions, only postfix expressions. Which is the opposite I wanted to do. Here is my program:
#include <iostream>
#include <string>
#include <sstream>
#include "stack"
using namespace std;
string infixexpr (istream& in)
{
//Holds value in computation
stack<string> postfixstack;
//used to to read in characters from the expression
char ch;
// used to read in numbers from expression
int num;
// Used to remove infix expressions from stack
string lexpr, rexpr;
ch = in.peek();
while ( ch != EOF)
{
//If we have a whitespace character skip it and continue with
// the end of the loop.
if(isspace(ch))
{
ch = in.get();
ch =in.peek();
continue;
}
//nonspace character is next to input stream
// if the next character is a number read it and convert it
// to string then put the string onto the postfix stack
if (isdigit (ch))
{
in >> num;
// use to convert string
ostringstream numberstr;
// convert to number using sstream
numberstr << num;
// Push the representing string onto stack0
postfixstack.push(numberstr.str());
ch = in.peek();
continue;
}
// if operator pop the two postfix expressions
// stored on the stack, put the operator after
postfixstack.pop();
lexpr = postfixstack.top();
postfixstack.pop();
if (ch == '+' || ch == '-' || + ch == '*' || ch == '/' || ch == '%')
postfixstack.push(rexpr + " " + lexpr + " " + ch);
else
{
cout << "Error in input expression" << endl;
exit(1);
}
ch = in.get();
ch = in.peek();
}
return postfixstack.top();
}
int main()
{
string input;
cout << "Enter a infix expression to convert to postfix,"
<< " \nor a blank line to quit the program:";
getline(cin,input);
while (input.size() != 0 )
{
//convert string to a string stream
istringstream inputExpr(input);
cout << "the infix equavilent is: "
<< infixexpr(inputExpr) << endl;
cout << "Enter a infix Expression to evaluate: ";
getline(cin,input);
}
return 0;
}
For example the program runs like this:
if I enter 56 2 + (add spaces after each number or operator)
I'll get back 56 2 +, which is what I want. But if I enter
56 + 2, the program will crash.
If you like to see my stack class and header, if that is the problem please let me know. I can post it under reply.
Oh my, where to begin. You should probably take this to the Code Review Stack Exchange instead, but let's get into it:
You don't describe the "crash", so we don't know what failure you're observing.
Your "if the next character is a number read it and convert it to string then put the string onto the postfix stack" code pushes the operand on the stack. But in Dijkstra's shunting-yard algorithm, which you appear to be trying to implement, only operators go on the stack.
Your "if operator pop the two postfix expressions stored on the stack, put the operator after" code doesn't guard against popping items off an empty stack.
That same code also pops two items off the stack, but you only pushed one on - the "56" in "56 + 2". Since you're forcing me to guess, I'm guessing this is where the program crashes.
That same code also pushes the result onto the stack, another example of how not to implement the shunting-yard algorithm.
Here is my whole program, I am supposed to calculate the average number of letters in words from an input file called hw4pr11input.txt. I have only been programming for a couple of weeks so I would appreciate simple answers that I could possibly implement with my small amount of knowledge. I do not know what arrays are yet, the chapter I am doing the homework for is on file io.
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
//function declaration
void average_letters(ifstream& fin);
//Precondition: there is a input file with text ready to be read
//postcondition: Text from the input file is read then the average length of
//words is calculated and output to the screen
//start main program
int main()
{
ifstream fin;
fin.open("hw4pr11input.txt"); //opening input file
if (fin.fail()) //checking for input file opening failure
{
cout << "Input file open fail";
exit(1); //terminating program if check fails
}
cout << "File Open\n";
average_letters(fin); //calling function to remove spaces
system("pause");
return 0;
}
//function definition, uses iostream and fstream
void average_letters(ifstream& fin)
{
char next, last_char = 0;
double letter_count = 0, word_count = 0;
double average = 0;
while(!(fin.eof()))
{
fin.get(next);
if(!(next == ' ' || next == ',' || next == '.' || next == '/'
|| next =='(' || next == ')'))
{
letter_count++;
}
else
{
if((next == ' ' || next == ',' || next == '.' || next == '/'
|| next =='(' || next == ')') && (last_char == ' ' || next == ','
|| next == '.' || next == '/' || next =='(' || next == ')' ))
{
continue;
}
else
{
word_count++;
}
}
last_char = next; //stores previous value of loop for comparison
}
average = letter_count/word_count;
cout << "The average length of the words in the file is:" << " " <<average;
cout << endl;
}
I believe this program works to accomplish the assignment, but my main concern is with the part of function average_letters that checks to see if it is a letter or a symbol. I chose this symbol list by looking at the .txt file. I deleted comments because they make copy and pasting here difficult I apologize if that makes my logic more difficult to understand.
Thanks for your help. Go easy on me :).
You can use a std::bitset<255> using the character converted to an unsigned integer and preset only those characters to true that are word characters. In your loop, you just lookup if its a valid word.
Note, this presupposes a char being 255 bits instead of unicode. You can up-size your bit set accordingly.
This allows you a very fast check of whether the character is a word character and allows you to define which characters you want to include (if the requirement changes suddenly to include '-', for example.
you could beautify this code by storing those groups of characters in strings. Then you could write a function which takes a char and a string and checks if the char is equal to any char in the given string. But that would require that you learn how to use arrays, because strings i C are arrays of chars.