0

I'm trying to implement a function that reads a column of data from a text file and stores it in a vector, which works. However when I try to implement it inside of a class I'm clearly missing some step. This causes the terminal to output the following message:

Outout for

error: member reference base type
      'ifstream (string)' is not a structure or union
                ...

error: member reference base type
      'ifstream (string)' is not a structure or union
                while(!file.eof()){
                ..
error: invalid operands to binary
      expression ('ifstream (*)(string)' and 'double')
                        file >> line;

In my class I try to implement the following function to be used with it's data members:

#include <iostream>
#include <vector>
#include <stdio.h>
#include <fstream> 

using namespace std;

class spectData{
public:
    vector<double> x, y, z;
    vector< int> A;
    vector<double> readVector(string){
        ifstream file(string);
        double line;
        vector<double> a;

        if(file.fail()){
            cout << "-----------------\n";
            cout << "Input file error!\n";
        }
        while(!file.eof()){
            file >> line;
            a.push_back(line);
        }
        return a;
    };
};

Any hint as to why this wouldn't work inside a function, but would inside main function?

Iancovici
  • 4,946
  • 6
  • 33
  • 54

4 Answers4

6
using namespace std;  
...
vector<double> readVector(string){
//                        ~~~~~~^
//                        missing parameter name
    ifstream file(string);
//                ~~~~~^
//                whoops, type name aka std::string instead of parameter name

What your ifstream file(string); currently does, it declares a function file that takes by value a parameter of the std::string type and returns the std::ifstream instance. Hence the error you get. What you probably meant to do is to supply a path parameter to your file's constructor:

vector<double> readVector(const string& path){
//                        ~~~~~~~~~~~~~~~~~^
//                        parameter name
    ifstream file(path.c_str());
//                ~~~^ ~~~~~~^
//                 
Piotr Skotnicki
  • 43,267
  • 7
  • 101
  • 142
5

The issues in this code are numerous, including:

  • Failing to include <string>. Don't rely on another header to do that for you.
  • Invalid parameter naming (as in, you have none; remember parameters are Type name).
  • Building on the mistake from above, ifstream file(string); therefore declares a function called file that takes a string parameter and returns an ifstream (which is impossible, as that class does not support copy construction, but does support move construction, not that it matters here).
  • Using .eof() as a loop condition, which is nearly always wrong (and this is no exception). Read this for why.
  • Minor: Reinventing the iterative read operation. std::istream_iterator provides this functionality for you, and should be exploited.
  • Minor: blanketing this with using namespace std;

For example:

#include <iostream>
#include <fstream> 
#include <string>
#include <vector>
#include <iterator>

class spectate
{
public:
    std::vector<double> x, y, z;
    std::vector< int> A;

    std::vector<double> readVector(const std::string& fname)
    {
        std::vector<double> res;

        std::ifstream file(fname);
        if(!file)
        {
            std::cout << "-----------------\n";
            std::cout << "Input file error!\n";
        }
        else
        {   // dump the file of doubles into your vector
            std::copy(std::istream_iterator<double>(file),
                      std::istream_iterator<double>(),
                      std::back_inserter(res));
        }
        return res;
    }
};

Truth be told, you can forego much of that if error reporting is handled by the caller (such as an empty file, vector, etc), at which point that entire member can be reduced to simply:

std::vector<double> readVector(const std::string& fname)
{
    std::ifstream file(fname);
    return std::vector<double> {
        std::istream_iterator<double>(file),
        std::istream_iterator<double>() };
}

It somewhat brings into question whether the function is truly even needed at all. The caller could just as easily have done this entirely on their side.

Community
  • 1
  • 1
WhozCraig
  • 59,130
  • 9
  • 69
  • 128
2

string is a typename that you've pulled in inadvertently via the using namespace std. As a result, file is not what you intended - it is a function taking a std::string and returning an std::ifstream. Avoid using namespace std except in very controlled scopes - definitely not in header files.

sfjac
  • 6,386
  • 4
  • 42
  • 62
1

#include <vector> does includes std::string. After using namespace std; std::string becomes type string so you cant use string as variable name because it is a type.

You should write using std::vector; instead of using namespace std;

Teivaz
  • 4,616
  • 4
  • 25
  • 63