C++ program, infinite loop on input - c++

Hello i compile this program to an executable called picodb and try to run it through a shell bash script at linux.
int main(int argc, char** argv) {
Debbuger DB(argc,argv);
char command[12];
int len;
bool valid;
while(1)
{
valid=true;
cin.clear();
cin>>command;
len=strlen(command);
if(command[0]=='t')
{
if(strcmp(command,"trace")==0 || len==1)
{
cin>>command;
valid=DB.Trace(command);
}
else valid=false;
}
else if(command[0]=='r')
{
if(strcmp(command,"redirect")==0 || len==1)
{
char stream[6],file[15];
cin>>stream; cin>>file;
valid=DB.Redirect(stream,file);
}
else valid=false;
}
else if(command[0]=='b')
{
if(strcmp(command,"blocking-mode")==0 || len==1)
{
cin>>command;
valid=DB.Blocking_mode(command);
}
else valid=false;
}
else if(command[0]=='l')
{
if(strcmp(command,"limit-trace")==0 || len==1)
{
int n;
cin>>n;
valid=DB.Limit_Trace(n);
}
else valid=false;
}
else if(command[0]=='g')
{
if(strcmp(command,"go")==0 || len==1)
{
DB.Go(argv[1]) ;
}
}
else if(command[0]=='q')
{
if(strcmp(command,"quit")==0 || len==1)
return 0;
else
valid=false;
}
else if(command[0]=='h')
{
if(strcmp(command,"help")==0 || len==1)
DB.Help();
else valid=false;
}
else valid =false;
if(valid==false)
{
cout<<"Invalid command"<<endl;
}
}
}
The script is this:
#!/bin/bash
./picodb << EOF
t file_management
r stdin input.txt
EOF
but when i execute this script the program goes to an infinite loop where it gets the "t file_management" and never stops or change this input. I printed the string command and it always has the value " t file_management" the first argument. I can't figure what I am doing wrong. I tried running the program at terminal giving it the inputs by hand and works fine.
Edit:To make it clearer this is supposed to be a user interface.It never gets out of loop until you type quit.The problem is that what is read throuth the bash repeats to infinite.

cin >> command will only read one word at a time. Are you sure you have "t file_management" in command? When I run your program it works. However it still ran in an infinite loop using the script, so I changed the following line: while(1) -> while(cin >> command)

Related

Stack Question (Balanced Expression problem set)

