[期中][Deep copy && Shallow Copy] SongList

[Deep copy && Shallow Copy] SongList
实时评测 2021-04-29 16:30 1000 ms 32 MB
Description
Recently, Xiao Ming is developing a music player, which requires model the SongList. He want to implement a simple SongList object. But in the versions he implemented before, the double free or memory leak mistake always show up. As you are excellent C++ developer, he try to ask help from you. He has already written down the declaration of the functions in songList.h. You only need to accomplish the songList.cpp.
小明最近在开发一个音乐播放器,需要对歌单进行建模。他希望实现一个简单的歌单类,但是在之前他自己实现的版本中,总是出现double free或者memory leak的错误,他听闻你C++学得不错,向你求助来了。他在songList.h头文件中已经写好了函数的声明,希望你能在songList.cpp中将定义完善。

Sample Input
The first line is an int variable numSongs, which indicates the number of songList1. And the next numSongs line are the songs’ name.
第一行是一个整型变量numSongs,记录第一个歌单的个数,接下来的numSongs行分别是歌曲名字。

2
We Choose To Go To The Moon
A Lovely Wedding - Snowand Sky

Sample Output
The output will show songList1、songList2、songList3, the songList1will be initiated by the songs in the input and add toAddAndRemoved twice, but the songList should do the elimination so it should be store once. songList2 is copied from songList1 and will remove toAddAndRemoved, songList3 is initiated from songList2 but clear it songs after that, so it shoule be empty.
输出会显示三个歌单,songList1通过输出的歌曲初始化,并添加两次歌曲toAddAndRemoved(Lights Frightened The Captain),但因为去重的原因实际只添加一次。songList2通过songList1拷贝得到,并删除toAddAndRemoved。songList3通过songList2初始化,并清空歌单。

owner:MakaBaka
Songs:
We Choose To Go To The Moon
A Lovely Wedding - Snowand Sky
Lights Frightened The Captain

owner:MakaBaka
Songs:
We Choose To Go To The Moon
A Lovely Wedding - Snowand Sky

MakaBaka's SongList is Empty.

Note
输出运算符重载:

如果歌单为空,则输出<owner>'s SongList is Empty.,其中owner是歌单类的成员变量。
如果歌单不为空,则输出

owner:<owner>
Songs:
<song1>
<song2>
...

Hint
清空歌曲是否需要真的把歌曲删除?
拷贝函数需要考虑什么?
赋值拷贝函数需要考虑哪三件事?
主程序(C/C++)

#ifndef SONGLIST_H
#define SONGLIST_H

#include <string>
#include <iostream>

using namespace std;

class SongList {
    std::string owner;          // 歌单拥有者
    unsigned int size;         // 歌单中有效歌曲的数量
    unsigned int capacity;          // 歌单的最大容量
    std::string *songs;         // 歌曲列表,一个string数组

public:
    // 初始化的歌曲列表中会保证没有重复歌曲
    SongList(const std::string _owner, unsigned int _size, unsigned int _capacity, std::string *_songs);

    SongList(const SongList &songList);

    // 添加歌曲,请考虑去重的情况(如果歌曲已经存在则不添加)、歌单已经满了需要扩容的情况,扩容方案自选
    // 扩容方案1:原地扩容,C语言中有个realloc函数可以实现
    // 扩容方案2:重新开辟一个更大容量songs歌曲列表,并将当前的数据迁移过去
    void addSong(const std::string &song);

    // 删除指定歌曲,歌曲不存在则无动作
    void removeSong(const std::string &song);

    // 清空歌曲
    void clearSong();

    SongList &operator=(const SongList &songList);

    friend ostream &operator<<(ostream &os, const SongList &songList);

    ~SongList();
};

#endif //SONGLIST_H

////////////
#include "source.cpp"

using namespace std;

int main() {
    int numSongs;
    cin >> numSongs;
    getchar();                  //读取换行符
    string name2 = "MakaBaka";
    string *songs = new string[numSongs];
    for (int i = 0; i < numSongs; ++i) {
        getline(cin, songs[i]);
    }
    string toAddAndRemoved = "Lights Frightened The Captain";

    SongList songList1(name2, numSongs, numSongs, songs);
    songList1.addSong(toAddAndRemoved);
    songList1.addSong(toAddAndRemoved);

    SongList songList2(songList1);
    songList2 = songList2;
    songList2.removeSong(toAddAndRemoved);

    SongList songList3 = songList2;
    songList3.clearSong();


    cout << songList1 << endl;
    cout << songList2 << endl;
    cout << songList3 << endl;
    
    delete [] songs;
    return 0;
}

/*
 * 示例输入:
 * 2
 * We Choose To Go To The Moon
 * A Lovely Wedding - Snowand Sky
 *
 * 示例输出:
 * owner:MakaBaka
 * Songs:
 * We Choose To Go To The Moon
 * A Lovely Wedding - Snowand Sky
 * Lights Frightened The Captain
 * 
 * owner:MakaBaka
 * Songs:
 * We Choose To Go To The Moon
 * A Lovely Wedding - Snowand Sky
 * 
 * MakaBaka's SongList is Empty.
 */

答案

//#include "songList.h"


SongList::SongList(std::string _owner, unsigned int _size, unsigned int _capacity, std::string *_songs) : owner(_owner),
                                                                                                       size(_size),
                                                                                                       capacity(_capacity){
    songs = new std::string[capacity];
    for (unsigned int i = 0; i < _size; ++i) {
        songs[i] = _songs[i];
    }
                                                                                                       }


SongList::SongList(const SongList &songList) {
    size = songList.size;
    capacity = songList.capacity;
    owner = songList.owner;
    songs = new std::string[capacity];
    for (unsigned int i = 0; i < size; ++i) {
        songs[i] = songList.songs[i];
    }
}

void SongList::addSong(const std::string &song) {
    for (unsigned int i = 0; i < size; ++i) {
        if (songs[i] == song) {
            return;
        }
    }

    if (size >= capacity) {
        std::string *oldSongs = songs;
        capacity *= 2;
        songs = new std::string[capacity];
        for (unsigned int i = 0; i < size; ++i) {
            songs[i] = oldSongs[i];
        }
        delete[] oldSongs;
    }
    songs[size++] = song;
}

void SongList::removeSong(const std::string &song) {
    for (unsigned int i = 0; i < size; ++i) {
        if (song == songs[i]) {
            for (unsigned int j = i; j + 1 < size; ++j) {
                songs[j] = songs[j + 1];
            }
            --size;
        }
    }
}

void SongList::clearSong() {
    size = 0;
}

ostream &operator<<(ostream &os, const SongList &songList) {
    if (songList.size <= 0) {
        os << songList.owner << "'s SongList is Empty." << endl;
        return os;
    }
    cout << "owner:" << songList.owner << endl;
    cout << "Songs:" << endl;
    for (unsigned int i = 0; i < songList.size; ++i) {
        os << songList.songs[i] << std::endl;
    }
    return os;
}

SongList &SongList::operator=(const SongList &songList) {
    if (&songList != this) {
        delete[] songs;
        size = songList.size;
        capacity = songList.capacity;
        owner = songList.owner;
        songs = new std::string[capacity];
        for (unsigned int i = 0; i < size; ++i) {
            songs[i] = songList.songs[i];
        }
    }

    return *this;
}



SongList::~SongList(){
    delete [] songs;
}

随机测试文本产生程序 (C)

#include "stdio.h"

int main() {
    printf("2\n\
We Choose To Go To The Moon\n\
A Lovely Wedding - Snowand Sky");    
}
上一篇: 10.1 (C++) 下一篇: 9.7 (C++)
支持 makedown语法