Problem using infile to copy to struct member

I am trying to read data from a text file and store it into an array of structs of various types. Everything works fine when reading charVar[] values, only when I try to read in double price and int miles into the array does everything fail. Only C-strings (char arrays) are allowed. The file is opening properly.

Question: How can I reformat my infile.getline command to correctly read a double and int from the textfile and store it into cars[numOfCars].price and cars[numOfCars].miles ?

The data in the textile is in the following form:

Chevy,Camaro,Black,23333.45,1578


code:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>

using namespace std;

const int strSize =200;
const int arraySize = 200;

struct carData
{
char model[strSize];
char make[strSize];
char color[strSize];
double price[strSize];
int miles[strSize];
};

//prototype
void loadCars(ifstream &infile, carData cars[], int strSize, int &numOfCars);

int main()
{
carData cars[arraySize];
ifstream infile;
int numOfCars;
char textFile[strSize];

cout << "textile name?" << endl;
cin.getline(textfile, strSize);

//function call
loadCars(infile, cars, strSize, numOfCars);

//function definition
void loadCars(ifstream &infile, carData cars[], int strSize, int &numOfCars)
{
do
{
inFile.getline((cars[numOfCars].model), strSize, ','); //works great
inFile.getline((cars[numOfCars].make), strSize, ','); //works great
inFile.getline((cars[numOfCars].color), strSize, ','); //works great
inFile.getline((cars[numOfCars].price), strSize, ','); //fails
inFile.getline((cars[numOfCars].miles), strSize, ','); //fails

numOfCars++;
} while (!inFile.eof());
}

Thank you.
1
2
3
4
5
inFile.getline((cars[numOfCars].model), strSize, ','); //works great
inFile.getline((cars[numOfCars].make), strSize, ','); //works great
inFile.getline((cars[numOfCars].color), strSize, ','); //works great
inFile.getline((cars[numOfCars].price), strSize, ','); //fails
inFile.getline((cars[numOfCars].miles), strSize, ','); //fails 


getline reads a whole line, so your following code reads 5 lines at once. You did specify a delimiter, but you don't need the last getline to have a comma delimiter, because you will not see a comma at the end of the line.

That said, the code above would become :

1
2
3
4
5
inFile.getline((cars[numOfCars].model), strSize, ',');
inFile.getline((cars[numOfCars].make), strSize, ',');
inFile.getline((cars[numOfCars].color), strSize, ',');
inFile.getline((cars[numOfCars].price), strSize, ',');
inFile.getline((cars[numOfCars].miles), strSize);

Last edited on
Mantorr22: as there are no whitespaces I'm not sure the extraction operator >> would know where to stop. My suggestion, tested with the sample text provided:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>

struct Car
{
    std::string m_model;//prefer std::string over char[]
    std::string m_make;
    std::string m_color;
    double m_price;
    int m_miles;
};
std::ostream& operator << (std::ostream& os, const Car& c)//for printing
{
    os << c.m_model << " " << c.m_make << " " << c.m_color << " " << c.m_price << " " <<c.m_miles << '\n';
    return os;
}
int main()
{
    std::vector<Car> cars;
    std::ifstream inFile ("D:\\input1.txt");
    while(inFile)
    {
        Car c{};
        std::string dummy1{};
        std::string dummy2{};
        std::string line;
        getline(inFile, c.m_model, ',')&&
            getline(inFile, c.m_make, ',')&&
                getline(inFile, c.m_color, ',')&&
                    getline(inFile, dummy1, ',')&&
                        getline (inFile, dummy2);
        /* getline()&& etc : short-circuit evaluation. In the expression A() && B(), A() is first evaluated
        and if it is not true, evaluation does not continue. */

        std::istringstream stream1(dummy1);
        stream1 >> c.m_price;
        std::istringstream stream2 (dummy2);
        stream2 >> c.m_miles;
        //http://stackoverflow.com/questions/21814297/how-to-extract-mixed-format-using-istringstream

        if(inFile)//make sure file is still open to avoid undefined behavior
        {
            cars.push_back(c);
        }
    }
    for (auto& elem : cars)
    {
        std::cout << elem;
    }
}
gunnerfunner : You are right when there are no space characters. Specifying a delimiter for getline would be the best way.

The OP code with minimal modifications as possible :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>
#include <sstream>

using namespace std;

const int strSize =200;
const int arraySize = 200;

struct carData
{
char model[strSize];
char make[strSize];
char color[strSize];
double price;        // Not "double price[strSize];"
int miles; // Not "double miles[strSize];"
};

//prototype
void loadCars(ifstream &infile, carData cars[], int strSize, int &numOfCars);

int main()
{
carData cars[arraySize];
ifstream infile;
int numOfCars = 0; // Initialization is necessary
char textFile[strSize];

cout << "textile name?" << endl;
cin.getline(textfile, strSize);

//function call
loadCars(infile, cars, strSize, numOfCars);

} // Does your code compile if you don't close the function with }?

//function definition
void loadCars(ifstream &infile, carData cars[], int strSize, int &numOfCars)
{

char price[strSize];
char miles[strSize];

stringstream ss;

do
{
inFile.getline((cars[numOfCars].model), strSize, ',');
inFile.getline((cars[numOfCars].make), strSize, ','); 
inFile.getline((cars[numOfCars].color), strSize, ','); 
inFile.getline((price), strSize, ',');
inFile.getline((miles), strSize);

if(!inFile) break;

ss << price;
ss >> cars[numOfCars].price;

ss.str("");
ss.clear();

ss << miles;
ss >> cars[numOfCars].miles;

ss.str("");
ss.clear();

numOfCars++;

} while (!inFile.eof());
}
Last edited on
First problem, original struct:
1
2
3
4
5
6
7
8
struct carData
{
    char model[strSize];
    char make[strSize];
    char color[strSize];
    double price[strSize];
    int miles[strSize];
};

Each car should not have an array of 200 different prices and mileages:
1
2
3
4
5
6
7
8
struct carData
{
    char model[strSize];
    char make[strSize];
    char color[strSize];
    double price;
    int miles;
};

There were a number of careless errors in the original code. It didn't compile, and the input file was never opened.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>

using namespace std;

const int strSize   = 200;
const int arraySize = 200;

struct carData
{
    char model[strSize];
    char make[strSize];
    char color[strSize];
    double price;
    int miles;
};

void loadCars(ifstream &infile, carData cars[], int strSize, int &numOfCars);
void showCars(carData cars[], int numOfCars);

int main()
{
    carData cars[arraySize];
    int numOfCars = 0;
    char textFile[strSize];

    cout << "textile name?" << endl;
    cin.getline(textFile, strSize);

    ifstream infile(textFile);
    if (!infile)
    {
        cout << "could not open file " << textFile << '\n';
        return 1;
    }


    loadCars(infile, cars, strSize, numOfCars);

    showCars(cars, numOfCars);
}


void loadCars(ifstream &inFile, carData cars[], int strSize, int &numOfCars)
{
    while (numOfCars < arraySize && inFile)
    {
        inFile.getline((cars[numOfCars].model), strSize, ',');
        inFile.getline((cars[numOfCars].make),  strSize, ',');
        inFile.getline((cars[numOfCars].color), strSize, ',');

        // read price, then skip until comma found
        inFile >> cars[numOfCars].price;
        inFile.ignore(100, ',');

        // read miles
        inFile >> cars[numOfCars].miles;

        // if everything ok so far, add 1 to count
        if (inFile)
            numOfCars++;

        // ignore everything until end of line
        inFile.ignore(100, '\n');

    }
}

void showCars(carData cars[], int numOfCars)
{
    for (int i=0; i<numOfCars; ++i)
    {
        cout << setw(4)  << i
             << setw(20) << cars[i].model
             << setw(20) << cars[i].make
             << setw(20) << cars[i].color
             << setw(10) << cars[i].price
             << setw(10) << cars[i].miles
             << '\n';
    }
}

Last edited on
Topic archived. No new replies allowed.