简体   繁体   English

从文件 cpp 加载

[英]Loading from file cpp

I want to load a playlist from a textfile.我想从文本文件加载播放列表。 The text file consists of albums with their songs, the first line is the album name, the second line is the number of songs in the album, then one song with data on each line until the album is finished, then the album name of the next album etc. To make things more fun, the list is it's own class, the album it's own class and the songs their own class.文本文件由专辑及其歌曲组成,第一行是专辑名称,第二行是专辑中的歌曲数,然后每行有一首歌曲,直到专辑完成,然后是专辑的专辑名称下一张专辑等等。为了让事情更有趣,列表是它自己的 class,专辑它自己的 class 和歌曲他们自己的 class。 Here is an example of what the file can look like这是文件的外观示例

Album name1

2

song1|artist1|234

song2|artist1|443

Album name2

3

song3|artist2|320

song4|artist2|360

song5|artist2|340

My problem is that when I load, the first album will be loaded correctly, but the second album (and third etc) will not have the full name loaded, it will miss the first character.我的问题是,当我加载时,第一张专辑会正确加载,但第二张专辑(和第三张等)不会加载全名,它会错过第一个字符。 So Album name2 would be loaded as lbum name2.所以专辑名称 2 将作为 lbum 名称 2 加载。

This is the classes involved with the functions and overloads that are used in doing this:这是用于执行此操作的函数和重载所涉及的类:

#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;
}

I add the song class here eventhough I don't think it's necessary as it seems to function as intended我在这里添加歌曲 class 尽管我认为没有必要,因为 function 似乎符合预期

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;
}

Thanks for any help.谢谢你的帮助。 I just can't find the reason for this to happen myself.我只是找不到自己发生这种情况的原因。

In your function在你的 function

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() will consume newline characters and the final is.get() will consume the next character from the stream. std::getline()将使用换行符,最后的is.get()将使用 stream 中的下一个字符。 It seems what is consumed here is the first character of the title of the next album.看来这里消耗的是下一张专辑标题的第一个字符。

To avoid this, you should remove this extra is.get();为避免这种情况,您应该删除这个额外的is.get(); . .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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