Is there a way to import the content of my text file into a structure?
My code looks like this:
struct customerstruct {
int Customer_ID;
string name;
string adress;
};
And this is the content of my text file:
101
James
221B Baker St.
I would like to mirror the value of my text file into the structure.
Here's a suggestion:
struct customerstruct
{
int Customer_ID;
string name;
string adress;
friend std::istream& operator>>(std::istream& input, customerstruct & c);
};
std::istream& operator>>(std::istream& input, customerstruct & c)
{
input >> c.Customer_ID;
input.ignore(1000, '\n');
std::getline(input, c.name);
std::getline(input, c.adress);
return input;
}
Your input loop could look like this:
customerstruct c;
std::vector<customerstruct> database;
while (my_file >> c)
{
database.push_back(c);
}
The structure overloads operator>> to reading a single instance.
A std::vector is used to contain more than one instance read from a file.
Related
How do you store my Comma seperate file in a vector structure
Hello so i have a file called FILE.txt which has data like this
Date,ID,ArrivalTime,DepatureTime
12/02/2022,BDF 021,12:30:20,_
13/02/2022,FSD 213,10:20:30,12:30:20
etc I have a vector called vector<vehicle> vehic(100);
I want to store it in the vector such that it will be the date will be stored, ID etc
Function for adding vechicles
So i add vehicles using a function
int static totalvehicle=0,totalcar=0,totalamt=0,i=0;
void vehicle::addVehicle()
{
vehicle *v = new vehicle;
cin.ignore();
cout<<"Enter vehicle number : ";
std::getline(cin, v->id);
cout<<"Enter arrival time in hours minutes and seconds : ";
cin>>v->arrive.hh>>v->arrive.col1>>v->arrive.mm>>v->arrive.col2>>v->arrive.ss;
cout<<"Enter date in day month and year: ";
cin>>v->dt.day>>v->dt.sym1>>v->dt.month>>v->dt.sym2>>v->dt.year;
vehic.at(i).id=v->pltno;
vehic.at(i).arrive.hh=v->arrive.hh;
vehic.at(i).arrive.mm=v->arrive.mm;
vehic.at(i).arrive.ss=v->arrive.ss;
vehic.at(i).dt.day=v->dt.day;
vehic.at(i).dt.month=v->dt.month;
vehic.at(i).dt.year=v->dt.year;
}
I would like to store it in the same structure as i added them using this function how would i do so please help??
IMHO, the route to go is to model a row (not the title row) with a structure, and overload operator>> for reading an instance.
struct Vehicle_Info
{
std::string m_date;
std::string m_id;
std::string m_arrival_time;
std::string m_departure_time;
friend std::istream& operator>>(std::istream& input, Vehicle_Info& vi);
};
std::istream& operator>>(std::istream& input, Vehicle_Info& vi)
{
std::getline(input, vi.m_date, ',');
std::getline(input, vi.m_id, ',');
std::getline(input, vi.m_arrival_time, ',');
std::getline(input, vi.m_departure_time);
return input;
}
Your input code could look like this:
std::vector<Vehicle_Info> database;
Vehicle_Info vi;
while (data_file >> vi)
{
database.push_back(vi);
}
Simple. Due to the overloaded operator>> for the Vehicle_Info class.
The contents of my file look like:
Barr,3145,7
Rab,12,5513,1412,221,232,179,7121231
Bean,1,1231,219,21,337,9239,312,764,640391,4,7966346,22278,5,116364,56350
Earl,132,230,121,32,425,67
Donut,112,5525,23121,2123,65432,8790,3,4567,444
I want each line to be stored in a 2D vector (vector<vector<string>>) without the comma.
I have tried doing:
while(getline(filestream, line)){
stringstream linestream(line);
while(getline(linestream, anotherLine, ','){
oneDvector.push_back(anotherLine);
}
twoDvector.push_back(oneDvector);
oneDvector.clear();
}
But this does not seem to work. What can I do?
IMHO, you don't want to use a 2d vector or array. You want a std::vector of a class:
struct Record
{
std::string text;
std::vector<int> data;
friend std::istream& operator>>(std::istream& input, Record& r);
};
std::istream& operator>>(std::istream& input, Record& r)
{
std::string text_line;
std::getline(input, text_line);
std::istringstream text_stream(text_line);
std::getline(text_stream, r.text, ',');
int value;
char comma;
while (text_stream >> value)
{
r.data.push_back(value);
text_stream >> comma;
}
return input;
}
Note: In the above input function, a record is read by line into a string. This will make the reading of the numbers easier.
You input loop could look like:
Record r;
std::vector<Record> database;
while (file_stream >> r)
{
database.push_back(r);
}
Usually modeling a structure from an input record makes a better program. Easier to develop and debug.
The input may be simplified by replacing the 2nd occurrence and remaining commas with spaces. The first comma is used to end the text field.
I am trying to count the no. of dates stores in the first line of a CSV file (Separated by commas):-
State,Region,Lat,Long,1/22/20,1/23/20,1/24/20,1/25/20,1/26/20
I have to count the no. of dates after Long(i.e. output = 5).
I have written the code to read the CSV file, which I have shown below, but, how shall I count the no. of dates after long. Would highly appreciate your help. Please feel free to ask for any other piece of information. Thanks.
char** readCSV(const char* csvFileName, int& csvLineCount)
{
ifstream fin(csvFileName);
if (!fin)
{
return nullptr;
}
csvLineCount = 0;
char line[1024];
while(fin.getline(line, 1024))
{
csvLineCount++;
};
char **lines = new char*[csvLineCount];
fin.clear();
fin.seekg(0, ios::beg);
for (int i=0; i<csvLineCount; i++)
{
fin.getline(line, 1024);
lines[i] = new char[strlen(line)+1];
strcpy(lines[i], line);
};
fin.close();
return lines;
}
This looks like you are reading a record that contains one or more subrecords.
I recommend using a Date class as well as a Record class.
class Date
{
public:
unsigned int month_num;
unsigned int day_num;
unsigned int year_num;
friend std::istream& operator>>(std::istream& input, Date& d);
};
std::istream& operator>>(std::istream& input, Date& d)
{
char forward_slash;
input >> d.month_num; input >> forward_slash;
input >> d.day_num; input >> forward_slash;
input >> d.year_num;
return input;
}
Overloading operator>> for the Date class will come in handy later.
Now the record class:
class Record
{
public:
std::string state;
std::string region;
std::string latitude;
std::string longitude;
// A container for the date subrecords
std::vector<Date> dates;
friend std::istream& operator>>(std::istream& input, Record& r);
};
std::istream& operator>>(std::istream& input, Record& r)
{
std::string text_line;
std::getline(input, text_line);
std::istringstream record_stream(text_line);
std::getline(record_stream, r.state, ',');
std::getline(record_stream, r.region, ',');
std::getline(record_stream, r.latitude, ',');
std::getline(record_stream, r.longitude, ',');
Date d;
while (record_stream >> d)
{
r.dates.push_back(d);
char comma;
record_stream >> comma;
}
return input;
}
The above function reads a text line of input, since the records are terminated by a newline. A stream is created from the text line. The stream helps in reading a variable quantity of dates.
Edit 1: Reading in the file
Your input code would look something like this:
std::vector<Record> database;
Record r;
while (fin >> r)
{
database.push_back(r);
}
Yes, you can use C-Strings and arrays, but C++ streams and std::vector simplify the code and simple code has less defects than complicated code.
Also, the std::vector and std::string classes manage dynamic memory for you. They expand as necessary. No need for checking for array overflows. They are also easier to pass. Passing arrays requires passing the capacity also (and maybe the quantity of elements in the array).
I am attempting to implement an AVL Tree by using key/value pairs from a text file. For example, (0003,09390,Vegas) would be one such key value pair, with 0003 being the key, and 09390, Vegas being the value. I am confused on how to extract each individual item. I would want 0003, 09390, and Vegas stored as each individual variables in a struct.
I recommend using a structure to hold the values:
struct Values
{
std::string value; // such as 09390
std::string city; // such as "Vegas"
};
Next, overload the extraction operator:
struct Values
{
std::string value; // such as 09390
std::string city; // such as "Vegas"
friend std::istream& operator>>(std::istream& inp, Values& v);
};
std::istream& operator>>(std::istream& inp, Values& v)
{
inp >> v.value;
// insert code to skip over delimiter.
inp >> v.city;
return inp;
}
Your input loop could look like this:
std::string key;
std::string delimiter;
Values v;
AVL tree;
//...
while (input_file >> key >> delimiter >> v)
{
tree[key] = v;
}
Note: the above input expression only works when values are not space or tab separated.
For more information about reading from a file, search StackOverflow for:
"c++ read file struct"
"c++ read file csv"
The easiest approach is probably to use ignore() in combination with std::getline():
std::string key, code, city;
if (in.ignore(std::numeric_limits<std::streamsize>::max(), '(')
&& std::getline(in, key, ',')
&& std::getline(in, code, ',')
&& std::getline(in, city, ')')) {
// ...
}
If I have a file containing 10 rows, where each row contain information about the following object,
class student
{
public:
string name;
int age;
int rollnum;
int year;
string father;
string mother;
string category;
string region;
char sex;
string branch;
int semester;
};
How can I read all the 10 objects information from a file? ( I am guessing I will have to take an array of 10 objects for this )
istream& operator >>(istream& in, student& val) {
return in >> name >> age >> rollnum >> year; // ...
}
Then you can do this:
for (string line; getline(infile, line); ) {
istringstream stream(line);
student person;
stream >> person;
}
Now person is being populated once per line. I do it this way rather than directly streaming from the file because this way is safer: if a line has the wrong number of tokens it won't misunderstand what the columns are, whereas without getline() you might naively parse 10 tokens of an 11 token line, then think that the 11th token on the line is the first token of the next record. Just a typical mistake that happens in beginner C++ text parsing code.