简体   繁体   中英

How to read specific amount of character from file to struct

I need to read 20 characters from this data file:

    7
    Petras A. Petraitis 120 15 20 0 
    Jurgis Jurgutis     222 16 12 22
    Rimas Jonas         138 15 15 59
    Bei Lin Sin Mun     23 15 0 0   
    Zigmas Nosis        256 16 23 9 
    Romas Senasis       111 15 15 15
    Jurgis Stasys Lydeka199 16 13 9 
    6
    256 16 43 15
    120 15 50 10
    111 16 5 35 
    199 16 35 59
    222 16 42 22
    23 15 30 0  

Basically every letter and spaces till numbers. I have tried using read(), but I couldn't get it to work with struct. I also been trying to use getline(), but it does not work for me either. I have been looking everywhere, but most of tutorials show with direct user input instead of reading from file.

    #include <iostream>
    #include <fstream>
    #include <string>

    using namespace std;

    struct competition{
        string name; // athletes name
        int athleteNum; // number
        int startHours; // starting time: hours
        int startMin; // starting time: minutes
        int startSec; // starting time: seconds
    };

    int main()
    {
        ifstream duom ("U2.txt");

        competition athletes[30];
        int n; // amount of athletes
        duom >> n;
        for (int i=0; i<n; i++){
            duom.getline(athletes[i].name, 20);
        }
        return 0;
    }

with getline() code doesn't compile, so I probably got the syntax wrong and read() doesn't seem to work with struct.

You're almost right. istream::getline() waits for char * at the first argument but you're are passing std::string . Keep in mind if getline doesn't read symbols to delimiter (by default, end of line and it is your case) it sets failbit for input stream ( duom ). You need to istream::clear() it. Also you're mixing duom >> n; and file reading. Maybe you want to read info for structure from file and n from cin ?

UPDATE

You need to skip a new line character with istream::ignore() . Also your example has name with 20 symbols at 8 line but istream::getline extracts one less than the specified. Following code doesn't contain any error checking.

int main()
{
    ifstream duom("U2.txt");
    competition athletes[30];
    int n; // amount of athletes
    duom >> n;
    duom.ignore(1);

    char name[256];
    for (int i = 0; i < n; i++) {
        duom.getline(name, 21);
        if (duom.fail())
            duom.clear();
        athletes[i].name = name;
        duom >> athletes[i].athleteNum >> 
                athletes[i].startHours >> 
                athletes[i].startMin >> 
                athletes[i].startSec;
        duom.ignore(1);
    }
    return 0;
}

If you don't want to read other athlete members you should also skip them with istream::ignore() instead of reading with duom >> ... :

duom.ignore(32); // skip up to 32 characters or '\n' 

https://en.cppreference.com/w/cpp/io/basic_istream/ignore

As alezh pointed out, istream::getline() takes a char* not a std::string . You may create a char hold[50] variable to pass to istream::getline() : duom.getline(hold, 50); , and then assign your std::string to that: athletes[i].name = std::string(hold, 20); .

Also as he pointed out, duom >> n; will not get you to the next line. You may want to duom.ignore(20, '\\n') after that line to start on the correct line. Or not use >> with getline in the first place.

And what is the nested for loop for? You can get rid of the second for line.

Up to my knowledge in file organisation and processing course .. every file record should have a defined structure for example: fixed length fields and records or variable length fields with fixed records size ... etc

So .. you have to define the structure of the file first in order to read it.I think these records above has not a defined structure so you can not read it.

But in general using functions file.read() /file.write() is better that using operators << / >> , because in them you can define the structure of the file well by writing the object in a char array (cast it's attributes and add them to it) then write the array in the file.

And you can read the records records by records by reading in a dynamic char [] then use istrstream object to separate it's attributes by getline function until it reaches the delimeter if it was variable field, or if it was fixed sized fields and record you can just say file.read((char*)& object_name,sizeof(object))

And for example , operator ">>" inputs in a variable until it reaches a space .. and getline reads until it finds a delimiter (the default delimiter is endl). So how could you read the string from the file? I think you can not read that file as it's records do not have a certain structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM