我过去曾经使用过这个网站,从来没有真正发布过一个问题,但我不确定如何简单地说出来。我在Devry的C ++课程中,我项目的实际作业需求方面已经完成,但我正在为练习添加一些元素。
因此,为了完成家庭作业,我又添加了一个名为Song的课程。它有2个私有变量(标题和长度),一些基本构造函数和=和==的操作重载。一切正常。然后我将一个Song类的数组添加到Cd类(每个Cd的最大歌曲数为10)。我为Cd创建了一些新的方法:
根据选择的数量按顺序写出歌曲。现在,选择和播放时间的Cd私有值分别与歌曲的总数和这些歌曲的总长度相关联。一切正常。 removeSong将指定的歌曲从列表中取出,然后调用organizeSong将剩余的歌曲设置为数组中的最低值。然而,似乎无论我在哪里调用removeSong(Song s),它都会在任何事物写入程序之前删除它。 因此,以下代码将从Cd中提取信息,但只有一首歌,尽管在Report方法之后调用了removeSong方法。任何人都有任何想法,为什么会这样?
Song s1("Hey Jude", 4.52);
Song s2("The song of Pie", 3.14);
Cd c1 ("Beatles", "Capitol");
c1.addSong(s1);
c1.addSong(s2);
cout<< "Using object directly: \n";
c1.Report();
c1.removeSong(s1);
报告方法如下所示:
void Cd::Report () const
{
cout<< "Performers: " << performers << endl << "Label: " <<label << endl << "Selections: " << selections <<endl << "Playtime: " << playtime << endl;
for(int i = 0; i < selections; i++)
{
cout << "Song " << i+1 << ": " << song[i].getTitle() << " Length: " << song[i].getLength() << endl;
}
}
澄清。我用更多的歌曲测试了这个,没有调用removeSong方法,它会写出数组中的所有歌曲。
编辑* * 我正在添加其余的代码以希望澄清我的问题。我还没有兴趣使它保持线程安全或更高效,除了向我的教师演示继承和类的组合之外,它没有任何目的,它已经超出了我们的任务要求。我很欣赏有关如何使代码更好的评论,并将调查这些内容,但我想弄清楚为什么removeSong在主代码中的removeSong之前报告时会影响Report的输出。我已经测试了不同的方法和重载,它们都按照预期的方式工作,它只是我感兴趣的removeSong发生的时间。它删除了正确的歌曲并正确地重新排列了现有的歌曲,它只是为了很快:在调用第一个报告之前。 (我确实需要在报告中更改大写以保持一致性)。我大多肯定这是一个基本的东西,我在这里缺少新的东西。
主要代码:
// GSP125_Davis_lab4_partA.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <conio.h>
#include "classic.h"
#include <string.h>
///Prototypes
void Bravo(const Cd & disk);
Song s1("Hey Jude", 4.52);
Song s2("the Song of Pie",3.14);
Song s3("National Anthem", 5.55);
char* userInput = "null";
char str[20] = "null";
bool bol_end = false;
int main()
{
Cd c1 ("Beatles", "Capitol");
c1.addSong(s1);
c1.addSong(s2);
c1.addSong(s3);
Cd *pcd = &c1;
Classic c2("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Phillips");
c2.addSong(s2);
c2.addSong(s3);
c2.addSong(s1);
cout << "Using object directly:\n";
//this is where the code seems to have an issue. as you see Report is called
//then after c1.removeSong(s1) is called. s1 is removed properly but this first
// c1.Report() reflects the changes removeSong makes.
c1.Report();
c2.Report();
c1.removeSong(s1);
cout << "Using type Cd method for cd object:\n";
pcd->Report();
pcd = &c2;
pcd-> Report();
cout<< "Calling a function with a Cd reference argument:\n";
Bravo(c1);
Bravo(c2);
cout << "Testing assignment: \n";
Classic copy;
copy = c2;
copy.Report();
cout << "Press any key to continue...";
_getch();
return 0;
}
void Bravo(const Cd & disk)
{
disk.Report();
}
Cd.cpp
#include "StdAfx.h"
#include "cd.h"
Cd::Cd(char * s1, char * s2)
{
strcpy(performers, s1);
strcpy(label, s2);
selections = 0;
playtime = 0;
for(int i = 0; i < songLimit; i++)
{
song[i] = Song();
}
}
Cd::Cd(const Cd & d)
{
strcpy(performers, d.performers);
strcpy(label, d.label);
selections = d.selections;
playtime = d.playtime;
for(int i = 0; i < songLimit; i++)
{
song[i] = d.song[i];
}
}
Cd::Cd()
{
strcpy(performers, "None");
strcpy(label, "No one");
selections = playtime = 0;
for(int i = 0; i < songLimit; i++)
{
song[i] = Song();
}
}
Cd::~Cd(void)
{
}
void Cd::Report () const
{
cout<< "Performers: " << performers << endl << "Label: " <<label << endl << "Selections: " << selections <<endl << "Playtime: " << playtime << endl;
for(int i = 0; i < selections; i++)
{
cout << "Song " << i+1 << ": " << song[i].getTitle() << " Length: " << song[i].getLength() << endl;
}
}
void Cd::addSong(Song s)
{
for (int i = 0; i < songLimit; i++)
{
if (song[i].getTitle() == "none")
{
song[i] = s;
selections++;
playtime+= s.getLength();
break;
}
}
}
void Cd::removeSong(Song s)
{
for (int i = 0; i < songLimit; i++)
{
if(song[i] == s)
{
song[i] = Song();
selections--;
playtime-= s.getLength();
break;
}
}
organizeSong();
}
void Cd::organizeSong()
{
int empty = -1;
for (int i = 0; i < songLimit; i++)
{
if(song[i].getTitle() == "none" && empty == -1)
{
empty = i;
}
else if (empty != -1)
{
song[empty] = song[i];
song[i] = Song();
empty = i;
}
}
}
Cd & Cd::operator=(const Cd & d)
{
strcpy(performers, d.performers);
strcpy(label, d.label);
selections = d.selections;
playtime = d.playtime;
for(int i = 0; i < songLimit; i++)
{
song[i] = d.song[i];
}
return *this;
}
Song.cpp
#include "StdAfx.h"
#include "Song.h"
Song::Song(char* s, double l)
{
title = s;
length = l;
}
Song::Song(const Song & s)
{
title = s.title;
length = s.length;
}
Song::Song()
{
title = "none";
length = 0;
}
Song::~Song(void)
{
}
char* Song::getTitle() const
{
return title;
}
double Song::getLength() const
{
return length;
}
Song & Song::operator=(const Song & s)
{
title = s.title;
length = s.length;
return *this;
}
bool & Song::operator==(const Song & s)
{
bool result = false;
if (title == s.title && length == s.length)
{
result = true;
}
return result;
}
我再次感谢尝试使代码更有效或更有意义,但我已经做了比老师要求我们更多的工作。我只是想知道是否有一个明显的原因,为什么在第一次报告显示之前删除该歌曲,即使报告在代码中排在第一位。
答案 0 :(得分:1)
在不知道你的实现的情况下,很难回答你的问题,所以我按照我想象的那样写了它。不过,我做了一些改进:
3.14
并不代表“3分14秒”。充其量,它意味着3.14分钟,即3分8.4秒。我已将其更改为明确的chrono
原语operator==
,但我无法看到如何合理实施。为每首歌添加一个唯一的ID将是一种解决它的方法,但我觉得没有权利,所以我决定通过索引删除(这也很好地模拟了CD本身)。report
是大写的,但我改变了这一点以保持一致性。我不确定裁谈会内部的重组是如何运作的,所以我只是跳过那部分。
#include <iostream>
#include <list>
#include <functional>
#include <chrono>
#include <string>
#include <stdexcept>
#include <iterator>
// C++14-like shim
// in C++14 just use min and s
constexpr std::chrono::minutes operator "" _min(unsigned long long m) {
return std::chrono::minutes(m);
}
constexpr std::chrono::seconds operator "" _s(unsigned long long s) {
return std::chrono::seconds(s);
}
class Song {
public:
std::string title;
std::chrono::seconds length;
Song(std::string title, std::chrono::seconds length) :
title(std::move(title)), length(length) { }
};
class Cd {
std::list<std::reference_wrapper<Song>> songs;
std::string performer, title;
public:
void addSong(Song & s) {
songs.push_back(std::ref(s));
}
void removeSong(unsigned n) {
if (n >= songs.size())
throw std::out_of_range("The song of given index doesn't exist on that album");
songs.erase(std::next(songs.begin(), n));
}
void report() const {
std::cout << title << ", " << performer << '\n';
for (auto const& song : songs) {
std::cout << song.get().title << " "
<< song.get().length.count() / 60 << ":"
<< song.get().length.count() % 60 << '\n';
}
std::cout << std::endl;
}
Cd(std::string performer, std::string title) :
performer(std::move(performer)), title(std::move(title))
{ }
};
int main() {
Song s1("Hey Jude", 4_min + 52_s);
Song s2("The song of Pie", 3_min + 14_s);
Cd c1 ("Beatles", "Capitol");
c1.addSong(s1);
c1.addSong(s2);
c1.report();
// this doesn't work anymore because of the reasons described above
//c1.removeSong(s1);
c1.removeSong(0);
c1.report();
}