I have solved a problem set for a CPSC class where we have to implement a stack to check if an expression is balanced. For example, when a user enters {a}, the program would check if it has been properly closed and return true or false. My program is running accordingly, but only for char values such as. {, ( & and [. When I enter an input of (2(1+2)) it returns false. The algorithm makes sense and works, but I cannot seem to find the issue with my isBalanced function.
I could really use some help
#ifndef BALANCED_H
#define BALANCED_H
#include<string>
class Balanced {
public:
Balanced(std::string);
bool isBalanced();
bool isMatch(char c, char d);
private:
std::string expression;
};
#endif // BALANCED_H
#include "Balanced.h"
#include <string>
#include<iostream>
#include <stack>
Balanced::Balanced(std::string s) : expression(s)
{
}
bool Balanced::isBalanced()
{
std::stack<char> b;
for(unsigned int i=0; i < expression.size(); i++)
{
if(expression[i]=='{'|| expression[i] == '[' || expression[i] == '(')
{
b.push(expression[i]);
continue;
}
if(b.empty() || !isMatch(b.top(), expression[i]))
{
return false;
}
else{
b.pop();
}
}
return b.empty();
}
bool Balanced::isMatch(char c, char d)
{
if(c == '{' && d == '}')
{
return true;
}
else if(c == '[' && d == ']')
{
return true;
}
else if(c == '(' && d == ')')
{
return true;
}
else
{
return false;
}
}
int main()
{
std::string s;
std::string expression;
std::cout<<"Welcome to balance expression program" <<std::endl;
do{
std::cout<<"Enter any key to continue or type 'Help' to display a help menu ";
std::cout<<"You may also type 'Exit' to exit the program: ";
std::cin>>s;
if(s=="Help")
{
displayHelp();
continue;
}
else if(s=="Exit")
{
break;
}
else{
std::cout<<"Enter an expression: ";
std::cin>>expression;
}
Balanced d(expression);
if(d.isBalanced()!=true){
std::cout<<"The expressions is not balanced";
std::cout<<std::endl;
}
else{
std::cout<<"The expression is balanced";
std::cout<<std::endl;
}
}while(s!="Exit");
return 0;
}
void displayHelp()
{
std::cout<<std::endl;
std::cout<<"The purpose of this program is to check ";
std::cout<<"if an expression is balanced ";
std::cout<<"You will enter an expression and it will check to see if there is
closing ";
std::cout<<"brackets. If the expression is balanced, then it will return true if
not ";
std::cout<<"then the program will return false ";
std::cout<<"You can enter as many expression as you like. If you like to exit
the program, ";
std::cout<<"type 'Exit'"<<std::endl;
std::cout<<std::endl;
}
It would seem that your isMatch function will return false if the current character is not an open or close bracket, thus causing the whole thing to return false.

Is there a way to stop the loop repeating more than once when running

I want to build a simple questionnaire program. When i run the code it repeats the statement twice when i want it to run only once and not repeat the cout statements. This only happens when i use strings and not characters. Sorry for the clumsy writing.[enter image description here][1]
The code is below:
#include<iostream>
#include<string>
using namespace std;
bool N='n';
bool Y='y';
bool YES="yes";
bool NO="no";
int main(){
char response, response2, response3;
string response_1, response_2, response_3;
cout<<"Hello would you like to answer a few questions?"<<endl<<"Please input y or n"<<endl;
cin>>response;
{ do{
if((response_1=="yes")||(response=='y')){
cout<<"please continue:"<<endl;
break;}
else if((response_1=="no")||(response=='n')){
cout<<"Please exit the program then:"<<endl;
}
else{
cout<<"Wrong input";
}
}
while((response_1!="yes")||(response!='y'));
}
{ do{
cout<<"Question one"<<endl<<"Can birds sing?.....";/*This statement repeats more than once.*/
cin>>response2;
if((response_2=="yes")||(response2=='y')){
cout<<"Correct they do sing"<<endl;
break;
}
else if((response_2=="no")||(response2=='n')){
cout<<"Do you want to try again?"<<endl;
}
else{
}
}
while((response_2!="yes")||(response2!='y'));
}
{ do{
cout<<"Question two now"<<endl<<"Are pigs smart?......"<<endl;/*This on also repeats moer than once*/
cin>>response3;
if((response_3=="yes")||(response3=='y')){
cout<<"Yes they are smart"<<endl;
break;
}
else if((response_3=="no")||(response3=='n')){
cout<<"Do you want to try again?"<<endl;
}
else{
}
}
while((response_3!="yes")||(response3!='y'));
}
return 0;
}
[1]: https://i.stack.imgur.com/bTnBY.jpg
You declare response as a char, but first time when you are trying to initialize it from console
cin>>response;
your input contains 3 chars ("yes" in third line of you example [1]), so responsegets 'y', but 'e' and 's' are also in the input stream now, so this is the reason, why during the next reading from console:
cin>>response2;
response2 is initialized with 'e', which causes printing of extra Can birds sing?.....Question one, afterwards 'response2' gets 's' and print extra line again.
I recommend you to delete all redundant variables and use only std::string response. It will be harder to make a mistake then.
You can add a variable that counts how many times the loop has looped
int loopCount = 0;
int LoopMaxTries = 1;
while ( loopCount < LoopMaxTries /* and possibly other stuff */ ) {
// at the end of the loop
loopCount++;
}

I have written this program for infix to postfix conversion

#include<iostream>
#include<stdio.h>
#define MAX 20
using namespace std;
char stk[MAX];
int top=-1;
void push(char c)
{
if(top==MAX-1)
cout<<"Overflow";
else
{
stk[++top]=c;
}
}
char pop()
{
if(top==-1)
{
return '\0';
}
else
return stk[top--];
}
int priority(char ch)
{
if(ch=='(')
return 1;
if(ch=='+'||ch=='-')
return 2;
if(ch=='*'||ch=='/')
return 3;
if(ch=='^')
return 4;
}
int main()
{
char exp[35],*t,x;
cout<<"Enter expression: ";
fgets(exp,35,stdin);
t=exp;
while(*t)
{
if(isalnum(*t))
cout<<*t;
else if(*t=='(')
push(*t);
else if(*t==')')
{
while((x=pop())!='(')
cout<<x;
}
else
{
if(priority(stk[top])>=priority(*t))
cout<<pop();
push(*t);
}
t++;
}
while(top!=-1)
cout<<pop();
return 0;
}
The output for input:
a+b-(c+d/e)
is
ab+cde/+
-
I don't understand why - is on a newline.
I have just started learning c++ and I am trying to implement some programs I did in c using c++. The same code in c works fine. I think there are some holes in my basic c++ knowledge and I would like to fill them up.
std::fgets does not discard the newline in the input stream like getline would. That means exp contains "a+b-(c+d/e)\n" and not "a+b-(c+d/e)". You either need to remove the newline from exp, switch to cin.getline(), or stop your processing loop when it hits the newline.
Try to change fgets to std::cin. And use std::string instead of char*:
#include <iostream>
#include <string>
int main()
{
string exp;
cout << "Enter expression: ";
std::cin >> exp;
auto t = exp.data();
char x;
for(auto &ch: exp)
{
if(isalnum(ch))
cout << ch;
else if(ch == '(')
push(ch);
else if(ch == ')')
{
while((x = pop()) != '(')
cout << x;
}
else
{
if(priority(stk[top]) >= priority(ch))
cout << pop();
push(ch);
}
}
while(top != -1)
cout << pop();
return 0;
}
In addition to the processing of '\n' as mentioned by NathanOliver, your function priority() doesn't return a value when the user entered any other character not checked in the if statements, so the behavior might be undefined.

Unable to Process Data from Text File in C++

Why is it that this program will not register the correct ID and Pin number entered?
Anything typed will proceed to wrong data being input but the correct data doesn't get recognized.
Inside the text file is 5 IDs, and 5 Pin numbers in a format of 5 rows 2 columns.
#include<iostream>
#include<iomanip>
using namespace std;
void main()
{
const int MAX=10, screenWidth=80;
string A = "Welcome to ABC Bank!";
int i=0;
int ID[MAX], Password[MAX], pin, acc, counter=1 ,limit=2;
cout<<setw((screenWidth-A.size())/2)<<" "<<A<<endl;
cout<<"\nAccount ID: ";
cin>>acc;
cout<<"Pin: ";
cin>>pin;
ifstream accountFile;
accountFile.open("AccountDetails.txt");
if (!accountFile)
cout<<"Unable to open requested file!";
else
{
while (!accountFile.eof())
{
accountFile>>ID[i]>>Password[i];
i++;
}
accountFile.close();
while (acc==ID[i] && pin==Password[i])
{
cout<<"Login successful!\n";
break;
}
while (acc!=ID[i] || pin!=Password[i])
{
if (counter==3)
{
cout<<"\nUnauthorized Access Detected. Account has been LOCKED!\n";
break;
}
else
{
cout<<"\nWrong Account ID/Pin. Please try again!"<<" (Attempts Left:"<<limit<<")";
cout<<"\nAccount ID: ";
cin>>acc;
cout<<"Pin: ";
cin>>pin;
counter++;
limit--;
}
}
}
system("pause");
}
After reviewing what #Joachim Pileborg stated in his answer earlier,
this is the updated code that I have done. Sadly, now this code fails to login successfully after the 1st attempt fails and the 2nd attempt is correct.
ifstream accountFile;
accountFile.open("AccountDetails.txt");
if (!accountFile)
cout<<"Unable to open requested file!";
else
{
while (accountFile>>ID[i]>>Password[i])
{
i++;
}
accountFile.close();
bool success = false;
for (int j=0; !success && j<i; j++)
{
if (ID[j] == acc && Password[j] == pin)
success = true;
}
if (success)
cout<<"\nLogin Successful!\n";
else
{
while (!success)
{
cout<<"\nAccount ID/Pin is incorrect. Please try again!"<<" (Attempts Left: "<<limit<<" )";
cout<<"\nAccount ID: ";
cin>>acc;
cout<<"Pin: ";
cin>>pin;
counter++;
limit--;
if (counter==3)
{
cout<<"Unauthorized Access Detected! Account Has Been LOCKED!\n";
break;
}
}
}
}
system("pause");
The logic for your login success/failure checks are flawed. To begin with they will invoke undefined behavior because you will access uninitialized elements of the arrays.
If, as you say, the file contains five entries, then after the loop i will have the value 5 which is the sixth element in the arrays (after you fix the reading loop, otherwise the value of i will be 6).
If we then overlook the UB (Undefined Behavior) the first loop, checking for successful login, that condition will most likely never be true, and that's good because otherwise you would have an infinite loop there. Then comes the second loop where you check for unsuccessful login, where the condition will almost always be true, and that will lead to an infinite loop.
To check if the login credentials given by the user was correct or not, I suggest something like
bool success = false;
for (int j = 0; !success && j < i; ++j)
{
if (ID[j] == acc && Password[j] == pin)
{
success = true;
}
}
if (success)
{
// Login successful
}
else
{
// Login failed
}
using namespace std;
int main()
{
const int MAX=10, screenWidth=80;
string A = "Welcome to ABC Bank!";
int i=0;
int ID[MAX], Password[MAX], pin, acc, counter=1 ,limit=2;
cout<<setw((screenWidth-A.size())/2)<<" "<<A<<endl;
cout<<"\nAccount ID: ";
cin>>acc;
cout<<"Pin: ";
cin>>pin;
ifstream accountFile;
accountFile.open("AccountDetails.txt");
if (!accountFile)
cout<<"Unable to open requested file!";
else
{
while (accountFile>>ID[i]>>Password[i])
{
i++;
}
accountFile.close();
bool success = false;
while (!success)
{
for (int j=0; !success && j<i; j++)
{
if (ID[j] == acc && Password[j] == pin)
success = true;
}
if (success)
cout<<"\nLogin Successful!\n";
else
{
cout<<"\nAccount ID/Pin is incorrect. Please try again!"<<" (Attempts Left: "<<limit<<" )";
cout<<"\nAccount ID: ";
cin>>acc;
cout<<"Pin: ";
cin>>pin;
counter++;
limit--;
}
if (counter==4)
{
cout<<"Unauthorized Access Detected! Account Has Been LOCKED!\n";
break;
}
}
}
system("pause");
}
CODE IS WORKING, Thank you for the input and help Mr Joachim Pileborg!

to check type of input in c++

## To check type of data entered in cpp ##
int main()
{
int num;
stack<int> numberStack;
while(1)
{
cin>>num;
if(isdigit(num))
numberStack.push(num);
else
break;
}
return(0);
}
If I declare a variable as interger, and I input an alphabet, say 'B', instead of the number, can I check this behavior of user? My code above exits when first number is entered and does not wait for more inputs.
First of all, the std::isdigit function checks if a character is a digit.
Secondly, by using the input operator >> you will make sure that the input is a number, or a state flag will be set in the std::cin object. Therefore do e.g.
while (std::cin >> num)
numberStack.push(num);
The loop will then end if there's an error, end of file, or you input something that is not a valid int.
First take your input as string
Using builtin libraries like isdigit() classify it as an integer
else if it contains '.'then its a float
else if it a alphanumerical the it is a string thats it
Code for this is below,
#include<iostream>
#include<string.h>
using namespace std;
int isint(char a[])
{
int len=strlen(a);
int minus=0;
int dsum=0;
for(int i=0;i<len;i++)
{
if(isdigit(a[i])!=0)
dsum++;
else if(a[i]=='-')
minus++;
}
if(dsum+minus==len)
return 1;
else
return 0;
}
int isfloat(char a[])
{
int len=strlen(a);
int dsum=0;
int dot=0;
int minus=0;
for(int i=0;i<len;i++)
{
if(isdigit(a[i])!=0)
{
dsum++;
}
else if(a[i]=='.')
{
dot++;
}
else if(a[i]=='-')
{
minus++;
}
}
if(dsum+dot+minus==len)
return 1;
else
return 0;
}
int main()
{
char a[100];
cin>>a;
if(isint(a)==1)
{
cout<<"This input is of type Integer";
}
else if(isfloat(a)==1)
{
cout<<"This input is of type Float";
}
else
{
cout<<"This input is of type String";
}
}
use cin.fail() to check error and clean the input buffer.
int num;
while (1) {
cin >> num;
if (cin.fail()) {
cin.clear();
cin.sync();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (num == -1) {
break;
}
numberStack.push(num);
}