Scott
Scott

Reputation: 11

Reading a txt file

For my project I have to overwrite the operator>> method to read in an array of numbers from a text file. This is my first time doing any of this and I am pretty lost. My code so far looks like this.

std::istream& operator>>(std::istream& in, bigint array){

          bool semi = false ;

          while(!semi){
            if(get() = ';')
              semi = true ;
            in <<get();
          }
        return in ;
     }

And the file looks like this.

10000000000000000000000000000000000345;
299793000000
00000000000000000000067;
4208574289572473098273498723475;
28375039287459832728745982734509872340985729384750928734590827098752938723;
99999999;  99999999;

Each new array stops when it hits a ";'. The white spaces and endlines are confusing me too. Any help would be appreciated thank you.

Upvotes: 0

Views: 134

Answers (2)

john
john

Reputation: 88017

There's quite a lot of confusions here. I'll just list some points, but you have a way to go even if you fix these things.

  1. What exactly are you reading? You say you are reading an array of numbers, but your code says this

    std::istream& operator>>(std::istream& in, bigint array){
    

    I might be wrong but bigint sounds like a single number to me. I would expect something like this

    std::istream& operator>>(std::istream& in, std::vector<bigint>& array){
    
  2. Which brings me to the second point, operator>> is expected to modify it's second argument, which means it cannot be passed by value, you must use a reference. In other words this is wrong

    std::istream& operator>>(std::istream& in, X x){
    

    but this is OK

    std::istream& operator>>(std::istream& in, X& x){
    
  3. You are trying to read an array of bigints, so you need a loop (you have that) and each time round the loop you will read one bigint. So you need a way to read one bigint, do you have that? There nothing in your question or your code that indicates you have the ability to read a bigint, but it's obviously crucial that you do. So if you do not have any code yet to read a bigint, you can forget about this whole exercise until you have that code, so work on that first. When you can read one bigint, only then should you come back to the problem of reading an array of bigints.

  4. The other tricky part is the stopping condition, you stop when you read a semi-colon (possibly preceded by whitespace). So you need a way to read the next non-space character, and crucially you need a way to unread it if it turns out not to be a semicolon. So you need something like this

    if (!(in >> ch) || ch == ';')
    {
         // quit, either no more input, or the next char is a semicolon
         break;
    }
    
    in.putback(ch); // unread the last char read
    // read the next bigint
    

Hope this helps.

Upvotes: 2

sehe
sehe

Reputation: 393769

You will want to use

bigint& array

to take the value by reference (or you couldn't possibly insert the digits read into it).

Also, you will want to use

char ch;
in >> ch;

instead of in << get() (which doesn't compile). Better yet, add error handling:

if (!(in >> ch))
{
    // we're in trouble (in.rdstate(), in.eof(), in.fail() or in.bad() to know more)
}

If you wanted to use in.get(), you should be prepared to skip your own whitespace (including newlines). I'd prefer std::istream_iterator here, because it will automatically do so (if the std::ios::skipws flag is in effect, which it is, by default).

So here's a simplist approach (that mostly assumes input data is valid and whitespace ignorable):

#include <vector>
#include <istream>
#include <iterator>

struct bigint
{
    std::vector<char> v; // or whatever representation you use (binary? bcd?)
};

std::istream& operator>>(std::istream& in, bigint& array)
{
    for (std::istream_iterator<char> f(in), l; f != l; ++f) {
        if (*f>='0' && *f<='9')
            array.v.push_back(*f - '0');
        else if (*f==';')
            break;
        else
            throw "invalid input";
    }

    return in;
}

#include <iostream>
#include <sstream>

int main()
{
    std::istringstream iss(
            "10000000000000000000000000000000000345;\n"
            "299793000000\n"
            "00000000000000000000067;\n"
            "4208574289572473098273498723475;\n"
            "28375039287459832728745982734509872340985729384750928734590827098752938723;\n"
            "99999999;  99999999;\n");

    bigint value;
    while (value.v.clear(), iss >> value)
        std::cout << "read " << value.v.size() << " digits\n";
}

See it Live on Coliru

Upvotes: 2

Related Questions