Reputation: 157
So i'd like to read numbers from a .txt file as integers.
file.txt:
hello 123-abc
world 456-def
current code:
int number;
ifstream file("file.txt");
while (!file.eof())
{
file >> number; //123, 456
}
Now this obviously doesnt work and ive been trying to solve this for a "while" but i just can not get around this.
Upvotes: 4
Views: 2120
Reputation: 15524
Read line by line and remove all chars that are not digits. Finish with a std::stoi
before pushing to your std::vector
.
std::ifstream file{"file.txt"};
std::vector<int> numbers;
for (std::string s; std::getline(file, s);) {
s.erase(std::remove_if(std::begin(s), std::end(s),
[] (char c) { return !::isdigit(c); }), std::end(s));
numbers.push_back(std::stoi(s));
}
Alternatively use std::regex_replace
to remove non-digit chars:
auto tmp = std::regex_replace(s, std::regex{R"raw([^\d]+(\d+).+)raw"}, "$1");
numbers.push_back(std::stoi(tmp));
Upvotes: 0
Reputation: 63451
There are a number of ways you could do this. The method you've tried doesn't work because there is no number-like thing sitting at the read position in the stream. So the input will fail, and the stream's fail-bit will be set. You'll loop forever because you're only testing for eof. Read this for more information.
A simple way is to read a line at a time, and search for the first number by exploiting the second argument to std::strtol
:
#include <iostream>
#include <string>
#include <experimental/optional>
std::experimental::optional<int> find_int_strtol( const std::string & s )
{
for( const char *p = s.c_str(); *p != '\0'; p++ )
{
char *next;
int value = std::strtol( p, &next, 10 );
if( next != p ) {
return value;
}
}
return {};
}
int main()
{
for( std::string line; std::getline( std::cin, line ); )
{
auto n = find_int_strtol( line );
if( n )
{
std::cout << "Got " << n.value() << " in " << line << std::endl;
}
}
return 0;
}
This is a bit clunky and it will also detect negatives, which you might not want. But it's a simple approach. The next
pointer will be different to p
if any characters were extracted. Otherwise the function fails. Then you increment p
by 1 and search again. It looks like a polynomial search, but it's linear.
I've used std::optional
from C++17, but I was testing on a C++14 compiler. It's for convenience. You could write the function without it.
Live example is here.
A more flexible way to solve problems like this is to use a regular expression. In this case, a simple numeric regex search is all you need. The following will only find positive integers, but you can use this type of pattern to find complex data too. Don't forget to include the header <regex>
:
std::experimental::optional<int> find_int_regex( const std::string & s )
{
static const std::regex r( "(\\d+)" );
std::smatch match;
if( std::regex_search( s.begin(), s.end(), match, r ) )
{
return std::stoi( match[1] );
}
return {};
}
Live example is here.
Upvotes: 1
Reputation: 708
You need to check if the file is open, then get the current line, then parse that current line to get the first number:
std::string currentLine = "";
std::string numbers = "";
ifstream file("file.txt");
if(file.is_open())
{
while(std::getline(file, currentLine))
{
int index = currentLine.find_first_of(' '); // look for the first space
numbers = currentLine.substr(index + 1, xyz);
}
}
xyz is the length of numbers ( 3 in this case if always constant ) or you can look for the next blank space by getting a substring from (index, currentLine.back() - index);
I'm sure you can figure out the rest, good luck.
Upvotes: 0