I was solving ArithmaticII. I am getting the correct output for the below input:
4
1 + 1 * 2 =
29 / 5 =
103 * 103 * 5 =
50 * 40 * 250 + 791 =
Output:
4
5
53045
500791
I am getting the correct output, but when I submit my solution to spoj, I
get a SIGABRT runtime error.
Note: It may also contain spaces to improve readability.
Since the input might not contain spaces, how can I handle that, because that is giving me error.
because my program stops (runtime error) when I don't provide
space in the input (1 * 1+2=)
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoll
Please help. What should I do?
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
int t;
string str;
cin >> t;
while (t--) {
///using cin.ignore() as input as preceded by a single line
cin.ignore();
getline(cin, str, '\n');
stringstream split(str);
///now use getline with specified delimeter to split string stream
string intermediate;
int flag = 0;
long long int ans=1;
while (getline(split, intermediate, ' ')) {
if (intermediate == "=") {
cout << ans<<"\n";
break;
}
if (intermediate == "*") {
flag = 1;
continue;
}
else if (intermediate == "/") {
flag = 2;
continue;
}
else if (intermediate == "+") {
flag = 3;
continue;
}
else if(intermediate == "-"){
flag = 4;
continue;
}
if (flag == 1) {
ans *= stoll(intermediate);
}
else if (flag == 2) {
ans /= stoll(intermediate);
}
else if (flag == 3) {
ans += stoll(intermediate);
}
else if (flag == 4) {
ans -= stoll(intermediate);
}
else if (flag == 0) {
ans = stoll(intermediate);
}
}
}
}
Take input one line at a time.
Put the first number into ans.
Then loop through the rest of the string chararcter by character.
If the character is an arithmatic operator ('*' or '+' or '/' or '-') then there will be a number after it.extract the number and perform specified operation.
If the character is '=' print the answer.
Hint:how to extract a number?
1.the first number starts from beginning and goes till the first arithmatic operator.
2. All other numbers are between arithmatic operators or '='.
Related
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 2 years ago.
Given an expression string exp. Examine whether the pairs and the orders of “{“,”}”,”(“,”)”,”[“,”]” are correct in exp.
For example, the program should print 'balanced' for exp = “[()]{}{[()()]()}” and 'not balanced' for exp = “[(])”
Input
The first line of input contains an integer T denoting the number of test cases. Each test case consists of a string of expression, in a separate line.
Output
Print 'balanced' without quotes if the pair of parenthesis is balanced else print 'not balanced' in a separate line.
Constraints
1 ≤ T ≤ 100
1 ≤ |s| ≤ 105
Example
Input:
3
{([])}
()
([]
Output
balanced
balanced
not balanced
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
int main() {
//code
int t;cin>>t;
while(t--) {
string s;
stack<char> st;
int i=0,flag =1;
getline(cin,s);
int n = s.size();
while(s[i] != '\0') {
if((s[i] == '{') || (s[i] == '[') || (s[i] == '(')) {
st.push(s[i]);
}
else if(!st.empty() && ((st.top() == '{' && s[i] == '}') ||
(st.top() == '[' && s[i] == ']') || (st.top() == '(' && s[i] == ')'))) st.pop();
else {
flag = 0;
break;
}
i++;
}
(st.empty() && flag) ? cout<<"balanced\n" : cout<<"not balanced\n";
}
return 0;
}
Stepping through your code with a debugger, the first time through the loop your string is empty.
This is because cin >> t stops reading at the newline character of the first line, and the first getline(cin, s) line receives an empty string.
Simply call getline(cin, dummy_string) after cin >> t to read the rest of the line, or switch your loop to use cin >> s instead.
I was solving ArithmaticII.I am getting correct output for the below input
Input:
4
1 + 1 * 2 =
29 / 5 =
103 * 103 * 5 =
50 * 40 * 250 + 791 =
Output:
4
5
53045
500791
I am getting correct output ,But when i am submitting my solution to spoj , I
am getting runtime error as SIGABRT ,Due to the overflow issue I am using stoll,When i tried to debug my program everything was seemed to be running fine .
Note->It may also contain spaces to improve readability.
This line looks suspicious to me because my programs stops(runtime error) when i doesn't provide
space in the input (1 * 1+2=)
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoll
Please help where I am doing wrong?
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
int t;
string str;
cin >> t;
while (t--) {
///using cin.ignore() as input as preceded by a single line
cin.ignore();
getline(cin, str, '\n');
stringstream split(str);
///now use getline with specified delimeter to split string stream
string intermediate;
int flag = 0;
long long int ans=1;
while (getline(split, intermediate, ' ')) {
if (intermediate == "=") {
cout << ans<<"\n";
break;
}
if (intermediate == "*") {
flag = 1;
continue;
}
else if (intermediate == "/") {
flag = 2;
continue;
}
else if (intermediate == "+") {
flag = 3;
continue;
}
else if(intermediate == "-"){
flag = 4;
continue;
}
if (flag == 1) {
ans *= stoll(intermediate);
}
else if (flag == 2) {
ans /= stoll(intermediate);
}
else if (flag == 3) {
ans += stoll(intermediate);
}
else if (flag == 4) {
ans -= stoll(intermediate);
}
else if (flag == 0) {
ans = stoll(intermediate);
}
}
}
}
Using exactly the input you posted above:
4
1 + 1 * 2 =
29 / 5 =
103 * 103 * 5 =
50 * 40 * 250 + 791 =
I'm able to reproduce your error:
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoll
Aborted
I'll bet you removed the newlines in the sample input to simplify things--that's what it looks like from your code anyways. You're doing a getline and pulling exactly as many lines as you're told in the first input. That means you'll pull an empty line (intermediate will be an empty string) and you'll try to process it.
And what happens when you try to call stoll("")? The error you got!
You could try to check if you get an empty line and then continue, something like:
getline(cin, str, '\n');
if(str.empty()) {
t++; //we didn't actually do anything, so increment t
continue;
}
stringstream split(str);
...
Or, you could use the fact that the >> operator already stops when it hits whitespace (and eats all the whitespace it can to get to the next edible character). So instead of reading a line at a time, you could continue reading until you hit a = character.
cin >> t; does not eat the newline character after reading the number 4 from the input. As the program enters the loop cin.ignore() finishes the first line of the input and then getline(...) reads a blank line. You get an empty string which cannot be converted to an int.
Putting one more cin.ignore() after reading t fixes the runtime error.
You still have to handle the case when there are no spaces between the tokens. This requires rethinking the inner while loop:
long long int ans;
char op;
split >> ans;
while (split >> skipws >> op) {
if (op == '=') {
cout << ans << '\n';
break;
}
long long int n;
split >> n;
if (op == '*')
ans *= n;
else if (op == '/')
ans /= n;
else if (op == '+')
ans += n;
else if(op == '-')
ans -= n;
}
If i want an integer input, but if it contains any digits 2 or 3 in it, it will be rejected.
For example entering 23564 will be invalid.
I was thinking of using do-while loops to solve this, but how do I get it to read the individual digits.
Have a look here:
#include <iostream>
using namespace std;
int main() {
int n,num,flag;
do{
cout<<"Enter number";
cin>>n;
num = n;
flag = 0;
while(num>0)
{
if(num%10 == 2 || num%10 ==3)
{
flag = 1;
break;
}
num = num/10;
}
}while(flag==1);
return 0;
}
If you don't care much about performance, you can convert the integer into a string and look for the digits. This is slower than extracting the last digit and comparing it though.
std::string str = std::to_string(number);
auto found2 = str.find('2');
auto found3 = str.find('3');
//number is valid if it doesn't have a 2 or a 3
bool isValid = found2 == std::string::npos && found3 == std::string::npos;
You can get the last digit of a number with something like:
unsigned int number = 23456;
unsigned int digit = number % 10; // gives 6
You can further "shift" all digits right with:
number = number / 10; // gives 2345
In other words, yes, you can do it using the method you propose:
bool has2Or3(unsigned int number) {
// Do until no more digits left.
while (number != 0) {
// Get last digit, return true if 2 or 3.
int digit = number % 10;
if ((digit == 2) || (digit == 3)) {
return true;
}
// Prepare to get next digit.
number = number / 10;
}
// If NO digits were 2 or 3, return false.
return false;
}
Another way would be to simply convert it to a string and use the string functions to see if it contains a specific digit, something such as:
bool has2Or3(unsigned int number) {
// Get number as string (via string stream).
std::stringstream ss;
ss << number;
std::string s = ss.str();
// If contains 2, return true, else continue.
if (s.find("2") != std::string::npos)
return true;
// If contains 3, return true, else return false.
return (s.find("3") != std::string::npos);
}
Instead of reading the input directly into an integer type, read it into a std::string. Then it's simple to check for unwanted digits; if the string passes the test, convert it to an integer:
int get_value() {
std::string bad = "23";
std::string input = "2"; // start with bad input
while (std::find_first_of(input.begin(), input.end(),
bad.begin(), bad.end()) != input.end()) {
std::cout << "Gimme a number: ";
std::cin >> input;
}
return std::stoi(input);
}
So I have a data file that looks something like this:
x + y + z
30 45 50
10 20 30
The only characters I needed was the operators, so '+' '+' I was able to use file.get() to successfully get those characters and put them in an array. Problem is I need to get the next line of numbers, and assign them to the values x , y z . I know I cant use .get() , I would have to use getline. Will i have to eliminate the file.get() and use getline instead for first part also?
I looked at some of the questions posted on here but none of them were quite like mines. Note I'm actually going to be using these values for another part of my program, just used cout to see if my values were being read correctly
Here's my previous code:
main(int argc, char *argv[])
{
int a=0;
int n;
fstream datafile;
char ch;
pid_t pid;
int a, b, c, result;
string line;
datafile.open("data1.txt");
if(datafile)
{
for(int i=0; i <9; i++)
{
datafile.get(ch);
if (ch == '*'||ch == '/'||ch == '+'||ch == '-')
{
operations[a] = ch;
cout<<operations[a];
a++;
}
}
}
else
cout<<"Error reading file";
}
So this is how I was getting the first line of the file in the beginning. It worked like I wanted it to, may have not been the nicest coding but it worked. Nevertheless I tried to get the rest of the file, this time using getline, but instead of getting the numbers I was getting a bunch of random gibberish/numbers. I know if I use getline, the first line cannot be in my loop. I know this is how I would get the numbers.
while(getline(datafile, line))
{
istringstream ss(line);
ss >> x >> y >> z;
cout<<x<<""<<y<<""<<z;
}
Would the following make sense for the first line, or am I missing something:
string input;
std::getline(datafile, input)
for (int i = 0; i < input.size(); i++)
if (input[i] == '+' || ...)
{
operations[a] = input[i];
a++;
}
If you don't want to use getline, you could simply read the entire file stream (note that the bool is a rather naive way to handle the problem, I'd recommend something more elegant in your actual code):
bool first = true;
string nums;
int lines = 0;
vector<vector<int>> numlines;
vector<int> topush;
while (!datafile.eof())
{
char ch = datafile.get()
if (ch == 12 && first) //I don't know if '\n' is valid, I'd assume it is but here's the sure bet
first = false;
else if (first && (ch == '+' || ...))
{
operator[a] = ch;
a++;
}
else if (!first && (ch >= '0' && ch <= '9'))
{
if (!(datafile.peek() >= '0' && datafile.peek() <= '0'))
{
numlines[lines].push_back(atoi(nums.c_str());
nums.clear();
if (datafile.peek() == 12)
{
numlines.push_back(topush);
lines++;
}
}
else
nums = nums + ch;
}
Honestly, I can't be sure the above will work exactly right, I'd recommend you just modify your code to use getline exclusively. You'll need to add #include to get atoi.
Add this to your code:
while(!datafile.eof()){
string s;
getline(datafile, s);
istringstream in(s);
string tmp;
while(in >> tmp){
int i = stoi(tmp)
//Do something with i....
}
}
given a string say " a 19 b c d 20", how do I test to see if at that particular position on the string there is a number? (not just the character '1' but the whole number '19' and '20').
char s[80];
strcpy(s,"a 19 b c d 20");
int i=0;
int num=0;
int digit=0;
for (i =0;i<strlen(s);i++){
if ((s[i] <= '9') && (s[i] >= '0')){ //how do i test for the whole integer value not just a digit
//if number then convert to integer
digit = s[i]-48;
num = num*10+digit;
}
if (s[i] == ' '){
break; //is this correct here? do nothing
}
if (s[i] == 'a'){
//copy into a temp char
}
}
These are C solutions:
Are you just trying to parse the numbers out of the string? Then you can just walk the string using strtol().
long num = 0;
char *endptr = NULL;
while (*s) {
num = strtol(s, &endptr, 10);
if (endptr == s) { // Not a number here, move on.
s++;
continue;
}
// Found a number and it is in num. Move to next location.
s = endptr;
// Do something with num.
}
If you have a specific location and number to check for you can still do something similar.
For example: Is '19' at position 10?
int pos = 10;
int value = 19;
if (pos >= strlen(s))
return false;
if (value == strtol(s + pos, &endptr, 10) && endptr != s + pos)
return true;
return false;
Are you trying to parse out the numbers without using any library routines?
Note: I haven't tested this...
int num=0;
int sign=1;
while (*s) {
// This could be done with an if, too.
switch (*s) {
case '-':
sign = -1;
case '+':
s++;
if (*s < '0' || *s > '9') {
sign = 1;
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// Parse number, start with zero.
num = 0;
do {
num = (num * 10) + (*s - '0');
s++;
} while (*s >= '0' && *s <= '9');
num *= sign;
// Restore sign, just in case
sign = 1;
// Do something with num.
break;
default:
// Not a number
s++;
}
}
It seems like you want to parse the string and extract all the numbers from it; if so, here's a more "C++" way to do it:
string s = "a 19 b c d 20"; // your char array will work fine here too
istringstream buffer(s);
string token;
int num;
while (!buffer.eof())
{
buffer >> num; // Try to read a number
if (!buffer.fail()) { // if it doesn't work, failbit is set
cout << num << endl; // It's a number, do what you want here
} else {
buffer.clear(); // wasn't a number, clear the failbit
buffer >> token; // pull out the non-numeric token
}
}
This should print out the following:
19
20
The stream extraction operator pulls out space-delimited tokens automatically, so you're saved from having to do any messy character-level operations or manual integer conversion. You'll need to #include <sstream> for the stringstream class.
You can use atoi().
after your if you need to shift to while to collect subqsequent digits until you hit a non-digit.
BUT, more inportantly, have you clearly defined your requirements? Will you allow whitespace between the digits? What if there are two numbers, like abc123def456gh?
Its not very clear what you are looking for.. Assuming you want to extract all the digits from a string and then from a whole number from the found digits you can try the following:
int i;
unsigned long num=0; // to hold the whole number.
int digit;
for (i =0;i<s[i];i++){
// see if the ith char is a digit..if yes extract consecutive digits
while(isdigit(s[i])) {
num = num * 10 + (s[i] - '0');
i++;
}
}
It is assumed that all the digits in your string when concatenated to from the whole number will not overflow the long data type.
There's no way to test for a whole number. Writing a lexer, as you've done is one way to go. Another would be to try and use the C standard library's strtoul function (or some similar function depending on whether the string has floating point numbers etc).
Your code needs to allow for whitespaces and you can use the C library's isdigit to test if the current character is a digit or not:
vector<int> parse(string const& s) {
vector<int> vi;
for (size_t i = 0; i < s.length();) {
while (::isspace((unsigned char)s[ i ]) i++;
if (::isdigit((unsigned char)s[ i ])) {
int num = s[ i ] - '0';
while (::isdigit((unsigned char)s[ i ])) {
num = num * 10 + (s[ i ] - '0');
++i;
}
vi.push_back(num);
}
....
Another approach will be to use boost::lexical_cast:
vector<string> tokenize(string const& input) {
vector<string> tokens;
size_t off = 0, start = 0;
while ((off = input.find(' ', start)) != string::npos) {
tokens.push_back(input.substr(start, off-start));
start = off + 1;
}
return tokens;
}
vector<int> getint(vector<string> tokens) {
vector<int> vi;
for (vector<string> b = tokens.begin(), e = tokens.end(); b! = e; ++b) {
try
{
tokens.push_back(lexical_cast<short>(*b));
}
catch(bad_lexical_cast &) {}
}
return vi;
}