I opened a .txt file with an ifstream object named input. If a new line starts with a "(" then it doesn't read it how I want it to. The expected output doesn't get printed, then it exits the loops. I want it to only jump out of the while loop when it reaches the end of the file. What am I doing wrong? My do while loop and my .txt file are below.
char c;
int i;
do
{
if(input.peek( ) == '(' || input.peek( ) == ')')
{
input >> c;
cout << c;
}else if(input.peek( ) == '+' || input.peek( ) == '-' || input.peek( ) == '*' || input.peek( ) == '/')
{
input >> c;
cout << c;
}else
{
input >> i;
cout << i;
}
}while(input && input.peek( ) != EOF);
Here is the .txt file, each on a separate line:
(3)
(3)
4
(5+7)-(5*3)
This is my output:
(3)3
So, I'm pretty certain that the problem is that input.peek() is returning a newline after ')' has been read. Then input >> i; doesn't read a number, and i remains the value it had before, so the output is 3. You could quickly try this by adding i = 42; before input >> i; - if the output becomes (3)42, then I'm right.
If I'm right, you will want to add a bit of code to handle isspace() or something similar.
May I also suggest that you do something like cpeek = input.peek();, before the first if, and then use if (cpeek == '(' || cpeek == ')')... etc.
Related
I am tasked to write a simple program that reads in a file, and determines if the characters '(' '[' and '{' and "balanced". Meaning, There is a matching closing bracket/brace/parentheses for each opening one.
I am having trouble with the input. We are to use input redirection, not an iostream object, taking advantage of the command line. We utilize a makefile and when I run the executable it tells me 2 errors: not using argc and argv[].
struct Contents {
int numP;
int numS;
int numC;
};
int main(int argc, const char* argv[]) {
char word;
Contents c;
while(cin >> word) {
if(word == '{' || word == '}') {
c.numC++;
}
if(word == '(' || word == ')') {
c.numP++;
}
if(word == '[' || word == ']') {
c.numS++;
}
}
if(c.numC % 2 == 0 || c.numP % 2 == 0 || c.numS % 2 == 0) {
cout << "Balanced" << endl;
}
else {
cout << "Not Balanced" << endl;
}
return 0;
}
What am I missing here to make the file redirection input work? When I run this in XCode I just enter a bunch of values and it never ends. I can't seem to do the input right.
Thank you!
You need to break out of the while loop, if you are reading from a file then your code should work as it is. I have just made a small change to the logic when checking whether it is balanced or not.
int main() {
char word;
Contents c;
while (cin >> word) {
if (word == '{' || word == '}') {
c.numC++;
}
if (word == '(' || word == ')') {
c.numP++;
}
if (word == '[' || word == ']') {
c.numS++;
}
}
// Edited here: Check using and instead of or.
if (c.numC % 2 == 0 && c.numP % 2 == 0 && c.numS % 2 == 0) {
cout << "Balanced" << endl;
} else {
cout << "Not Balanced" << endl;
}
return 0;
}
Update:
I have tested the code, so here is the output.
Here is the output. You can redirect the input to any file and it will scan the file until it reaches EOF.
I have looked over this for hours it seems like. This program will compile, it just can't detect errors correctly. And for some reason it will work when I type in hey [) or hey {], etc. But it won't work for hey[) or hey{]. Obviously in all cases it should detect an error but for some reason the space after 'hey' makes a difference.
#include<iostream>
#include <stack>
using namespace std;
bool delimiterMatching(char *file){
stack<char> x;
int count = 0;
char ch, onTop, check;
while(ch != '\0'){
ch = file[count];
if (ch == '(' || ch == '[' || ch == '{')
x.push(ch);
else if (ch == ')' || ch == ']' || ch == '}') {
onTop == x.top();
x.pop();
if((ch==')' && onTop!='(') || (ch==']' && onTop!='[') || (ch=='}' &&
onTop!= '{'))
return false;
}
count++;
}
if (x.empty())
return true;
else
return false;
}
int main()
{
char *test = new char();
cout << "enter sentence: ";
cin >> test;
if (delimiterMatching(test))
cout << "success" << endl;
else
cout << "error" << endl;
return 1;
}
With cin >> test you don't get a whole sentence, but only a string until cin encounters whitespace. So if you type (hey ), thest would be (hey and the closing brace would only be read by the next >>, whereas (hey) would work as expected.
You have a second issue with your test allocation, which might be too short for reasonable input.
Change main() as follows:
char *test = new char[256]; // enough space. COnsider also string
cout << "enter sentence: ";
cin.getline(test, 256); // full line input.
...
You have also two nasty bugs in delimiterMatching().
First you use an uninitialized ch in your while condition. Either initialise ch to a non nul char, or use while (file[count]).
And did you notice onTop == x.top(); ? Shouldn't it be onTop = x.top();?
I got conflicting advice with respect to how c++ operates with respect to reading past the eof.
The first group of people state that when the marker is reading past the eof area it reaches the eof and stops while the other group of people state it has to be in the exact position for it to be processed as reaching the eof. To make this clearer let me paste 2 blocks of code.
In this block of code, I am reading a number 1 from the file numbers.txt. They're no syntax errors and the only thing which I didn't paste over here is the code that opens the file.
while (!sample.eof())
{
char ch;
sample.get(ch);
sample.seekp(-1L, ios::cur);
sample >> initialnumber;
sample.seekp(2L, ios::cur);
cout << "OK";
}
In this program here I am reading the number 1 moving back one space making it start from the beginning processing it and then moving two spaces forward. The output for this is OK written only once.
#include < iostream>
#include < fstream>
#include< string>
using namespace std;
string conversion(int);
int conversion2(string);
int main()
{
string initialnumber;
fstream SAMPLE("numbers.txt", ios::in | ios::out);
ofstream sample2("numbers2.txt");
if (sample && sample2)
{
int number2;
string roman;
int number;
char ch;
while (!sample.eof()) {
sample.get(ch);
if (ch != '1' && ch != '2' && ch != '3' && ch != '4' && ch != '5' && ch != '6'
&& ch != '7' && ch != '8' && ch != '9') {
SAMPLE.seekg(-1L, ios::cur);
sample >> roman;
sample.seekg(2L, ios::cur);
sample2 << roman << " " << conversion2(roman) << endl;
int L = sample.tellp();
cout << L;
}
else {
sample.seekg(-1L, ios::cur);
sample >> number2;
sample2 << conversion(number2) << " " << number2 << endl;
sample.seekg(2L, ios::cur);
}
}
}
else
{
cout << "fail";
}
sample.close();
sample2.close();
}
Here it is repeating the number infinite number of times when it shouldn't be repeating it meaning it never reached the eof.
Please help me understand the logic of both programs.
Starting from C++11
Before doing anything else, seekg clears eofbit.
http://en.cppreference.com/w/cpp/io/basic_istream/seekg
Since seekg is always the last thing you call before checking .eof(), it will never be detected. The eofbit is set when a read operation hits the end of file. So, a read must be the last thing you do for it to work.
I'm working on a project from class and it's a text analysis project. We're supposed to load a document into the program and basically read data from it. Ex: (word count, sentence count, etc.). For some reason, my first function isn't working correctly: my loadDocument function is supposed to load the document into the program.
Here is the code in main to call that function:
case 1: // Load Document
{
string inputLoc;
cout << "Please input the document name:" << endl;
cin >> docName;
myDocs[docCount].setName(docName);
myDocs[docCount].id = docCount;
cout << "Input Location: " << endl;
cin >> inputLoc;
myDocs[docCount].loadDocument(inputLoc);
docCount++;
break;
}
I have docName initialized outside of the case - before it.
Here is my loadDocument in side my Document class:
void Document::loadDocument(string name)
{
ifstream myFile(name);
int numOflines = 0;
string theLine;
char words;
while (myFile.get(words))
{
switch (words)
{
case '.':
numOflines++;
break;
case '?':
numOflines++;
break;
case '!':
numOflines++;
break;
}
}
lineCount = numOflines;
setLineCt(numOflines);
arr = new Line[lineCount];
myFile.close();
char theChar;
ifstream myFile2(name);
int key = 0;
if (myFile2.is_open())
{
for (id = 0; id < lineCount; id++)
{
while (theChar != '.' || theChar != '!' || theChar != '?')
{
myFile2 >> noskipws >> theChar;
theLine[key] = theChar;
key++;
}
myFile2 >> theChar;
arr[id].setStr(theLine);
}
}
}
I just wanted to know if my loadDocument has any evident bugs? For some reason, it's not actually loading a document into the program. For the input location, I typed in the exact file location of a text file that I want to input. For ex: C:\Users\Documents------. After I input that, my program just goes into an infinite loop.
Is my loadDocument doing what it's supposed to do? It's supposed to open a document and extract the number of sentences from it as well as number of words.
Also, am I testing it correctly by typing in that file location like that? I'm new to file input/output sorry.
Your while() loop is incorrect:
while (theChar != '.' || theChar != '!' || theChar != '?')
|| is not the right conditional operator here. If one condition is false, the two others will be true, thus leading to the infinite loop. You have to use &&:
while (theChar != '.' && theChar != '!' && theChar != '?')
I'm writing a program that takes user input and uses stacks to convert an infix expression into a postfix expression based on precedence, with operands always going before operators. For example, if a user inputs:
(a+b*c)
then the program should display:
abc*+
so far, I have this:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main()
{
stack<char> s;
char input;
while (cin.get(input) && input != '\n')
{
if (isalnum(input))
cout << input << "\n";
else if (input == '(')
s.push(input);
else if (input == ')')
{
while (!s.empty() && s.top() != '(')
{
cout << s.top();
s.pop();
}
if(!s.empty())
s.pop();
else
cout << "ERROR: No Matching ( \n";
}
else if (s.empty() && input == '*'||'/'||'+'||'-' && s.top() < input) // Error Begins Here?
{
char a = '*';
char b = '/';
char c = '+';
char d = '-';
bool prec (char a, char b, char c, char d);
return ('*' > '/' > '+' > '-');
s.push(input);
}
else if (input == '*'||'/'||'+'||'-' && s.top() >= input)
while (!s.empty())
{
cout << s.top();
s.pop();
s.push(input);
}
}
while (!s.empty())
{
cout << s.top();
s.pop();
}
}
Which compiles and runs but is not functioning as it should. When an expression like "ab" is input, the program will display "ab" as it should but if I input "a+b+c", then only "a" will be displayed. This means the program is not placing the operators into the stack to be displayed later on. What I need help with is modifying the program so that when an operator is input, it should be added onto the stack and then displayed based on it's precedence (*>/>+>-) after the operands, when the input is done.
I'm quite new to C++ and programming in general, so any suggestions would be great.
else if (input == '*'||'/'||'+'||'-' && s.top() >= input)
This does not do what you think it does. You need to do
else if (input == '*'|| input == '/'|| input == '+'|| input == '-' && s.top() >= input)
And this looks like an error too
bool prec (char a, char b, char c, char d);
That's the syntax for a function prototype. Are you sure this compiles?
The problem is here:
bool prec (char a, char b, char c, char d);
return ('*' > '/' > '+' > '-');
I'm guessing this is intended to define a precedence function, but that's not what it's doing. The first line declares that such a function exists (and its arguments have nothing to do with the variables declared in the previous lines), and the second causes the whole program to terminate. If you want a function like this, you must define it outside main.
A slightly less dramatic bug is here:
if (s.empty() && input == '*'||'/'||'+'||'-' && s.top() < input)
First, this part
input == '*'||'/'||'+'||'-'
is interpreted as
(input == '*') || ('/') || ('+') || ('-')
The last three terms are true, the first is irrelevant. And I'm not even sure what s.top() does if s is empty.
This should be enough to go on. I suggest you start by building and testing routines that can, e.g., identify the operators and evaluate their precedence, before you try putting everything together in one program.
Falmarri is right just wanted to post that my self , and it compiles I tried it , but there is another thing : you said
else if (s.empty() && input == '*'||'/'||'+'||'-' && s.top() < input) // Error Begins Here?
Are you sure that even reached that point because when I runn it , it just stops on the :
while (cin.get(input) && input != '\n')
until I hit enter and even more you can enter more then one char from consol while in cin.get(input) but the input will contain only the first char you entered . To solve this I just put an
#include <conio.h>at the beginning an used
while ((input = getch()) && input != (char)13) in staid of you're code
short explanation
getch()
returns after you press only one character and
input != (char)13
is required in staid of
input != '\n'
because getch() return (char)13 for ENTER see ASCII table for more info.