-2

I'm trying to read .txt data (formatted with spaces) into a struct object. To simplify the question, say the .txt contains one record of a student's first name, last name, campus code, and id.

Here is the struct:

struct Student {
char f_name[10]; // John, followed by 6 spaces
char l_name[20]; // Fuller, followed by 14 spaces
char camp_code; 
char id[8]; // 
} s;

Here is how i use the reinterpret_cast with read from fstream:

f.read(reinterpret_cast<char *>(&s), sizeof(s));

It compiles, but when I'm displaying (edit: std::cout<<s.f_name; ...) the result, the result looks like this:

first name: John      Fuller              E23123456 
last name: Fuller              E23123456 
campus code: E
id: 23123456 

It seems like the compiler successfully found the starting point of each component of the struct object, but it stores the entire record starting from that component. Except for the camp_code part, it correctly grabbed the char element. Any idea where I have missed here?

Thanks!

Madmint
  • 5,976
  • 1
  • 11
  • 17
  • 2
    May I ask why you are messing with raw pointers and c-style raw arrays when you're coding in c++? – πάντα ῥεῖ Sep 20 '20 at 07:35
  • when I'm displaying the result... How are you doing it? – 273K Sep 20 '20 at 07:37
  • @πάνταῥεῖ tbh this is the only way I know (so far) to read data into a struct, is there any other techniques I can look into to handle it more nicely? – Madmint Sep 20 '20 at 08:08
  • @Madmint Well, the c++ standard [I/O facilities](https://en.cppreference.com/w/cpp/io) and [`std::string`](https://en.cppreference.com/w/cpp/string) work together well and nicely. Here's an older post of mine with an example similar to yours: [Why does reading a record struct fields from std::istream fail, and how can I fix it?](https://stackoverflow.com/questions/23047052/why-does-reading-a-record-struct-fields-from-stdistream-fail-and-how-can-i-fi) – πάντα ῥεῖ Sep 20 '20 at 08:32
  • @πάνταῥεῖ Thank you for the link. In my input file, everything is in one line, so the getline method wouldn't work. Also, there is no delimiter between each field. i.e. the f_name field should contain10 chars, John takes up 4 chars, so there will be 6 spaces following that, but if someone's f_name is aaaaabbbbb, then the f_name and the l_name will become one long string. So I can't think about another way other than using char arrays to handle this case or when a field is empty, i.e. situations where someone doesn't have l_name. – Madmint Sep 20 '20 at 19:48

1 Answers1

1

As your char array is not nul terminated, you have to display each character instead of the (decayed) const char*:

template <std::size_t N>
void print(const char (&a)[N])
{
    for (auto c : a)
        std::cout << c;
}

and then

Student student;
// init student
// ...


print(student.f_name); // instead of std::cout << student.f_name;
print(student.l_name); // instead of std::cout << student.l_name;
std::cout << student.camp_code;
// ...
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Oh! No wonder the char camp_code prints the correct result but the char arrays are not. When I directly cout and got the incorrect answer, the first thing I thought about my problem was how I read the data but not how I print the result. This is very helpful. Thank you very much! – Madmint Sep 20 '20 at 08:23