Reputation: 27
Hello can someone tell me how can i get only value of total sum of notes (1x20 ;10x50 ,100x50 = total 111 notes) from input text file?
I try something with line.find()
but when i have two/three-digit number like 10 x 50 USD ,100 x 50 USD it gave me error:
Unhandled exception exception: std::out_of_range at memory location 0x005FDB1C
Here is the code
int total=0;
string str2="USD";
std::ifstream file("input.txt");
if (file.is_open()) {
std::string line;
while (getline(file, line)) {
if (line.find(str2) != string::npos) {
cout << line.substr((line.find("USD")-7))<< '\n';
int d = stoi(line.substr((line.find(" x")- 1)));
total = total + d;
cout << "Total sum: " << total;
}
}
file.close();
}
Input file:
===============================
DATE: 20190929 TIME: 13:55:24
MY ID: mypc
===============================
Client: 1234
DATE: 2019.09.17 TIME: 14:19:14
0 x 0 USD
1 x 20 USD
Client: 4567
DATE: 2019.09.17 TIME: 14:21:33
0 x 0 USD
10 x 50 USD
Client: 8910
DATE: 2019.09.17 TIME: 14:34:25
0 x 0 USD
100 x 50 USD
===============================
Upvotes: 1
Views: 192
Reputation: 28251
Here is how you could implement the parsing using C++ regular expressions:
#include <regex>
...
while (std::getline(file, line)) {
std::smatch match;
if (std::regex_match(line, match, std::regex("\\s*([0-9]+) x ([0-9]+) USD\\s*"))) {
int number_of_notes = std::stoi(match[1]);
int value = std::stoi(match[2]);
total += number_of_notes * value;
std::cout << "Total sum: "<< total << std::endl;
}
}
Here match
is an object which stores the result of the parsing.
A breakdown of the regular expression:
\s*
- allows leading and trailing spaces([0-9]+)
- captures (using parentheses) a sequence of 1 or more digits into the match
objectx
, and USD
- requires the input to have these; only those input lines which have this text will match the regexIf you use regular expressions, it might be easier to adapt your code if you ever decide to upgrade your input file format - ideally, you would only need to change the regex, not the code.
Upvotes: 0
Reputation: 409196
One possible way is to save the position you get from line.find(str2)
in a variable. Then create a substring from the beginning of the line to that position:
auto usd_pos = line.find(str2);
if (usd_pos != std::string::npos)
{
auto value_string = line.substr(0, usd_pos);
...
}
Once you got the substring with the numbers in it, put it into an input string stream (std::istringstream
) and read the integers and the 'x'
from that stream:
int first_value, second_value;
char dummy_x_char;
std::istringstream stream_with_values(value_string);
stream_with_values >> first_value >> dummy_x_char >> second_value;
Upvotes: 1
Reputation: 2070
Parsing string using absolute position is error prone.
When you have token separated value (especially if the tokens are whitespace) that you need to store into typed variable, it is easier to use streams (such as std::stringstream
).
This is one way to do it :
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main() {
int total=0;
std::string str2="USD";
std::ifstream file("input.txt");
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
if (line.find(str2) != std::string::npos) {
std::stringstream ss(line);
int number_of_notes, value;
std::string operatorX, USD_string;
ss >> number_of_notes>> operatorX >> value >> USD_string;
total += number_of_notes;
std::cout << "Total sum: "<< total << std::endl;
}
}
file.close();
}
}
Upvotes: 1