Reading file.txt with mixture of first name, last name & middle name
Feb 3, 2021 at 8:37am UTC
I have a file below. Some have a name as input, there were a few with middle name. How should i store the names?
For the first line i can use a dummy line to store them but for the name what should i do?
1 2 3 4
Name Age Subject1 Subject2 Subject3
John 13 55 55 55
John Terry 15 55 55 55
John X Terry 13 55 55 55
Feb 3, 2021 at 8:49am UTC
Depending on the format of the file, you might be able to make certain guarantees.
- Is a number allowed to be a last name? Can a suffix like "3" (maybe meaning "the third") happen? If not, then parse each word, and if that word is a number, then you know the name is over, and the age has begun.
- Is there guaranteed to be a constant number of characters (including spaces) between the start of the line and the first number character (e.g. 14 as your example has)? If so, you can just read in the first 14 characters, and then strip trailing spaces from the string.
Hastily made example of first:
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
// Example program
#include <iostream>
#include <string>
#include <sstream>
// more like "is_positive_int_of_unbounded_size"
bool is_int(const std::string& token)
{
bool nondigit_found = false ;
for (size_t i = 0; i < token.length(); i++)
{
if (!std::isdigit((unsigned char )token[i]))
{
nondigit_found = true ;
break ;
}
}
return !nondigit_found;
}
int get_int(const std::string& token)
{
std::istringstream iss(token);
int ret;
iss >> ret;
return ret;
}
int main()
{
// replace this with an ifstream:
std::istringstream file(
"Name Age Subject1 Subject2 Subject3\n"
"John 13 55 55 57\n"
"John Terry 15 55 55 59\n" );
std::string dummy;
if (!(file >> dummy >> dummy >> dummy >> dummy >> dummy))
{
std::cout << "Error opening file\n" ;
return 1;
}
std::string token;
while (file >> token)
{
std::string name = token;
int age = -1;
while (file >> token)
{
if (is_int(token))
{
age = get_int(token);
break ;
}
else
{
name += " " ;
name += token;
}
}
int subject[3] {};
file >> subject[0] >> subject[1] >> subject[2];
std::cout << name << " | " << age << " | " << subject[0] << ' ' << subject[1] << ' ' << subject[2] << '\n' ;
}
}
John | 13 | 55 55 57
John Terry | 15 | 55 55 59
Last edited on Feb 3, 2021 at 9:06am UTC
Feb 3, 2021 at 10:36am UTC
Consider:
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
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
struct Person {
std::string name;
int age {};
std::vector<int > marks;
};
std::istream& operator >>(std::istream& is, Person& p)
{
std::string line;
if (std::getline(is, line)) {
std::istringstream iss(line);
p.name.clear();
p.marks.clear();
for (std::string str; !(iss >> p.age); p.name += str) {
iss.clear();
iss >> str;
if (!p.name.empty())
p.name += ' ' ;
}
for (int i {}; iss >> i; p.marks.push_back(i));
}
return is;
}
std::ostream& operator <<(std::ostream& os, const Person& p)
{
os << std::setw(15) << std::left << p.name << " " << p.age << ' ' ;
for (const auto & m : p.marks)
os << ' ' << m;
return os;
}
int main()
{
std::ifstream ifs("names.txt" );
if (!ifs)
return (std::cout << "Cannot open file\n" ), 1;
std::string line;
std::getline(ifs, line); // Remove header line
std::vector<Person> students;
for (Person p; ifs >> p; students.push_back(p));
for (const auto & s : students)
std::cout << s << '\n' ;
}
Given input of:
Name Age Subject1 Subject2 Subject3
John 13 55 55 55
John Terry 15 55 55 55
John X Terry 13 55 55 55
Displays:
John 13 55 55 55
John Terry 15 55 55 55
John X Terry 13 55 55 55
Topic archived. No new replies allowed.