Counting the no. of words in a csv file in c++ - c++

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).

Related

How do i store My text file data into a vector in c++

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.

Reading from a .txt file into a structure in C++ language

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.

Reading CSV files into a 2D vector

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.

How to deal with csv file input stream where I need to divide the data in each row of the file into 6 different varaibles (types string and int)

I have a CSV file with data separated with commas. The file looks like this:
1998,MALE,United States,45,566
1993,FEMALE,......
I am going to have a vector of class ROW and each row from the data file will be stored there. My ROW has 5 variables and I need to separate them so I can use set function to row.set(year,sex, country, score, result).
Any idea how to read in the data?
From what I was told I should try to avoid getline. I do not want to convert strings to ints.
Any ideas?
I would probably start with a little operator to verify the presence of (but otherwise ignore) a string, something like this:
std::istream &operator>>(std::istream &is, char const *pat) {
char ch;
while (isspace(static_cast<unsigned char>(is.peek())))
is.get(ch);
while (*pat && is && *pat == is.peek() && is.get(ch)) {
++pat;
}
// if we didn't reach the end of the pattern, matching failed (mismatch, premature EOF, etc.)
if (*pat) {
is.setstate(std::ios::failbit);
}
return is;
}
We can use this to verify the presence of commas where needed, but otherwise ignore them fairly painlessly. I'd then overload operator>> for the ROW type to read the data appropriately:
class ROW {
int year;
enum { MALE, FEMALE} sex;
std::string country;
int foo;
int bar;
friend std::istream &operator>>(std::istream &is, ROW &r) {
is >> r.year >> ",";
std::string s;
is >> s >> ",";
if (s == "MALE")
r.sex = MALE;
else if (s == "FEMALE")
r.sex = FEMALE;
else
error("bad sex");
std::getline(is, r.country, ',');
return is >> r.foo >> "," >> r.bar;
}
};
From there, we can create a vector fairly directly:
// Open the file
std::ifstream in("data.txt");
// Read all the data
std::vector<ROW> rows { std::istream_iterator<ROW>(in), {}};

Reading an object from a file in c++

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.