-1

Currently migrating one of my program from Matlab to C++, I am experiencing a difficulty in reading a file.csv and look for assistance for my understanding.

struct nav {
std::string title;
... // I have 17 members but for simplicity purposes I am only disclosing
   // two of them
float quant;
};
nav port[];
std::string filedir = "C:\\local\\";
std::string fdbdir = filedir + "Factor\\";
std::string extension1 = "fdb.csv";
std::string extension2 = "nav.csv";
std::string factorpath = fdbdir + extension1;
std::string factorpath2 = filedir + extension2;
std::ifstream fdbdata(factorpath);
std::ifstream navdata(factorpath2);

int main() {

// 2nd data file involving data of different types
    {       

    navdata.open(factorpath2);
    if (navdata.fail()) {
        std::cout << "Error:: nav data not found." << std::endl;
        exit(-1);
    }

    for (int index = 0; index < 5; index++)
    {
        std::getline(navdata, port[index].title, ',');
        std::getline(navdata, port[index].quant, ',');
    }

    for (int index = 0; index < 4; index++)
    {
        std::cout << port[index].title << " " << port[index].quant << 
    std::endl;
    }

    }
}

Error: LNK2001: unresolved external symbol "struct nav * port" (?port@@3PAUnav@@A)

From the Error list, there is certainly something wrong with the declaration of the struct type port that I'd like to know.

Most importantly: Is there a way of not hard-coding index as the dimension of the data is not fixed. I've used for (int index = 0; index < 4; index++) for testing purposes, but index could be any integer as 50,200, etc.

EDIT:

As requested, please find below the minimal example:

struct Identity {
int ID;
std::string name;
std::string surname;
float grade;    
};

std::string filedir = "C:\\local\\";
std::string extension = "sample.csv";
std::string samplepath = filedir + extension;

int main() {

std::ifstream test(samplepath);
std::vector<Identity> iden;
Identity i;
while (test >> i.ID >> i.name >> i.surname >> i.grade)
{
iden.push_back(i); 
}
std::cout << iden[1].name;
system("pause");
}

resulting in vector subscript out of range. Any idea of what looks wrong here?

Also the below sample data as requested: ps: the point header should be read grade for consistency purposes.

enter image description here

Best,

owner
  • 723
  • 3
  • 9
  • 25
  • 1
    `nav port[];` <-- what's this? – Ivan Aksamentov - Drop Oct 29 '15 at 14:09
  • May help: [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Ivan Aksamentov - Drop Oct 29 '15 at 14:11
  • 1
    You can't define an "empty" array. If you want to add runtime then use [`std::vector`](http://en.cppreference.com/w/cpp/container/vector). – Some programmer dude Oct 29 '15 at 14:13
  • _"Most importantly: Is there a way of not hard-coding `index` as the dimension of the data is not fixed. "_ Yes, use a `std::vector – πάντα ῥεῖ Oct 29 '15 at 14:14
  • And what's with all the global variables? – Some programmer dude Oct 29 '15 at 14:14
  • `nav` `=` `struct type` , `port[]` is supposed to be an object of `nav`. – owner Oct 29 '15 at 14:15
  • @Drop: got some books already, but thanks for the suggestion. – owner Oct 29 '15 at 14:18
  • No, `port` is an *array* of `nav` objects, an array of size zero, which means that any indexing into the array will be out of bounds and lead to undefined behavior. And apparently your compiler will not even add that variable to the output object file leading to your linker error. Either set a size, or use `std::vector`. – Some programmer dude Oct 29 '15 at 14:19
  • @JoachimPileborg: thanks for the tip on the "empty array". is there alternative to `std::vector`? the reason: following some searches I am more familiar with solutions involving `ifstream`, `stringstream`, etc. to the extent that I've managed to make it work on csv with data of same type. Just stuck with `struct` – owner Oct 29 '15 at 14:24
  • There might be some other causes of your problem to, like if your definition of `port` is in another source file, do you actually *build* with that source file? And why if you declare `nav port[]` do the error message say `nav* port`? Can you please try to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) and show us? – Some programmer dude Oct 29 '15 at 14:26
  • A [`std::vector`](http://en.cppreference.com/w/cpp/container/vector) (please read about it, either the linked reference of some other place) is like an array, but it can be expanded at runtime. You can even use indexing like an array. – Some programmer dude Oct 29 '15 at 14:27
  • @JoachimPileborg: was my intention, initially: setting the empty array then find a way of filling it through `getline` and stuff. thanks for the explanation. – owner Oct 29 '15 at 14:28
  • @JoachimPileborg: sure, a vector could be seen as a 1-d array. I am not denying that fact. Thus there should certainly be a way of using `std:: vector` i am not aware of at the moment. – owner Oct 29 '15 at 14:32
  • @JoachimPileborg: `std::vector` will imply reading each column of the `file.csv` as a vector of different types. is it an optimal approach? – owner Oct 29 '15 at 14:40
  • It's not that hard: `std::vector – Some programmer dude Oct 29 '15 at 14:43
  • So is your idea consisting of defining `port` as a `vector` on a `struct type` `nav`? if yes, then I was not aware of such possible thing. – owner Oct 29 '15 at 14:54
  • @JoachimPileborg: as suggested I have edited the post and disclosed a Minimal, Complete, and Verifiable Example. any idea of what is going wrong? cheers – owner Oct 29 '15 at 16:49
  • Parsing csv files is harder than you think. Don't write your own code. Use a library. – Neil Kirk Oct 29 '15 at 16:53
  • I've actually managed on a single file containing only `float` `data type` and I am only stuck with `struct array`. I just hope to strengthen skills by writing own code rather than resorting to existing library. but you're right as I concede that it could sometimes be a pain. cheers – owner Oct 29 '15 at 16:58

1 Answers1

0

You need to supply a dimension for the array "port". Regarding the error message with struct nav * port, that is a side-effect of how C++ will decay an array into a pointer

Alternatively, since you ask if there is a way to not hardcode the dimension, simply use std::vector. You will find that using std::vector is usually both safer to use and efficient.

The other issue with "index out of range", I cannot be 100% certain not seeing the content of the sample.csv file, but if the file only contained one entry, then index "1" would be out of range. In C++ C-style arrays and C++ std::vectorS use Zero-based indices.

Varsuuk
  • 115
  • 1
  • 10
  • Thanks for the reply. Regarding the content of the sample.csv, I've edited the post with a picture. Hope it helps. cheers. – owner Oct 29 '15 at 18:26