0

I'm wanting to take 4 values, each separated by a comma, and store them to a airport object. Each line would have those 4 values would be stored together. So, calling all objects from Sweden, would find all objects from the country sweden and retrieve the appropriate values as well. Right now I have 4 different vectors, which store all 4 object values, however, doesn't necessarily set all 4 attributes/values together as an object. Help is greatly appreciated.

Examples of what the Text File looks like -

1,Goroka,Goroka,Papua New Guinea,GKA,AYGA,-6.081689,145.391881,5282,10,U 2,Madang,Madang,Papua New Guinea,MAG,AYMD,-5.207083,145.7887,20,10,U


#include "pch.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;

struct Airport
{
string code;
string name;
string city;
string nation;

friend std::istream& operator>>(std::istream& input, Airport& a);
};

istream& operator>>(std::istream& input, Airport& a)
 {
getline(input, a.code, ',');
getline(input, a.name, ',');
getline(input, a.city, ',');
getline(input, a.nation);
return input;
}
////////////////////////////////////////////

vector<string> split(const string& s, const string& delim)
 {
const bool keep_empty = true;
vector<string> result;

if (delim.empty())
{
    result.push_back(s);
    return result;
}

string::const_iterator substart = s.begin(), subend;

while (true)
{
    subend = search(substart, s.end(), delim.begin(), delim.end());
    string temp(substart, subend);
    if (keep_empty || !temp.empty())
    {
        result.push_back(temp);
    }
    if (subend == s.end())
    {
        break;
    }
    substart = subend + delim.size();
}

return result;
}

// Sorting Function 
bool Sort_By_Name_Ascending(const Airport& a, const Airport& b)
{
return a.name < b.name;
}


int main()
{
vector<Airport> database;
Airport a;

char choice;
string chr;

ifstream inputFile;
inputFile.open("airports.dat");

if (!inputFile)
{
    cout << "File Access Error!";
    return 0;
}

string fileLine;
cout << "Reading File ..." << endl;

while (!inputFile.eof())
{
    getline(inputFile, fileLine);
    vector<string> lineVector = split(fileLine, ",");
    if (lineVector[4].length() == 3)
    {
        while (inputFile >> a)
        {
            database.push_back(a);
        }
    }

}

cout << "What would you like to do?\nA. Sort in Alphabetical Order.\nB. 
Delete an Airport.\nC. Exit Program." << endl;

cin >> choice;

switch (choice)
{
case 'A':
    sort(database.begin(), database.end(), Sort_By_Name_Ascending);
break;

case 'B':
    cout << "Deleting a value" << endl;

break;

case 'C':
return 0;
break;
}


return 0;
}
mjzach22
  • 39
  • 6
  • 2
    Please add an input file to your question. – Swordfish May 07 '19 at 19:44
  • 3
    [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons?rq=1) – Swordfish May 07 '19 at 19:49
  • 2
    Consider making a structure that holds `code`, `name`, `city`, and `nation` and having a single `vector` of that structure. This usually makes the data a lot easier to track. – user4581301 May 07 '19 at 19:55
  • You may want to search the internet for "c++ read file CSV" or "C++ read file comma separated". – Thomas Matthews May 07 '19 at 20:24
  • Just updated my questions with txt example – mjzach22 May 08 '19 at 13:50

1 Answers1

2

You may want to organize your data structures to model the input data:

struct Airport
{
  std::string    code;
  std::string    name;
  std::string    city;
  std::string    nation;
};

A next step is to overload operator>> to read in an instance from a stream:

struct Airport
{
  //...
  friend std::istream& operator>>(std::istream& input, Airport& a);
};
std::istream& operator>>(std::istream& input, Airport& a)
{
    std::getline(input, a.code, ',');
    std::getline(input, a.name, ',');
    std::getline(input, a.city, ',');
    std::getline(input, a.nation);
    return input;
}

This simplifies the input:

std::vector<Airport> database;
Airport a;
while (inputfile >> a)
{
  database.push_back(a);
}

To sort, you can come up with some functions or function objects and supply them to std::sort:

bool Sort_By_Name_Ascending(const Airport& a, const Airport& b)
{
  return a.name < b.name;
}

//...
std::sort(database.begin(), database.end(), Sort_By_Name_Ascending);

Edit 1: The whole record or line
There is a difference between modeling the whole line versus only fields you are interested in. If your records are text line (one record == one text line), you may want to read in the text line as a string then extract the fields you are interested in.

std::istream& operator>>(std::istream& input, Airport& a)
{
    std::string record;
    std::getline(input, record);

    // Now extract the interesting fields from the string.
    std::istringstream record_stream;
    unsigned int record_number;
    char         comma;
    record_stream >> record_number;  // Read but ignore.
    record_stream >> comma;          // Read but ignore.
    std::getline(record_stream, a.code, ',');
    std::getline(record_stream, a.name, ',');
    std::getline(record_stream, a.city, ',');
    std::getline(record_stream, a.nation);
    return input;    
}
Thomas Matthews
  • 52,985
  • 12
  • 85
  • 144
  • Thank you so much Thomas! Im having issues with passing the values now, when I out put it, it shows blank. Please see code I updated. – mjzach22 May 08 '19 at 13:47
  • I added This, for (int i = 0; i < 4; ++i) { cout << "Airport Info: [" << i << "]: " << database[i].nation << " | Code: " << database[i].code << endl; } – mjzach22 May 08 '19 at 13:56
  • But It shows the whole line like this - Airport Info: [0]: Papua New Guinea,MAG,AYMD,-5.207083,145.7887,20,10,U | Code: 2 Airport Info: [1]: Papua New Guinea,HGU,AYMH,-5.826789,144.295861,5388,10,U | Code: 3 Airport Info: [2]: Papua New Guinea,LAE,AYNZ,-6.569828,146.726242,239,10,U | Code: 4 Airport Info: [3]: Papua New Guinea,POM,AYPY,-9.443383,147.22005,146,10,U | Code: 5 – mjzach22 May 08 '19 at 13:56
  • Since you didn't post a sample of the input file, I had to guess based on your code. See my edit. – Thomas Matthews May 08 '19 at 14:03
  • This is what Im trying to use to call the struct to output the results, what am I missing? for (int i = 0; i < 4; ++i) { cout << "Airport Info: " << a.nation << " | Code: " << database[i].code << " | City: " << database[i].city << endl; } – mjzach22 May 08 '19 at 14:29
  • You are missing the `name` member. – Thomas Matthews May 08 '19 at 14:39