Fastest way to read a file line by line with an arbitrary number of characters in each - c++

Ok, I'm trying to figure out which way would be faster to read a text file that I'm working with. The contents of the file look like this
1982 3923 3542 4343
2344 3453 2
334 423423 32432 23423
They're basically just an arbitrary number of int numbers and I need to read line by line. Would it be better to use getline or the insertion (>>) operator? I, personally, think it would be a lot easier to implement by using the insertion operator but I don't know how I would make the program so that it reads all of the int numbers in the same line until it reaches the end. I was thinking of setting it up like the following:
ifstream input;
input.open("someFile.txt");
if (input) {
char* ch;
while (ch != '\n\)
getline(input, buffer, ' ')
The only problem is that I have to do a conversion to an int, then put each int in an array. My desired end goal is to produce a two-dimensional array where each line of int's is an array of int's. Any suggestions as to the best implementation is appreciated!

I would keep it real simple:
ifstream in(...);
string line;
while (getline(in, line)) {
istringstream line_in(line);
while (line_in) {
int val = 0;
if (line_in >> val) {
// Do something with val
}
}
// eol
}

You'd have to benchmark to get a correct answer.
The speed of the two functions is implementation defined. You might get different results on different compilers.
Fastest way to do it would probably to use a custom-made finite state machine. But those are about as unreadable as you get.
Produce correct code first. Then fine tune it if you need to later.

Related

How Do I use input to pass a string into a char array from a Text File

Hey I know I can just use a string to read from a text file. However I need to use a char array. Like If I was using a string I would do this
while (!input.eof()){
input >> s;
}
I am unsure how I would go about this if I don't know the length of the string. I know I can use getLine, but I'll prefer to use input.
I'm thinking that maybe I can use a loop to check until it reaches "\0"?
Anyway I have a feeling this question has been asked before, but if it has I can't find it. So sorry if that is the case.
You can consider istream::getline. Note that it can be use for C++ string and it must have a length limit for C string.
I think you should avoid check eof directly in while condition. It only returns true it reach end-of-file. So if you have multiple line, you read it, then do some calculate, the consequence can be unexpected when it reach the end-of-file right at reading step. So the check of EOF should be placed right after reading from stream like my example.
int main()
{
ifstream input("filename.txt");
const int MAX = 10000;
char characters[MAX];
while (true) {
input.getline(characters, MAX - 1, '\n');
if (input.eof())
break;
}
}

Reading file into two arrays

I'm trying to write my own vocabulary with a test for my little brother, but I have a problem when I want to read data from file into two arrays - first with English words, and second with Polish words. File looks alike
black - czarny
red - czerwony etc.
And my function:
void VOC::readout()
{
fstream file;
VOC *arr = new VOC;
string line;
file.open("slowka.txt");
if(file.good())
{
int i=0;
while(!file.eof())
{
getline(file, line);
size_t pos = line.find(" - ");
int position = static_cast<int>(pos);
file>>arr[i].en;
file>>arr[i].pl;
++i;
}
}
}
I thought it could be a good idea to insert a line into first array until the function finds " - ", and after that insert the rest of line into second array, but I have some problems with that. Could someone help me? I know I can solve it by using std::vector but I care to do that by using arrays.
If you insist on using plain arrays, you'll first have to count the number of lines in your file and then allocate enough memory. Arrays -- unlike std::vector objects -- won't grow automatically but have a fixed size.
That being said, note that using !file.eof() is not the best way to read a stream until the end is reached. You can use the simpler
std::string line;
while (std::getline(file, line)) {
// ...
}
idiom instead, which also takes care of error conditions. See this question (and corresponding answers) for more information on that.

Is there anyway to reset the filein to the initial state?

I am trying to input data from a text file in C++.
The text file is in that format:
4 15
3 516
25 52 etc.
Each line contains two integers. I don't know the number of lines in the file so I can bind enough memory and this is what I have come into as a way to solve that:
ifstream filein;
filein.open("text.txt",ios::in);
int count=0;
while (!filein.eof())
{
count++;
filein>>temporary;
}
count=count/2; // This is the number of lines in the text file.
My problem is that I can't figure out a way to reset
filein
into the initial state (to the beggining of the file so I can actually input the data) other than closing the input stream and opening it again. Is there any other way to do that?
Rather than answer the question you asked, I'm going to answer the question you didn't ask, namely:
Q: How can I read in all the lines of the file if I don't know how many lines there are?
A: Use a std::vector<>.
If you want to read in all of the numbers, regardless of pairing:
// all code fragments untested. typos are possible
int i;
std::vector<int> all_of_the_values;
while(filein >> i)
all_of_the_values.push_back(i);
If you want to read in all of the numbers, putting alternating numbers into different data structures:
int i, j;
std::vector<int> first_values;
std::vector<int> second_values;
while(filein >> i >> j) {
first_values.push_back(i);
second_values.push_back(j);
If you want to read in all of the numbers, storing them in some sort of data structure:
int i, j;
struct S {int i; int j;};
std::vector<S> values;
while(filein >> i >> j) {
S s = {i, j};
values.push_back(s);
}
Finally, if you want to read the file a line at a time, keeping the first two numbers from each line, discarding the remainder of each line, and storing them a user-defined data structure:
std::vector<MyClass> v;
std::string sline;
while(std::getline(filein, sline)) {
std::istringstream isline(sline);
int i, j;
if(isline >> i >> j) {
values.push_back(MyClass(i, j));
}
}
Aside: never use eof() or good() in a loop conditional. Doing so almost always produces buggy code, as it would have in your case. Instead prefer invoking the input function in the condition, as I have done above.
I think #Robᵩ has pretty much the right idea -- instead of reading through all the data just to count the number of lines, then reading through the whole file again to actually read the data, using something like std::vector (or std::deque) that will expand as needed as you read the data.
In a typical case, however, the two numbers on a line are going to be related to each other, and you typically want to store them in a way that shows that association directly. For example, they might be the X and Y coordinates of points, in which case you want to read points:
class point {
int x, y;
};
std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
std::ifstream in("myfile.txt");
// create the vector from the data in the file:
std::vector<point> points((std::istream_iterator<point>(in)),
std::istream_iterator<point>());
On a slightly different note: even if you decide you want to use an explicit loop, please don't use while (!whatever.eof()) to do it -- that's pretty much guaranteed to fail. You want to check that reading data succeeded, so (for example) using the point class above, you could use something like:
point p;
while (infile >> p)
points.push_back(p);
The function is: filein.seekg (0, ios::beg);
Here is a Reference
You should also use filein.clear() to reset the eof bit in the file if you do it this way.
And, of course, if you want the best method for what you are ultimately trying to do, Robᵩ's answer is much better, albeit more involved.

Read number of lines, words, characters from a file

I can read the number of lines easy, using:
ifstream in(file);
string content;
while(getline(in, content))
{
// do stuff
}
Or I can read the number of words and characters easy using something like:
ifstream in(file)
string content;
int numOfCharacters = 0;
int numOfWords = 0;
while(in >> content)
{
++numOfWords;
numOfCharacters += content.size();
}
But I dont want to read the file twice. How can I read the file once, and find out the number of lines, words and characters?
PS: I would welcome a Boost sugestion, if there is a easy way.
Thank you.
Read the line and for each line count the words. See stringstream for the second part.
(I'm not giving more information, that looks too much like an homework).
This could be done with a trivial boost.spirit.qi parser.
Sticking with the iostreams solution: you could create a strstream out of each line read via getline(), and do the word/char counting operations on it, accumulating across all the lines.

Reading input into dynamically-sized array

What I've been trying to do, is read a line from stdin and split it, by using whitespace as seperators.
Let's say I have this as input:
2
1 2
3 4
The first line gives me the amount of lines I'd like to read, they're all lines with integers seperated by an unknown amount of whitespace (i.e. could be 1 space, but it could also be 10 spaces).
The thing I've been trying to do is reading those lines into dynamically sized arrays of integers.
This was extremely easy in Python:
foo = raw_input()
array = foo.split()
or even shorter:
foo = raw_input().split()
However, because of the circumstances, I have to learn the beauty of C++.
So I tried to create something akin to the above Python code:
#include <iostream>
using namespace std;
int lines;
int *array;
int main() {
cin >> lines;
for (int line = 0; line < lines; line++) {
// Something.
}
}
I don't seem to know a way to split the line of input. I know that std::cin reads until it reaches a whitespace. However, I can't seem to think of something to count the amount of numbers on the line...
A little nudge into the right direction would be appreciated, thanks.
so given all you wanted is a nudge, here are a couple of hints..
std::getline() - allows you to read from a stream into a std::string.
You can then construct a std::istringstream using this string which you've just read in. Then use this stream to read your ints
for example:
std::string line;
if(std::getline(std::cin, line))
{
std::istringstream str(line);
int lc;
if (str >> lc) // now you have the line count..
{
// now use the same technique above
}
}
oh and for your "dynamically sized array", you need to look at std::vector<>
In C++ you can access characters in a string with [], just as if that string were an array. I suggest you read a line from cin into a string, iterate over the string with a for loop and check each character to see whether it is whitespace. Whenever you find a non-whitespace character, store it in your array.