Reputation: 1849
I want to read custom file structure and output them, also i want to ignore the lines which are not in the right format. Like comments, titles, etc.,
I've tried this code but its stop looping when it meets a line which is out of the structure.
Here is the txt file.
1001 Promod Dinal IT-K20 42 42
1002 Sahan Navod BM-K11 65 28
day_02
1003 Kaushani Dilinika BM-K12 69 49
1004 Fathima Sahana QS-K14 73 43
int main()
{
ifstream thefile;
thefile.open("GameZone.txt");
int id;
char fName[30];
char lName[30];
char stream[30];
int score;
int time;
if (!thefile.is_open()) {
cout << "cant open the file" << endl;
}
else {
while (!thefile.eof()) {
if (thefile >> id >> fName >> lName >> stream >> score >> time) {
cout << id << " ," << fName << " ," << lName << " ," << stream << " ," << score << " ," << time << endl;
}else if(!(thefile >> id >> fName >> lName >> stream >> score >> time)){
cout << "skip the row" << endl;
continue;
}
}
}
return 0;
}
Output
1001 ,Promod ,Dinal ,IT-K20 ,42 ,42
1002 ,Sahan ,Navod ,BM-K11 ,65 ,28
Upvotes: 0
Views: 340
Reputation: 84652
If you are still having difficulty with the implementation, then a very simple implementation would simple read each line, create a stringstream
from the line to allow you to attempt to parse your values from, then depending on the result of reading from the stringstream
output your values in your (rather strange " ,"
) csv format, or simply go read the next line and try again.
You should be using std::string
instead of char[]
to holds your string data in C++. Either will work, but the latter is much more user-friendly and flexible. In either case, you will want to coordinate all the differing types of data that make up one record as a struct
. This has many benefits if you are actually doing something more than just dumping your data to stdout
. For example, you can store all of your data read in a std::vector
of struct and then be able to further process your data (e.g. sort
, push_back
, or erase
records) as needed or pass it to other functions for further processing.
A simple struct using int
and std::string
could be:
struct record_t { /* simple struct to coordinate data in single record */
int id, score, time;
std::string fname, lname, stream;
};
The reading and outputting of records in your csv format, can then be as simple as using a temporary struct to attempt to parse the line into, and if successful, output (or further use) the data as needed, e.g.
std::string line; /* string to hold line */
std:: ifstream fin (argv[1]); /* in stream for file */
while (getline (fin, line)) { /* read entire line into line */
std::stringstream ss (line); /* create stringstream from line */
record_t record; /* temp struct to read into */
if (ss >> record.id >> record.fname >> record.lname >>
record.stream >> record.score >> record.time)
/* if successful read from stringstream, output record */
std::cout << record.id << " ," << record.fname << " ,"
<< record.lname << " ," << record.stream << " ,"
<< record.score << " ," << record.time << '\n';
}
Putting it altogether in a short example that takes the file to be read as the first argument to the program could be:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
struct record_t { /* simple struct to coordinate data in single record */
int id, score, time;
std::string fname, lname, stream;
};
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least 1 argument provided */
std::cerr << "error: filename required.\n";
return 1;
}
std::string line; /* string to hold line */
std:: ifstream fin (argv[1]); /* in stream for file */
while (getline (fin, line)) { /* read entire line into line */
std::stringstream ss (line); /* create stringstream from line */
record_t record; /* temp struct to read into */
if (ss >> record.id >> record.fname >> record.lname >>
record.stream >> record.score >> record.time)
/* if successful read from stringstream, output record */
std::cout << record.id << " ," << record.fname << " ,"
<< record.lname << " ," << record.stream << " ,"
<< record.score << " ," << record.time << '\n';
}
}
(note: do not hard-code filenames or use magic numbers in your code)
Example Use/Output
Output in your rather odd " ,"
csv format:
$ ./bin/readrecords dat/records.txt
1001 ,Promod ,Dinal ,IT-K20 ,42 ,42
1002 ,Sahan ,Navod ,BM-K11 ,65 ,28
1003 ,Kaushani ,Dilinika ,BM-K12 ,69 ,49
1004 ,Fathima ,Sahana ,QS-K14 ,73 ,43
To make things slightly more useful, you can, instead of simply outputting the records directly, store all records in a std::vector<record_t>
(vector of struct). This then opens the possibility of further processing your data. See if you can understand the changes made below on how each record is stored in a vector and then a Range-based for loop is used to loop over each record held in the vector to output your information.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
struct record_t { /* simple struct to coordinate data in single record */
int id, score, time;
std::string fname, lname, stream;
};
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least 1 argument provided */
std::cerr << "error: filename required.\n";
return 1;
}
std::string line; /* string to hold line */
std:: ifstream fin (argv[1]); /* in stream for file */
std::vector<record_t> records; /* vector of records */
while (getline (fin, line)) { /* read entire line into line */
std::stringstream ss (line); /* create stringstream from line */
record_t record; /* temp struct to read into */
if (ss >> record.id >> record.fname >> record.lname >>
record.stream >> record.score >> record.time)
records.push_back(record); /* if good read, add to vector */
}
if (records.size() > 0) /* validate vector contains records */
for (auto& r : records) /* loop over all records */
std::cout << r.id << " ," << r.fname << " ," << r.lname << " ,"
<< r.stream << " ," << r.score << " ," << r.time << '\n';
else /* if no records read, throw error */
std::cerr << "error: no records read from file.\n";
}
Look things over and let me know if you have any further questions.
Upvotes: 0
Reputation: 182883
Do not try to parse fields directly from the file. Instead, read lines from the file and attempt to parse those lines. Use the following algorithm:
Upvotes: 4