Загрузка из файла cpp - PullRequest
       101

Загрузка из файла cpp

0 голосов
/ 01 августа 2020

Я хочу загрузить список воспроизведения из текстового файла. Текстовый файл состоит из альбомов с их песнями, первая строка - это название альбома, вторая строка - количество песен в альбоме, затем одна песня с данными в каждой строке, пока альбом не будет закончен, затем название альбома следующий альбом et c. Чтобы было веселее, список - это отдельный класс, альбом - это собственный класс, а песни - отдельный класс. Вот пример того, как может выглядеть файл

Album name1

2

song1|artist1|234

song2|artist1|443

Album name2

3

song3|artist2|320

song4|artist2|360

song5|artist2|340

Моя проблема в том, что при загрузке первый альбом будет загружен правильно, а второй альбом (и третий et c) - нет. загружено полное имя, первый символ будет пропущен. Таким образом, альбом name2 будет загружен как lbum name2.

Это классы, связанные с функциями и перегрузками, которые используются при этом:

#ifndef DT019G_JUKEBOX_H
#define DT019G_JUKEBOX_H

#include "Prototypes.h"
#include "Album.h"
#include "Menu.h"

class Jukebox {
private:
    std::vector <Album> albums;
    Menu mainMenu, fileMenu, printMenu;

public:
    Jukebox() {
    void openFile();


void Jukebox::openFile() {
    Album tmpAlbum;
    std::fstream inFile(directory+fileName, std::ios::in);
      while(!inFile.eof()) {inFile>> tmpAlbum;
    albums.push_back(tmpAlbum);}
    inFile.close();
}


#ifndef DT019G_ALBUM_H
#define DT019G_ALBUM_H

#include "Prototypes.h"
#include "Song.h"
class Album {
public:
    std::string albumName;
private:
    std::vector <Song> songList;
public:
    Album() {albumName="NoName";}
    Album(std::string pName) {albumName=pName;}

    //Set/Get functions
    void setAlbumName (const std::string pname) {albumName=pname;}
    void setSongList (const std::vector <Song> pSongList) {songList=pSongList;}
    void clearSongList () {songList.clear();}

    // Add a song to the albums song list
    void addSongToAlbum (const Song pSong);

};

std::istream &operator>>(std::istream &is, Album &album);
#endif //DT019G_ALBUM_H

// Overloads the >> stream so it can be used to load an album from file.
// First it puts all the input in the vector inputData. Then when the first row (containing the album name)
// has been loaded into albumName, the first two entries of inputData are erased (the ones containing the album name and
// number of songs. Then only songs are left in vector thus they can be loaded into the songList with ease.
std::istream &operator>>(std::istream &is, Album &album){
    album.clearSongList();
    std::string tempData;
    std::getline(is, tempData);
    album.setAlbumName(tempData);
    std::getline(is, tempData);
    int numberOfSongs;
    std::istringstream iss(tempData);
    iss >> numberOfSongs;
    Song tempSong;
    for (size_t i=0; i<numberOfSongs; i++){
       std::getline(is, tempData);
       std::istringstream iss(tempData);
       iss>>tempSong;
       album.addSongToAlbum(tempSong);
    }
    is.get();
    return is;
}

Я добавляю сюда класс песни, хотя я не думаю, что это необходимо, так как кажется, что он работает должным образом

class Song {
private:
    string title;
    string artist;
    Time length;
public:
    // Default constructor
    Song() {title="noTitle"; artist="noArtist"; length=Time(0,0,0);}
    // Constructor using parameters
    Song (string pTitle, string pArtist, int pHours, int pMinutes, int pSeconds)
    {title=pTitle, artist=pArtist, length=Time(pHours, pMinutes, pSeconds);}

    // Set/Get functions
    void setTitle (string pTitle) {title=pTitle;}
    void setArtist (string pArtist) {artist=pArtist;}
    void setLength (Time pTime) {length=pTime;}
    string getTitle ()const {return title;}
    string getArtist ()const {return artist;}
    Time getLength () const {return length;}

    void clientProgram();
};

// Takes an in stream on the format title | artist | time and convert it to a Song object.
std::istream &operator>>(std::istream &is, Song &song);

#endif //DT019G_SONG_H

std::istream &operator>>(std::istream &is, Song &song){
    string loadData;
    std::getline(is, loadData);
    string tempSeconds;
    Time tempTime;
    size_t j,k,l;
    j=loadData.find(DELIM);
    k=loadData.find(DELIM, j+1);
    l=loadData.size();
    song.setTitle(loadData.substr(0,j));
    song.setArtist(loadData.substr(j+1,k-(j+1)));
    tempSeconds=loadData.substr(k+1, l-(k+1));
    std::istringstream iss(tempSeconds);
    iss >>tempTime;
    song.setLength(tempTime);
    is.get();
    return is;
}

Спасибо за любую помощь. Я просто не могу найти причину, по которой это произошло.

1 Ответ

0 голосов
/ 01 августа 2020

В вашей функции

std::istream &operator>>(std::istream &is, Album &album){
    album.clearSongList();
    std::string tempData;
    std::getline(is, tempData);
    album.setAlbumName(tempData);
    std::getline(is, tempData);
    int numberOfSongs;
    std::istringstream iss(tempData);
    iss >> numberOfSongs;
    Song tempSong;
    for (size_t i=0; i<numberOfSongs; i++){
       std::getline(is, tempData);
       std::istringstream iss(tempData);
       iss>>tempSong;
       album.addSongToAlbum(tempSong);
    }
    is.get();
    return is;
}

std::getline() будет использовать символы новой строки, а последний is.get() будет использовать следующий символ из потока. Похоже, здесь используется первый символ названия следующего альбома.

Чтобы этого избежать, вы должны удалить этот лишний is.get();.

...