안형준

재생목록만들기, 최근추가목록 완성


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project", "Project\Project.vcxproj", "{488DFF6D-08D7-40A9-B10D-AE7374047D99}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Debug|x64.ActiveCfg = Debug|x64
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Debug|x64.Build.0 = Debug|x64
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Debug|x86.ActiveCfg = Debug|Win32
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Debug|x86.Build.0 = Debug|Win32
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Release|x64.ActiveCfg = Release|x64
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Release|x64.Build.0 = Release|x64
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Release|x86.ActiveCfg = Release|Win32
{488DFF6D-08D7-40A9-B10D-AE7374047D99}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {13F536C0-2A1C-46D1-AC75-9315EF6D367F}
EndGlobalSection
EndGlobal
#pragma once
#include<string>
using namespace std;
#include"SimplifiedType.h"
#include"SortedLinkedList.h"
class AlbumType {
public:
AlbumType()
{
AlbumName = "";
ArtistName = "";
} //기본 생성자
~AlbumType()
{
} //기본 소멸자
/**
* @brief AlbumType의 생성자이다.
* @pre x
* @post AlbumType이 생성된다.
@param albumname 앨범명
@param artistname 이 앨범을 낸 아티스트명
*/
AlbumType(string albumname, string artistname)
{
AlbumName = albumname;
ArtistName = artistname;
}
AlbumType(const AlbumType& data)
{
AlbumName = data.AlbumName;
ArtistName = data.ArtistName;
}
/**
* @brief AlbumName 을 set한다.
* @pre x
* @post AlbumName is set
* @return x
*/
void SetAlbumName(string Name)
{
AlbumName = Name;
};
/**
* @brief ArtistName을 set한다.
* @pre x
* @post ArtistName is set
* @return x
*/
void SetArtistName(string Name)
{
ArtistName = Name;
};
/**
* @brief get AlbumName
* @pre AlbumName is set
* @post x
* @return AlbumName
*/
string GetAlbumName()
{
return AlbumName;
};
/**
* @brief getArtistName
* @pre ArtistName is set
* @post x
* @return ArtistName
*/
string GetArtistName()
{
return ArtistName;
};
/**
* @brief 비교 연산자
* @pre 비교하려는 두 앨범타입이 초기화되어 있어야한다
* @post x
* @param data 비교하려는 앨범타입
* @return 좌변이크면 false, 우변이크면 true
*/
bool operator<(AlbumType data)
{
if (AlbumName == data.GetAlbumName())
return (ArtistName < data.GetArtistName());
else
return (AlbumName < data.GetAlbumName());
};
/**
* @brief 비교 연산자
* @pre 비교하려는 두 앨범타입이 초기화되어 있어야한다
* @post x
* @param data 비교하려는 앨범타입
* @return 좌변이크면 true, 우변이크면 false
*/
bool operator>(AlbumType data)
{
if (AlbumName == data.GetAlbumName())
return (ArtistName > data.GetArtistName());
else
return (AlbumName > data.GetAlbumName());
};
/**
* @brief 등위연산자
* @pre 비교하려는 두 앨범타입이 초기화되어 있어야한다
* @post x
* @param data 비교하려는 앨범타입
* @return 두 항이 같으면 true 아니면 false
*/
bool operator==(AlbumType data) {
if (AlbumName == data.GetAlbumName() && ArtistName == data.GetArtistName())
return true;
else
return false;
};
private:
string AlbumName; //앨범 이름을 저장할 변수
string ArtistName; //앨범의 아티스트를 저장할 변수
};
#include"Application.h"
// Program driver.
void Application::Run()
{
while (1)
{
m_Command = GetCommand();
switch (m_Command)
{
case 1: // read a record and add to list.
AddMusic();
break;
case 2: // display all the records in list on screen.
Delete();
break;
case 3:
Update();
break;
case 4: //곡명으로 검색
RetreiveRecordByName();
break;
case 5: //가수명으로 검색
RetreiveRecordBySinger();
break;
case 6: //앨범명으로 검색
RetreiveRecordByAlbum();
break;
case 7: //장르로 검색
RetreiveRecordByGenre();
break;
case 8: // load list data from a file.
DisplayAllMusic();
break;
case 9:
DIsplayNewMusic();
break;
case 10:
DisplayMusicbyGenre();
break;
case 11:
RetreiveRecordByNameNGenre();
break;
case 12:
DisplayMusicByAlbum();
break;
case 13:
DisplayMusicByArtist();
break;
case 20:
makePlayList();
break;
case 21:
AddMusicInPL();
break;
case 22:
PrintPL();
break;
case 98:
ReadDataFromFile();
break;
case 99:
WriteDataToFile();
case 0:
return;
default:
cout << "\tIllegal selection...\n";
break;
}
}
}
// Display command on screen and get a input from keyboard.
int Application::GetCommand()
{
int command;
cout << endl << endl;
cout << "\t---ID -- Command ----- " << endl;
cout << "\t 1 : Add Music" << endl;
cout << "\t 2 : Delete Music" << endl;
cout << "\t 3 : Replace Music" << endl;
cout << "\t 4 : Search by Song Name" << endl;
cout << "\t 5 : Search by Artist(Singer)" << endl;
cout << "\t 6 : Search by Album" << endl;
cout << "\t 7 : Search by Genre" << endl;
cout << "\t 8 : Display all Music" << endl;
cout << "\t 9 : Display New Music" << endl;
cout << "\t 10 : Display Music by Genre" << endl;
cout << "\t 11 : search by Name and Genre" << endl;
cout << "\t 12 : Display Music by Album" << endl;
cout << "\t 13 : Display Music by Artist" << endl;
cout << "\t 20 : 재생목록 만들기" << endl;
cout << "\t 21 : 재생목록에 추가하기" << endl;
cout << "\t 22 : 재생목록 보기" << endl;
cout << "\t 30 : 재생하기" << endl;
cout << "\t 98 : Get from file" << endl;
cout << "\t 99 : Put to file " << endl;
cout << "\t 0 : Quit" << endl;
cout << endl << "\t Choose a Command--> ";
cin >> command;
cout << endl;
return command;
}
// Add new record into list.
int Application::AddMusic()
{
string genre; //장르를 저장할 임시변수
string name; //곡명을 저장할 임시변수
MusicType item;
SimplifiedType Simpletype; //곡번호, 곡명만 저장할 타입
item.SetInfoFromKB();
m_List.Add(item); //MusicList에 원소 추가
RemakeSubList(); //MusicList에 변화가 생겼으므로 하위 리스트들을 다시 만들어줘야 한다.
SetMusicIndex(); //MusicList에 변화가 생겼으므로 Index를 다시 부여한다.
DoublyIter<MusicType> Miter(m_List);
ManageType mgitem;
while (Miter.NotNull())
{
if (Miter.GetCurrentNode().data == item)
{
mgitem.setIndex(Miter.GetCurrentNode().data.GetNum());
}
Miter.Next();
}
mgitem.setName(item.GetName());
mgitem.setPkey(item.GetPkey());
mgitem.setArtist(item.GetSinger());
mg_List.Add(mgitem);
//최근 추가목록에 추가하기
/*
Simpletype.SetRecord(num, name);
if (!AddRecentlyMusicList.IsFull()) //최근 추가된목록이 가득차지 않았을경우
AddRecentlyMusicList.EnQueue(Simpletype); //큐에 하나 추가
else //최근 추가된목록이 30개 꽉 찼을경우
{
SimplifiedType S_temp;
AddRecentlyMusicList.DeQueue(S_temp); //하나를 지우고
AddRecentlyMusicList.EnQueue(Simpletype); //방금 추가된 레코드를 집어넣는다
}
*/
// 현재 list 출력
DisplayAllMusic();
return 1;
}
// Display all records in the list on screen.
void Application::DisplayAllMusic()
{
DoublyIter<MusicType> iter(m_List);
cout << "\n\tCurrent list" << endl;
// list의 모든 데이터를 화면에 출력
while (iter.NotNull())
{
iter.GetCurrentNode().data.DisplayRecordOnScreen();
iter.Next();
}
}
//찾을 ID를 사용자에게 입력받고 SortedList의 Delete함수를 호출한다.
void Application::Delete()
{
cout << "\t지울 : ";
MusicType data; //Delete함수는 MusicType을 파라미터로 갖기 때문에 임의로 만들어준다.
data.SetNumFromKB(); //사용자에게서 곡 번호를 입력받는다.
SearchByIndex(data);
if (m_List.Delete(data)) //Delete함수에 data를 넘겨준다.
{
cout << "\t삭제를 완료했습니다." << endl; //삭제에 성공했으면 메시지를 출력한다.
RemakeSubList(); //MusicList에 변화가 생겼으므로 하위 리스트들을 다시 만들어줘야 한다.
if (m_List.GetLength() != 0) //길이가 0이면 인덱스를 부여할수 없다.
{
SetMusicIndex();//MusicList에 변화가 생겼으므로 Index를 다시 부여한다.
}
}
else
cout << "\t삭제하지 못했습니다. 일치하는 항목을 찾을 수 없습니다." << endl; //삭제에 실패했으면 메시지를 출력한다.
}
//찾을 ID를 사용자에게 입력받고 SortedList의 Update함수를 호출한다.
void Application::Update()
{
cout << "\t변경을 원하는 항목의 ";
MusicType data; //Replace함수는 MusicType을 파라미터로 갖기 때문에 임의로 만들어준다.
data.SetNumFromKB(); //사용자에게서 수정할 항목의 곡 번호를 입력받는다.
SearchByIndex(data);
if (!m_List.Get(data)) //사용자가 입력한 항목이 List에 있나 검색
{
cout << "\t항목을 찾을 수 없습니다." << endl; //찾을 수 없을때 메시지를 출력한다.
return;
}
else //찾을 수 있을때
{
data.SetNameFromKB(); //사용자에게서 곡명을 입력받는다.
data.SetSingerFromKB(); //사용자에게서 가수를 입력받는다.
data.SetAlbumFromKB(); //사용자에게서 앨범을 입력받는다.
data.SetGenreFromKB(); //사용자에게서 장르를 입력받는다.
data.SetLyricsFromKB(); // 사용자에게서 가사를 입력받는다.
if (m_List.Delete(data))//기존 항목을 삭제하고
{
data.SetPkey(); //데이터를 변경했으므로 Pkey를 다시 지정해준다.
m_List.Add(data);
cout << "\t수정을 완료했습니다." << endl; //수정을 성공했을 때 메시지를 출력한다.
RemakeSubList(); //MusicList에 변화가 생겼으므로 하위 리스트들을 다시 만들어줘야 한다.
if (m_List.GetLength() != 0) //길이가 0이면 인덱스를 부여할수 없다.
{
SetMusicIndex();//MusicList에 변화가 생겼으므로 Index를 다시 부여한다.
}
}
else
cout << "\t수정을 실패했습니다." << endl; //수정에 실패했을 때 메시지를 출력한다.
}
}
//사용자에게 찾고자하는 Name을 입력받고 넘겨주는 역할을 한다.
void Application::RetreiveRecordByName()
{
MusicType temp;
cout << "\t찾을 ";
temp.SetNameFromKB(); //SearchByName함수에 넘겨줄 temp의 Name을 사용자에게 입력받는다.
SearchByName(temp); //실질적으로 찾는 동작을 하는 SearchByName함수를 호출하고 temp값을 넘겨준다.
}
//사용자가 찾고자하는 Name을 포함하는 inData로 m_List의 항목들 중 일치하는 항목을 찾고 출력해준다. **프로그램에 전반적으로 Array에 index를 직접 접근하는 방법을 선호했으나 이 함수는 Application 클래스의 메소드이므로 GetNextItem함수를 이용해 iteration을 이용했습니다.
void Application::SearchByName(MusicType &inData)
{
MusicType temp; //m_List의 값을 비교해주기 위한 임시 MusicType.
DoublyIter<MusicType> iter(m_List);
int count = 0;
while (iter.NotNull())
{
if (iter.GetCurrentNode().data.GetName().find(inData.GetName()) != -1)
{
iter.GetCurrentNode().data.DisplayRecordOnScreen();
count++;
}
iter.Next();
}
if (count == 0)
cout << "\t찾을 수 없습니다." << endl; //찾은 개수가 0개이면 찾을 수 없다는 메시지를 출력한다.
}
//사용자에게 찾고자하는 Singer을 입력받고 넘겨주는 역할을 한다.
void Application::RetreiveRecordBySinger()
{
MusicType temp;
cout << "\t찾을 ";
temp.SetSingerFromKB(); //SearchBySinger함수에 넘겨줄 temp의 Name을 사용자에게 입력받는다.
SearchBySinger(temp); //실질적으로 찾는 동작을 하는 SearchBySinger함수를 호출하고 temp값을 넘겨준다.
}
//사용자가 찾고자하는 Singer을 포함하는 inData로 m_List의 항목들 중 일치하는 항목을 찾고 출력해준다. **프로그램에 전반적으로 Array에 index를 직접 접근하는 방법을 선호했으나 이 함수는 Application 클래스의 메소드이므로 GetNextItem함수를 이용해 iteration을 이용했습니다.
void Application::SearchBySinger(MusicType &inData)
{
MusicType temp; //m_List의 값을 비교해주기 위한 임시 MusicType.
DoublyIter<MusicType> iter(m_List);
int count = 0;
while (iter.NotNull())
{
if (iter.GetCurrentNode().data.GetSinger().find(inData.GetSinger()) != -1)
{
iter.GetCurrentNode().data.DisplayRecordOnScreen();
count++;
}
iter.Next();
}
if (count == 0)
cout << "\t찾을 수 없습니다." << endl; //찾은 개수가 0개이면 찾을 수 없다는 메시지를 출력한다.
}
//사용자에게 찾고자하는 Album을 입력받고 넘겨주는 역할을 한다.
void Application::RetreiveRecordByAlbum()
{
MusicType temp;
cout << "\t찾을 ";
temp.SetAlbumFromKB(); //SearchByAlbum함수에 넘겨줄 temp의 Album을 사용자에게 입력받는다.
SearchByAlbum(temp); //실질적으로 찾는 동작을 하는 SearchByAlbum함수를 호출하고 temp값을 넘겨준다.
}
//사용자가 찾고자하는 Album을 포함하는 inData로 m_List의 항목들 중 일치하는 항목을 찾고 출력해준다. **프로그램에 전반적으로 Array에 index를 직접 접근하는 방법을 선호했으나 이 함수는 Application 클래스의 메소드이므로 GetNextItem함수를 이용해 iteration을 이용했습니다.
void Application::SearchByAlbum(MusicType &inData)
{
if (m_List.IsEmpty() == true)
{
cout << "리스트에 아무것도 없습니다." << endl;
return;
}
MusicType temp; //m_List의 값을 비교해주기 위한 임시 MusicType.
DoublyIter<MusicType> iter(m_List);
int count = 0;
while (iter.NotNull())
{
if (iter.GetCurrentNode().data.GetAlbum().find(inData.GetAlbum()) != -1)
{
iter.GetCurrentNode().data.DisplayRecordOnScreen();
count++;
}
iter.Next();
}
if (count == 0)
cout << "\t찾을 수 없습니다." << endl; //찾은 개수가 0개이면 찾을 수 없다는 메시지를 출력한다.
}
//사용자에게 찾고자하는 Genre을 입력받고 넘겨주는 역할을 한다.
void Application::RetreiveRecordByGenre()
{
MusicType temp;
cout << "\t찾을 ";
temp.SetGenreFromKB(); //SearchByGenre함수에 넘겨줄 temp의 Genre을 사용자에게 입력받는다.
SearchByGenre(temp); //실질적으로 찾는 동작을 하는 SearchByGenre함수를 호출하고 temp값을 넘겨준다.
}
//사용자가 찾고자하는 Genre을 포함하는 inData로 m_List의 항목들 중 일치하는 항목을 찾고 출력해준다. **프로그램에 전반적으로 Array에 index를 직접 접근하는 방법을 선호했으나 이 함수는 Application 클래스의 메소드이므로 GetNextItem함수를 이용해 iteration을 이용했습니다.
void Application::SearchByGenre(MusicType &inData)
{
if (m_List.IsEmpty() == true)
{
cout << "리스트에 아무것도 없습니다." << endl;
return;
}
MusicType temp; //m_List의 값을 비교해주기 위한 임시 MusicType.
DoublyIter<MusicType> iter(m_List);
int count = 0;
while (iter.NotNull())
{
if (iter.GetCurrentNode().data.GetGenre().find(inData.GetGenre()) != -1)
{
iter.GetCurrentNode().data.DisplayRecordOnScreen();
count++;
}
iter.Next();
}
if (count == 0)
cout << "\t찾을 수 없습니다." << endl; //찾은 개수가 0개이면 찾을 수 없다는 메시지를 출력한다.
}
// Open a file by file descriptor as an input file.
int Application::OpenInFile(char *fileName)
{
m_InFile.open(fileName); // file open for reading.
// 파일 오픈에 성공하면 1, 그렇지 않다면 0을 리턴.
if (!m_InFile) return 0;
else return 1;
}
// Open a file by file descriptor as an output file.
int Application::OpenOutFile(char *fileName)
{
m_OutFile.open(fileName); // file open for writing.
// 파일 오픈에 성공하면 1, 그렇지 않다면 0을 리턴.
if (!m_OutFile) return 0;
else return 1;
}
// Open a file as a read mode, read all data on the file, and set list by the data.
int Application::ReadDataFromFile()
{
MusicType data; // 읽기용 임시 변수
ifstream ReadData;
ReadData.open("text.txt");
string OneLine;
while (getline(ReadData, OneLine))
{
istringstream L(OneLine);
string name, singer, Album, Genre, Lyrics;
L >> name;
L >> singer;
L >> Album;
L >> Genre;
L >> Lyrics;
data.SetRecord(name, singer, Album, Genre, Lyrics);
m_List.Add(data);
}
/*
char fileName[FILENameSIZE];
cout << "\n\tEnter Input file Name : ";
cin >> fileName;
// file open, open error가 발생하면 0을 리턴
if (!OpenInFile(fileName))
return 0;
// 파일의 모든 내용을 읽어 list에 추가
while (!m_InFile.eof())
{
// array에 학생들의 정보가 들어있는 structure 저장
data.ReadDataFromFile(m_InFile);
m_List.Add(data);
}
m_InFile.close(); // file close
*/
SetMusicIndex();
// 현재 list 출력
DisplayAllMusic();
return 1;
}
// Open a file as a write mode, and write all data into the file,
int Application::WriteDataToFile()
{
m_OutFile.close(); // file close
return 1;
}
//최근 추가된 30곡 출력
void Application::DIsplayNewMusic()
{
if (m_List.IsEmpty() == true)
{
cout << "리스트에 아무것도 없습니다." << endl;
return;
}
int cnt = 0;
DoublyIter2<ManageType> Mgiter(mg_List);
Mgiter.Last();
while (Mgiter.NotNull() && cnt < 30)
{
Mgiter.GetCurrentNode().data.PrintNameNIndex();
Mgiter.Prev();
cnt++;
}
}
bool Application::Search(int key, MusicType& inData)
{
inData.SetNum(key);
if (m_List.Get(inData))
return true;
else
return false;
}
//Display Music by genre through genre list
void Application::DisplayMusicbyGenre()
{
if (m_List.GetLength() == 0)
return;
if (RemakeGenreList == true)
{
GenreList.MakeEmpty(); //기존의 리스트를 비운다
DoublyIter<MusicType> Miter(m_List);
while (Miter.NotNull())
{
string thisGenre;
thisGenre = Miter.GetCurrentNode().data.GetGenre();
GenreList.Add(thisGenre);
Miter.Next();
} //이 반복문이 끝나면 장르리스트에 장르가 정렬되어 들어감
}
RemakeGenreList = false; //리스트를 다시 만들었으므로 변경이 없으면 다시 만들필요가 없다
//아래는 출력하는 코드
DoublyIter<string> Giter(GenreList);
string thisGenre;
while (Giter.NotNull())
{
thisGenre = Giter.GetCurrentNode().data;
DoublyIter<MusicType> Miter2(m_List);
cout << "\t장르 : " << Miter2.GetCurrentNode().data.GetGenre() << endl;
while (Miter2.NotNull())
{
if (thisGenre == Miter2.GetCurrentNode().data.GetGenre())
{
cout << "트랙넘버 : " << Miter2.GetCurrentNode().data.GetName() << endl;
cout << "곡명 : " << Miter2.GetCurrentNode().data.GetName() << endl;
}
Miter2.Next();
}
cout << "\t -------------------------" << endl;
Giter.Next();
}
}
//name 과 genre 정보를 받아 Search함수에 넘긴다.
void Application::RetreiveRecordByNameNGenre()
{
MusicType temp;
cout << "\t찾을 ";
temp.SetNameFromKB();
temp.SetGenreFromKB(); //SearchByGenre함수에 넘겨줄 temp의 Genre을 사용자에게 입력받는다.
SearchByNameNGenre(temp); //실질적으로 찾는 동작을 하는 SearchByGenre함수를 호출하고 temp값을 넘겨준다.
}
void Application::SearchByNameNGenre(MusicType& inData)
{
if (m_List.IsEmpty() == true)
{
cout << "리스트에 아무것도 없습니다." << endl;
return;
}
MusicType temp; //m_List의 값을 비교해주기 위한 임시 MusicType.
DoublyIter<MusicType> iter(m_List);
int count = 0;
while (iter.NotNull())
{
if (iter.GetCurrentNode().data.GetName().find(inData.GetName()) != -1 && iter.GetCurrentNode().data.GetGenre().find(inData.GetGenre()) != -1)
{
iter.GetCurrentNode().data.DisplayRecordOnScreen();
count++;
}
iter.Next();
}
if (count == 0)
cout << "\t찾을 수 없습니다." << endl; //찾은 개수가 0개이면 찾을 수 없다는 메시지를 출력한다.
}
void Application::DisplayMusicByAlbum()
{
if (m_List.GetLength() == 0)
return;
//쉽게 구현하기
if (RemakeAlbumList == true) //앨범 리스트를 다시만들어야 하는가
{
AlbumList.MakeEmpty();
DoublyIter<MusicType> Miter(m_List);
while (Miter.NotNull())
{
AlbumType thisAlbum(Miter.GetCurrentNode().data.GetAlbum(), Miter.GetCurrentNode().data.GetSinger());
AlbumList.Add(thisAlbum);
Miter.Next();
}
}
RemakeAlbumList = false; //리스트를 갱신했으므로 다시만들 필요가 없다.
//여기서부터는 출력코드
DoublyIter<AlbumType> Abiter(AlbumList);
while (Abiter.NotNull())
{
DoublyIter<MusicType> Miter2(m_List);
cout << "\t앨범명 : " << Abiter.GetCurrentNode().data.GetAlbumName() << endl;
cout << "\t아티스트명 : " << Abiter.GetCurrentNode().data.GetArtistName() << endl;
while (Miter2.NotNull())
{
if (Miter2.GetCurrentNode().data.GetAlbum() == Abiter.GetCurrentNode().data.GetAlbumName() && Miter2.GetCurrentNode().data.GetSinger() == Abiter.GetCurrentNode().data.GetArtistName())
{
cout << "\t트랙넘버 : " << Miter2.GetCurrentNode().data.GetName() << endl;
cout << "\t곡명 : " << Miter2.GetCurrentNode().data.GetName() << endl;
}
Miter2.Next();
}
cout << "\t-------------------------" << endl;
Abiter.Next();
}
}
void Application::DisplayMusicByArtist()
{
if (m_List.GetLength() == 0)
return;
if (RemakeArtistList == true) //아티스트 리스트를 다시 만들어야 하는가
{
ArtistList.MakeEmpty();
AlbumList.MakeEmpty(); //아티스트 리스트와 앨범리스트를 비운다
DoublyIter<MusicType> Miter(m_List);
while (Miter.NotNull())
{
ArtistType thisArtist;
thisArtist.SetArtistName(Miter.GetCurrentNode().data.GetSinger());
ArtistList.Add(thisArtist);
Miter.Next();
}//아티스트리스트에 아티스트가 정렬되어 삽입된다.
DoublyIter<MusicType> Miter2(m_List);
while (Miter2.NotNull())
{
AlbumType thisAlbum(Miter2.GetCurrentNode().data.GetAlbum(), Miter2.GetCurrentNode().data.GetSinger());
AlbumList.Add(thisAlbum);
Miter2.Next();
}
//AlbumList에 앨범추가됨
DoublyIter<AlbumType> Abiter(AlbumList); //앨범을 해당 앨범과 같은 아티스트를 가진 아티스트 타입의 리스트에 추가한다.
while (Abiter.NotNull())
{
DoublyIter<ArtistType> Atiter(ArtistList);
while (Atiter.NotNull())
{
if (Atiter.GetCurrentNode().data.GetArtistName() == Abiter.GetCurrentNode().data.GetArtistName())
{
ArtistType* temp;
temp = Atiter.GetCurrentPtr();
AlbumType thisAlbum = Abiter.GetCurrentNode().data;
temp->AddListinList(thisAlbum);
}
Atiter.Next();
}
Abiter.Next();
}
}
RemakeArtistList = false; //리스트를 갱신했으므로 다시만들 필요가 없다.
//여기서부턴 출력코드
DoublyIter<ArtistType> Atiter2(ArtistList);
while (Atiter2.NotNull())
{
ArtistType *Atptr;
Atptr = Atiter2.GetCurrentPtr();
Atptr->PrintListinList();
Atiter2.Next();
}
}
void Application::SetMusicIndex()
{
int Index = 1;
DoublyIter<MusicType> Miter(m_List);
while (Miter.NotNull())
{
MusicType* Mptr;
Mptr = Miter.GetCurrentPtr();
Mptr->SetNum(Index);
Index++;
Miter.Next();
}
//List의 끝까지 인덱스를 부여한다. 인덱스의 최대값은 MusicList의 길이이다.
}
void Application::SearchByIndex(MusicType &indata)
{
DoublyIter<MusicType> Miter(m_List);
int Index = indata.GetNum();
while (Miter.NotNull())
{
if (Index == Miter.GetCurrentNode().data.GetNum())
Miter.GetCurrentNode().data.DisplayRecordOnScreen();
Miter.Next();
}
}
void Application::makePlayList()
{
string N;
PLType PL;
cout << "재생목록 이름 :";
cin >> N;
PL.setPLname(N);
PlayLists.Add(PL);
}
void Application::AddMusicInPL()
{
DoublyIter2<PLType> PLiter(PlayLists);
while (PLiter.NotNull())
{
cout << "재생목록명 : " << PLiter.GetCurrentNode().data.getPLname();
cout << endl;
PLiter.Next();
}
string N;
cout << "추가하고자 하는 재생목록 선택 : " << endl;
cin >> N;
DoublyIter2<PLType> PLiter2(PlayLists);
PLType* ptr;
while (PLiter2.NotNull())
{
if (PLiter2.GetCurrentNode().data.getPLname() == N)
{
ptr = PLiter2.GetCurrentPtr();
DisplayAllMusic();
int num = 1;
while (1)
{
cout << "추가하고자 하는 곡의 Index를 입력해주세요 0을 입력하면 그만 추가합니다" << endl;
cin >> num;
if (num > m_List.GetLength() || num == 0)
break;
DoublyIter2<ManageType> Mgiter(mg_List);
ManageType* mgPtr;
while (Mgiter.NotNull())
{
if (Mgiter.GetCurrentNode().data.getIndex() == num)
{
mgPtr = Mgiter.GetCurrentPtr();
ptr->AddListinList(mgPtr);
}
Mgiter.Next();
}
}
}
PLiter2.Next();
}
}
void Application::PrintPL()
{
DoublyIter2<PLType> PLiter(PlayLists);
while (PLiter.NotNull())
{
cout << "재생목록명 : " << PLiter.GetCurrentNode().data.getPLname();
cout << endl;
PLiter.Next();
}
string N;
cout << "재생목록 선택 : " << endl;
cin >> N;
DoublyIter2<PLType> PLiter2(PlayLists);
PLType* ptr;
while (PLiter2.NotNull())
{
if (PLiter2.GetCurrentNode().data.getPLname() == N)
{
ptr = PLiter2.GetCurrentPtr();
ptr->Printall();
while (1)
{
int temp;
cout << "재생할 곡을 선택해주세요 0을 입력하면 재생목록에서 나갑니다" << endl;
cin >> temp;
if (temp == 0)
break;
}
}
PLiter2.Next();
}
}
\ No newline at end of file

#ifndef _APPLICATION_H
#define _APPLICATION_H
#include <iostream>
#include <fstream>
#include <string>
#include<sstream>
using namespace std;
#include "MusicType.h"
#include"SortedLinkedList.h"
#include"GenreType.h"
#include"AlbumType.h"
#include"ArtistType.h"
#include"ManageType.h"
#include"UnSortedLinkedList.h"
#include"PLType.h"
#define FILENameSIZE 1024
/**
* application class for item management simply.
*/
class Application
{
public:
/**
* default constructor.
*/
Application()
{
m_Command = 0;
RemakeAlbumList = true;
RemakeArtistList = true;
RemakeGenreList = true;
NumofPL = 0;
}
/**
* destructor.
*/
~Application()
{
DoublyIter<ArtistType> Atiter(ArtistList);
while (Atiter.NotNull())
{
ArtistType* Atptr = Atiter.GetCurrentPtr();
Atptr->MakeEmptyListinList();
Atiter.Next();
}
m_List.MakeEmpty();
GenreList.MakeEmpty();
AlbumList.MakeEmpty();
};
/**
* @brief Program driver.
* @pre program is started.
* @post program is finished.
*/
void Run();
/**
* @brief Display command on screen and get a input from keyboard.
* @pre none.
* @post none.
* @return user's command.
*/
int GetCommand();
/**
* @brief Add new record into list.
* @pre list should be initialized.
* @post new record is added into the list.
* @return return 1 if this function works well, otherwise 0.
*/
int AddMusic();
/**
* @brief Display all records in the list on screen.
* @pre none.
* @post none.
*/
void DisplayAllMusic();
/**
* @brief Open a file by file descriptor as an input file.
* @pre a file for reading is exist.
* @post open the file for reading.
* @param fileName a fileName to open for reading.
* @return return 1 if this function works well, otherwise 0.
*/
int OpenInFile(char *fileName);
/**
* @brief Open a file by file descriptor as an output file.
* @pre list should be initialized.
* @post open the file for writing.
* @param fileName a fileName to open for writing.
* @return return 1 if this function works well, otherwise 0.
*/
int OpenOutFile(char *fileName);
/**
* @brief Open a file as a read mode, read all data on the file, and set list by the data.
* @pre The file is not opened.
* @post list holds all records from the file.
* @return return 1 if this function works well, otherwise 0.
*/
int ReadDataFromFile();
/**
* @brief Open a file as a write mode, and write all data into the file,
* @pre The file is not opened.
* @post the list is stored in the output file.
* @return return 1 if this function works well, otherwise 0.
*/
int WriteDataToFile();
/**
* @brief 객체를 생성 후, 문자열을 입력받는다.
* @pre 없다.
* @post SearchByName함수에 문자열이 설정된 객체를 전달한다.
* @return 없다.
*/
void RetreiveRecordByName();
/**
* @brief inData의 이름 부분을 포함하는 문자열을 찾아 출력한다.
* @pre inData의 이름 부분이 초기화되어있어야 한다.
* @post inData에 알맞은 항목이 복사된다.
* @param inData 이름이 설정되어있고 나머지는 비어있는 Musictype
* @return 없다.
*/
void SearchByName(MusicType &inData);
/**
* @brief 객체를 생성 후, 문자열을 입력받는다.
* @pre 없다.
* @post SearchBySinger함수에 문자열이 설정된 객체를 전달한다.
* @return 없다.
*/
void RetreiveRecordBySinger();
/**
* @brief inData의 이름 부분을 포함하는 문자열을 찾아 출력한다.
* @pre inData의 이름 부분이 초기화되어있어야 한다.
* @post inData에 알맞은 항목이 복사된다.
* @param inData 이름이 설정되어있고 나머지는 비어있는 Musictype
* @return 없다.
*/
void SearchBySinger(MusicType &inData);
/**
* @brief 객체를 생성 후, 문자열을 입력받는다.
* @pre 없다.
* @post SearchByAlbum함수에 문자열이 설정된 객체를 전달한다.
* @return 없다.
*/
void RetreiveRecordByAlbum();
/**
* @brief inData의 이름 부분을 포함하는 문자열을 찾아 출력한다.
* @pre inData의 이름 부분이 초기화되어있어야 한다.
* @post inData에 알맞은 항목이 복사된다.
* @param inData 이름이 설정되어있고 나머지는 비어있는 Musictype
* @return 없다.
*/
void SearchByAlbum(MusicType &inData);
/**
* @brief 객체를 생성 후, 문자열을 입력받는다.
* @pre 없다.
* @post SearchByGenre함수에 문자열이 설정된 객체를 전달한다.
* @return 없다.
*/
void RetreiveRecordByGenre();
/**
* @brief inData의 이름 부분을 포함하는 문자열을 찾아 출력한다.
* @pre inData의 이름 부분이 초기화되어있어야 한다.
* @post inData에 알맞은 항목이 복사된다.
* @param inData 이름이 설정되어있고 나머지는 비어있는 Musictype
* @return 없다.
*/
void SearchByGenre(MusicType &inData);
/**
* @brief inData의 Index와 같은 Index를 가진 MusicList의 정보를 찾아온다
* @pre inData의 Index가 초기화 되어 있어야 한다.
* @post inData에 알맞은 항목이 복사된다.
* @param inData Index가 설정되어있고 나머지는 비어있는 Musictype
* @return 없다.
*/
void SearchByIndex(MusicType &indata);
/**
* @brief 사용자에게 Name을 입력받아 SortedList의 Delete함수에 넘겨주는 역할을 한다.
* @pre 없다.
* @post 사용자가 입력한 Name을 가지고 있는 Musictype이 m_List에서 사라진다.
* @return 없다.
*/
void Delete();
/**
* @brief 사용자에게 Name을 입력받아 SortedList의 Replace함수에 넘겨주는 역할을 한다.
* @pre 없다.
* @post 사용자가 입력한 Name을 가지고 있는 MusicType을 다시 입력받아 갱신한다.
* @return 없다.
*/
void Update();
/**
* @brief 최근에 추가된 30곡의 자세한 정보를 화면에 출력
* @pre 없다.
* @post 없다.
* @return 없다.
*/
void DIsplayNewMusic();
/**
* @brief Primary key를 이용해 원하는 음악정보가져온다.
* @pre 리스트가 초기화되어야함.
* @post inData에 원하는 곡정보가 담김
* @return 찾으면 1, 아니면 0
* @param key 곡번호를 찾기위한 int형 변수
* @inData 원하는 곡의 정보를 받아오기 위한 변수
*/
bool Search(int key, MusicType& inData);
/**
* @brief 장르 리스트에 있는 곡들을 장르에 맞춰 출력
* @pre 없다.
* @post 없다.
* @return 없다.
*/
void DisplayMusicbyGenre();
/**
* @brief 객체를 생성 후, 문자열을 입력받는다.
* @pre 없다.
* @post SearchByNameNGenre함수에 문자열이 설정된 객체를 전달한다.
* @return 없다.
*/
void RetreiveRecordByNameNGenre();
/**
* @brief inData의 이름 부분을 포함하는 문자열을 찾아 출력한다.
* @pre inData의 이름 부분이 초기화되어있어야 한다.
* @post inData에 알맞은 항목이 복사된다.
* @param inData 이름이 설정되어있고 나머지는 비어있는 Musictype
* @return 없다.
*/
void SearchByNameNGenre(MusicType &inData);
/**
* @brief MusicList에 있는 곡을 앨범별로 출력한다.
* @pre 없다.
* @post 없다.
* @return 없다.
*/
void DisplayMusicByAlbum();
/**
* @brief MusicList에 있는 곡을 아티스트별로 나누고, 각 아티스트별 로 앨범을 분류하여 출력한다.
* @pre 없다.
* @post 없다.
* @return 없다.
*/
void DisplayMusicByArtist();
/**
* @brief MusicList에 있는 곡을 Primary Key에 따라 정렬된 순서에 따라 Index를 부여한다
* @pre MusicList에 최소한 하나이상의 곡이 있어야한다.
* @post MusicList의 각 MusicType에 Index가 부여된다
* @return 없다.
*/
void SetMusicIndex();
/**
* @brief MusicList의 Music을 분류하는 하위리스트들을 다시 만들기 위한 조건을 충족시킨다.
* @pre 곡이 추가되거나, 삭제되거나, 변경되어야 한다.
* @post Remake~~List 형의 변수의 값이 모두 true가 된다.
* @return 없다.
*/
void RemakeSubList()
{
RemakeAlbumList = true;
RemakeArtistList = true;
RemakeGenreList = true;
};
void makePlayList();
void AddMusicInPL();
void PrintPL();
private:
ifstream m_InFile; ///< input file descriptor.
ofstream m_OutFile; ///< output file descriptor.
SortedLinkedList<MusicType> m_List; /// 노래 리스트
UnSortedLinkedList<ManageType> mg_List;
int m_Command; ///< current command number.
SortedLinkedList<AlbumType> AlbumList; //앨범을 분류하기 위한 앨범리스트
SortedLinkedList<ArtistType> ArtistList; //아티스트를 분류하기 위한 아티스트리스트
SortedLinkedList <string> GenreList; //장르를 분류하기 위한 장르 리스트
UnSortedLinkedList<PLType> PlayLists;
//아래의 변수들은 각 하위 리스트를 다시만들어야 할지 판별하는 변수이다.
bool RemakeAlbumList;
bool RemakeArtistList;
bool RemakeGenreList;
int NumofPL;
};
#endif // _APPLICATION_H
#include"ArtistType.h"
void ArtistType::PrintListinList()
{
DoublyIter<AlbumType> Abiter(AlbumList);
cout << "\t ----------------" << endl;
cout << "\t ƼƮ : " << ArtistName << endl;
while (Abiter.NotNull())
{
cout << "\tٹ" << Abiter.GetCurrentNode().data.GetAlbumName() << endl;
Abiter.Next();
}
}
ArtistType::ArtistType(const ArtistType& data)
{
ArtistName = data.ArtistName;
AlbumList = data.AlbumList;
}
\ No newline at end of file
#pragma once
#include"AlbumType.h"
using namespace std;
class ArtistType {
public:
ArtistType()
{
ArtistName = "";
}
; //기본 생성자
~ArtistType()
{
AlbumList.MakeEmpty();
}
; //기본 소멸자
ArtistType(const ArtistType& data);
/**
* @brief Get ArtistName
* @pre ArtistName is set
* @post x
* @return ArtistName
*/
string GetArtistName()
{
return ArtistName;
};
/**
* @brief set ArtistName
* @pre x
* @post ArtistName is set
*/
void SetArtistName(string Name)
{
ArtistName = Name;
};
/**
* @brief 비교 연산자
* @pre 비교하려는 두 아티스트타입이 초기화되어 있어야한다
* @post x
* @param data 비교하려는 아티스트타입
* @return 좌변이크면 false, 우변이크면 true
*/
bool operator<(ArtistType data)
{
return (ArtistName < data.GetArtistName());
};
/**
* @brief 비교 연산자
* @pre 비교하려는 두 아티스트타입이 초기화되어 있어야한다
* @post x
* @param data 비교하려는 아티스트타입
* @return 좌변이크면 true, 우변이크면 false
*/
bool operator>(ArtistType data)
{
return (ArtistName > data.GetArtistName());
};
/**
* @brief 등위 연산자
* @pre 비교하려는 두 아티스트타입이 초기화되어 있어야한다
* @post x
* @param data 비교하려는 아티스트타입
* @return 두 항이 같으면 true 아니면 false
*/
bool operator==(ArtistType data)
{
if (ArtistName == data.GetArtistName())
return true;
else
return false;
};
/**
* @brief 대입 연산자
* @pre 패러미터로 넘어오는 Artisttype이 초기화되어있어야한다.
* @post this가 data와 같아진다
* @param data 대입하려는 아티스트타입
* @return *this
*/
ArtistType operator=(const ArtistType& data)
{
ArtistName = data.ArtistName;
AlbumList = data.AlbumList;
return *this;
};
/**
* @brief 리스트안의 리스트에 원소를 추가한다
* @pre x
* @post AlbumList에 앨범이 추가된다.
* @param A 추가하려는 앨범타입
*/
void AddListinList(AlbumType &A)
{
AlbumList.Add(A);
};
/**
* @brief 리스트 안의 리스트의 내용을 출력한다.
* @pre 앨범리스트가 초기화되어 있어야 한다.
* @post x
*/
void PrintListinList() ;
void MakeEmptyListinList()
{
AlbumList.MakeEmpty();
}
private:
SortedLinkedList<AlbumType> AlbumList; //한 아티스트가 가지는 앨범 리스트
string ArtistName;
};
#pragma once
#ifndef _SORTED_LINKED_LIST_H
#define _SORTED_LINKED_LIST_H
#include"SortedLinkedList.h"
template<typename T>
class SortedLinkedList;
template<typename T>
struct NodeType;
template<typename T>
class DoublyIter {
friend class SortedLinkedList<T>;
private:
const SortedLinkedList<T>& m_List;
NodeType<T>* CurPointer;
public:
DoublyIter(const SortedLinkedList<T>& list) : m_List(list), CurPointer(list.m_pList)
{}
/**
* @brief 현재 노드를 가리키는 포인터가 null인지 아닌지 판단하는 메서드.
* @pre Iterator has been initialized.
* @post None.
* @return nullptr true, otherwise false.
*/
bool NotNull();
/**
* @brief 현재 노드 포인터의 다음 노드가 null인지 아닌지 판단하는 메서드.
* @pre Iterator has been initialized.
* @post None.
* @return nullptr true, otherwise false.
*/
bool NextNotNull();
/**
* @brief 현재 노드 포인터의 이전 노드가 null인지 아닌지 판단하는 메서드.
* @pre Iterator has been initialized.
* @post None.
* @return nullptr true, otherwise false.
*/
bool PrevNotNull();
/**
* @brief Get first data of the list.
* @pre Iterator has been initialized.
* @post Current pointer is moved to the first node.
* @return Return first data of the list.
*/
T First();
/**
* @brief Get next data of the current pointer.
* @pre Iterator has been initialized.
* @post Current pointer is moved to the next node.
* @return Return next data of the list.
*/
T Next();
/**
* @brief Get current data of the list and go to the next node. 현재 노드. 객체반환은 return by value
* @pre Iterator has been initialized.
* @post Current pointer is moved to next node.
* @return Return current data of the list.
*/
NodeType<T> GetCurrentNode();
/**
* @brief 현재 노드의 data의 주소값을 반환하는 함수
* @pre Iterator has been initialized.
* @post x
* @return Return current data's address
*/
T* GetCurrentPtr();
/**
* @brief 마지막 데이터의 포인터를 받는다.
* @pre Iterator has been initialized.
* @post x
* @return Return last data of the list.
*/
T Last();
/**
* @brief Curpointer의 이전 노드로 간다
* @pre Iterator has been initialized.
* @post 이전 노드로 포인터가 이동한다
* @return Return Prev data of the list.
*/
T Prev();
};
// 현재 원소가 null인지 검사
template <typename T>
bool DoublyIter<T>::NotNull() {
if (CurPointer == NULL) {
return false;
}
else return true;
}
// 다음 원소가 null인지 검사
template <typename T>
bool DoublyIter<T>::NextNotNull() {
if (CurPointer->next == NULL) {
return false;
}
else
return true;
}
template<typename T>
bool DoublyIter<T>::PrevNotNull()
{
if (CurPointer->Prev == NULL)
return false;
else
return true;
}
// 첫 번째 node
template <typename T>
T DoublyIter<T>::First() {
if (!m_List.IsEmpty()) {
CurPointer = m_List.m_pFirst;
return CurPointer->data;
}
}
// 다음 node로 이동 후 item을 return.
template <typename T>
T DoublyIter<T>::Next() {
T output = CurPointer->data;
if (NotNull()) {
CurPointer = CurPointer->next;
}
return output;
}
template<typename T>
T DoublyIter<T>::Last()
{
if (!m_List.IsEmpty()) {
CurPointer = m_List.m_pLast;
return CurPointer -> data;
}
}
template<typename T>
T DoublyIter<T>::Prev()
{
T output = CurPointer->data;
if (NotNull()) {
CurPointer = CurPointer->prev;
}
return output;
}
// 현재 node를 return
template <typename T>
NodeType<T> DoublyIter<T>::GetCurrentNode() {
if (CurPointer != NULL) {
return *CurPointer;
}
}
template<typename T>
T* DoublyIter<T>::GetCurrentPtr()
{
if (CurPointer != NULL)
{
return &(CurPointer->data);
}
}
#endif // !_DOUBLY_ITER_H
\ No newline at end of file
#pragma once
#ifndef _UN_SORTED_LINKED_LIST_H
#define _UN_SORTED_LINKED_LIST_H
#include"UnSortedLinkedList.h"
template<typename T>
class UnSortedLinkedList;
template<typename T>
struct NodeType2;
template<typename T>
class DoublyIter2 {
friend class UnSortedLinkedList<T>;
private:
const UnSortedLinkedList<T>& m_List;
NodeType2<T>* CurPointer;
public:
DoublyIter2(const UnSortedLinkedList<T>& list) : m_List(list), CurPointer(list.m_pList)
{}
/**
* @brief 현재 노드를 가리키는 포인터가 null인지 아닌지 판단하는 메서드.
* @pre Iterator has been initialized.
* @post None.
* @return nullptr true, otherwise false.
*/
bool NotNull();
/**
* @brief 현재 노드 포인터의 다음 노드가 null인지 아닌지 판단하는 메서드.
* @pre Iterator has been initialized.
* @post None.
* @return nullptr true, otherwise false.
*/
bool NextNotNull();
/**
* @brief 현재 노드 포인터의 이전 노드가 null인지 아닌지 판단하는 메서드.
* @pre Iterator has been initialized.
* @post None.
* @return nullptr true, otherwise false.
*/
bool PrevNotNull();
/**
* @brief Get first data of the list.
* @pre Iterator has been initialized.
* @post Current pointer is moved to the first node.
* @return Return first data of the list.
*/
T First();
/**
* @brief Get next data of the current pointer.
* @pre Iterator has been initialized.
* @post Current pointer is moved to the next node.
* @return Return next data of the list.
*/
T Next();
/**
* @brief Get current data of the list and go to the next node. 현재 노드. 객체반환은 return by value
* @pre Iterator has been initialized.
* @post Current pointer is moved to next node.
* @return Return current data of the list.
*/
NodeType2<T> GetCurrentNode();
/**
* @brief 현재 노드의 data의 주소값을 반환하는 함수
* @pre Iterator has been initialized.
* @post x
* @return Return current data's address
*/
T* GetCurrentPtr();
/**
* @brief 마지막 데이터의 포인터를 받는다.
* @pre Iterator has been initialized.
* @post x
* @return Return last data of the list.
*/
T Last();
/**
* @brief Curpointer의 이전 노드로 간다
* @pre Iterator has been initialized.
* @post 이전 노드로 포인터가 이동한다
* @return Return Prev data of the list.
*/
T Prev();
};
// 현재 원소가 null인지 검사
template <typename T>
bool DoublyIter2<T>::NotNull() {
if (CurPointer == NULL) {
return false;
}
else return true;
}
// 다음 원소가 null인지 검사
template <typename T>
bool DoublyIter2<T>::NextNotNull() {
if (CurPointer->next == NULL) {
return false;
}
else
return true;
}
template<typename T>
bool DoublyIter2<T>::PrevNotNull()
{
if (CurPointer->Prev == NULL)
return false;
else
return true;
}
// 첫 번째 node
template <typename T>
T DoublyIter2<T>::First() {
if (!m_List.IsEmpty()) {
CurPointer = m_List.m_pFirst;
return CurPointer->data;
}
}
// 다음 node로 이동 후 item을 return.
template <typename T>
T DoublyIter2<T>::Next() {
T output = CurPointer->data;
if (NotNull()) {
CurPointer = CurPointer->next;
}
return output;
}
template<typename T>
T DoublyIter2<T>::Last()
{
if (!m_List.IsEmpty()) {
CurPointer = m_List.m_pLast;
return CurPointer->data;
}
}
template<typename T>
T DoublyIter2<T>::Prev()
{
T output = CurPointer->data;
if (NotNull()) {
CurPointer = CurPointer->pre;
}
return output;
}
// 현재 node를 return
template <typename T>
NodeType2<T> DoublyIter2<T>::GetCurrentNode() {
if (CurPointer != NULL) {
return *CurPointer;
}
}
template<typename T>
T* DoublyIter2<T>::GetCurrentPtr()
{
if (CurPointer != NULL)
{
return &(CurPointer->data);
}
}
#endif // !_DOUBLY_ITER2_H
\ No newline at end of file
#pragma once
#include<iostream>
#include<string>
#include"SortedLinkedList.h"
#include"SimplifiedType.h"
using namespace std;
/**
* @brief 과제 1에서 이 클래스는 쓰이지 않는다.
*/
class GenreType //현재 이 장르타입은 쓰지 않는다.
{
public:
GenreType()
{
G_num = -1;
G_name = "";
} //기본 생성자
~GenreType()
{
} //기본 소멸자
/**
* @brief Get Genre
* @pre Genre is set.
* @post none.
* @return Genre;
*/
string GetGenre()
{
return G_name;
}
/**
* @brief Get song Number
* @pre song Name is set.
* @post none.
* @return song number
*/
int GetNum()
{
return G_num;
}
/**
* @brief set song number
* @pre x
* @post song number is set
* @param num song number
*/
void SetNum(int num)
{
G_num = num;
}
/**
* @brief set genre
* @pre x
* @post genre is set
* @param Genre Genre
*/
void SetGenre(string Genre)
{
G_name = Genre;
}
/**
* @brief 두 SimplifiedType의 Primary key가 같은지 비교함
* @pre 비교하고자 하는 SimplifiedType이 초기화 되어있어야함
* @post x
* @param data 비교하고자 하는 데이터
* @return 같을경우 true, 다를경우 false
*/
bool operator==(GenreType data)
{
if (this->GetNum() == data.GetNum())
return true;
else
return false;
}
/**
* @brief 두 SimplifiedType의 Primary key의 크기를 비교함
* @pre 비교하고자 하는 SimplifiedType이 초기화 되어있어야함
* @post x
* @param data 비교하고자 하는 데이터
* @return 좌변이 클경우 true 작을경우 false
*/
bool operator>(GenreType data)
{
if (this->GetNum() > data.GetNum())
return true;
else
return false;
}
/**
* @brief 두 SimplifiedType의 Primary key의 크기를 비교함
* @pre 비교하고자 하는 SimplifiedType이 초기화 되어있어야함
* @post x
* @param data 비교하고자 하는 데이터
* @return 우변이 클경우 true 작을경우 false
*/
bool operator<(GenreType data)
{
if (this->GetNum() < data.GetNum())
return true;
else
return false;
}
/**
* @brief GenreList안에 Simplified 타입을 넣는 함수
* @pre x
* @post 현재 GenreList에 Simplified 타입이 추가된다
* @param 추가하고자 하는 데이터
*/
void addListinGenre(SimplifiedType in)
{
G_List.Add(in);
}
/**
* @brief 현 GenreList안의 모든 데이터를 출력하는함수
* @pre GenreList안의 원소가 초기화 되어있어야함
* @post x
*/
void PrintAll()
{
}
private:
int G_num; //장르 넘버 = Primary Key
string G_name; //장르 명
SortedLinkedList<SimplifiedType> G_List; //각 장르별 장르리스트
};
\ No newline at end of file
#pragma once
#include"MusicType.h"
class ManageType {
private:
string Pkey;
int played;
int Index;
string name;
string artist;
public:
ManageType() {
Pkey = "";
played = 0;
Index = 0;
};
~ManageType() {};
void setPkey(string key)
{
Pkey = key;
}
void setIndex(int I)
{
Index = I;
}
void IncreasePlayed()
{
played++;
}
void setName(string N)
{
name = N;
}
void setArtist(string A)
{
artist = A;
}
string getArtist()
{
return artist;
}
string getPkey()
{
return Pkey;
}
int getPlayed()
{
return played;
}
int getIndex()
{
return Index;
}
string getName()
{
return name;
}
void PrintNameNArtist()
{
cout << "\t°î¸í : " << name << endl;
cout << "\t¾ÆƼ½ºÆ® : " << artist << endl << endl;
}
void PrintNameNIndex()
{
cout << "\t°î¸í : " << name << endl;
cout << "\tIndex : " << Index << endl << endl;
}
};
#include "MusicType.h"
// Ǻ
// Set student song Name from keyboard.
void MusicType::SetNameFromKB()
{
cout << "\tsong Name : ";
cin >> Name;
}
// Set Singer Name from keyboard.
void MusicType::SetSingerFromKB()
{
cout << "\tSinger : ";
cin >> Singer;
}
// Set Album Name from keyboard.
void MusicType::SetAlbumFromKB()
{
cout << "\tAlbum : ";
cin >> Album;
}
// Set Genre from keyboard
void MusicType::SetGenreFromKB()
{
cout << "\tGenre : ";
cin >> Genre;
}
// Set Lyrics from keyboard
void MusicType::SetLyricsFromKB()
{
cin.ignore();
cout << "\tLyrics : ";
getline(cin, Lyrics);
}
void MusicType::SetNumFromKB()
{
cout << "\tNumber : ";
cin >> Num;
}
// Set student record from keyboard.
void MusicType::SetInfoFromKB()
{
//SetNumFromKB();
SetNameFromKB();
SetSingerFromKB();
SetAlbumFromKB();
SetGenreFromKB();
SetLyricsFromKB();
SetPkey();
}
// Read a record from file.
int MusicType::ReadDataFromFile(ifstream& fin)
{
fin >> Name;
fin >> Singer;
fin >> Album;
fin >> Genre;
getline(fin, Lyrics);
return 1;
};
// Write a record into file.
int MusicType::WriteDataToFile(ofstream& fout)
{
fout << endl;
fout << Name << " ";
fout << Singer << " ";
fout << Album << " ";
fout << Lyrics << " ";
return 1;
}
\ No newline at end of file
#ifndef _MusicType_H
#define _MusicType_H
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
/**
* item information class.
*/
class MusicType
{
public:
/**
* default constructor.
*/
MusicType()
{
Num = -1;
Name = "";
Singer = "";
Album = "";
Genre = "";
Lyrics = "";
}
/**
* destructor.
*/
~MusicType() {}
/**
* @brief Get song Name
* @pre song Name is set.
* @post none.
* @return song Name;
*/
int GetNum()
{
return Num;
}
/**
* @brief Get song Name
* @pre song Name is set.
* @post none.
* @return song Name;
*/
string GetName()
{
return Name;
}
/**
* @brief Get Singer Name.
* @pre Singer Name is set.
* @post none.
* @return Singer Name.
*/
string GetSinger()
{
return Singer;
}
/**
* @brief Get Album Name
* @pre Album Name is set.
* @post none.
* @return Album Name.
*/
string GetAlbum()
{
return Album;
}
/**
* @brief Get Genre
* @pre Genre is set.
* @post none.
* @return Genre.
*/
string GetGenre()
{
return Genre;
}
/**
* @brief Get Lyrics
* @pre Lyrics is set.
* @post none.
* @return Lyrics.
*/
string GetLyrics()
{
return Lyrics;
}
/**
* @brief Get Pkey
* @pre Pkey is set.
* @post none.
* @return Pkey
*/
string GetPkey()
{
return Pkey;
}
/**
* @brief Set song Name
* @pre none.
* @post song Name is set.
* @param s_Name song Name
*/
void SetName(string s_Name)
{
Name = s_Name;
}
/**
* @brief Set song Name
* @pre none.
* @post song Name is set.
* @param s_Name song Name
*/
void SetNum(int s_Num)
{
Num = s_Num;
}
/**
* @brief Set Singer Name
* @pre none.
* @post Singer Name is set.
* @param s_Singer Singer Name.
*/
void SetSinger(string s_Singer)
{
Singer = s_Singer;
}
/**
* @brief Set Album Name
* @pre none.
* @post Album Name is set.
* @param s_Album Album Name.
*/
void SetAlbum(string s_Album)
{
Album = s_Album;
}
/**
* @brief Set Genre
* @pre none.
* @post Genre is set.
* @param s_Genre Genre.
*/
void SetGenre(string s_Genre)
{
Genre = s_Genre;
}
/**
* @brief Set Lyrics
* @pre none.
* @post Lyrics is set.
* @param s_Lyrics Lyrics
*/
void SetLyrics(string s_Lyrics)
{
Lyrics = s_Lyrics;
}
/**
* @brief Set Pkey
* @pre none.
* @post Pkey is set.
*/
void SetPkey()
{
Pkey = Name + Singer;
}
/**
* @brief Set song information
* @pre none.
* @post song information is set
* @param s_Name song Name
* @param s_Singer Singer Name
* @param s_Album Album Name.
* @param s_Genre Genre
* @param s_Lyrics Lyrics;
*/
void SetRecord(string s_Name, string s_Singer, string s_Album, string s_Genre, string s_Lyrics)
{
SetName(s_Name);
SetSinger(s_Singer);
SetAlbum(s_Album);
SetGenre(s_Genre);
SetLyrics(s_Lyrics);
SetPkey();
}
/**
* @brief Display song Name on screen.
* @pre song Name is set.
* @post song Name is on screen.
*/
void DisplayNumOnScreen()
{
cout << "\tSong Number(Track Number) : " << Num << endl;
};
/**
* @brief Display song Name on screen.
* @pre song Name is set.
* @post song Name is on screen.
*/
void DisplayNameOnScreen()
{
cout << "\tSong Name : " << Name << endl;
};
/**
* @brief Display Singer Name on screen.
* @pre Singer Name is set.
* @post Singer Name is on screen.
*/
void DisplaySingerOnScreen()
{
cout << "\tSinger : " << Singer << endl;
};
/**
* @brief Display Album Name on screen.
* @pre Album Name is set.
* @post Album Name is on screen.
*/
void DisplayAlbumOnScreen()
{
cout << "\tAlbum : " << Album << endl;
};
/**
* @brief Display Genre on screen.
* @pre Genre is set.
* @post Genre is on screen.
*/
void DisplayGenreOnScreen()
{
cout << "\tGenre : " << Genre << endl;
};
/**
* @brief Display Lyrics on screen.
* @pre Lyrics is set.
* @post Lyrics is on screen.
*/
void DisplayLyricsOnScreen()
{
cout << "\tLyrics : " << Lyrics << endl;
};
/**
* @brief Display an song information on screen.
* @pre song information is set.
* @post song information is on screen.
*/
void DisplayRecordOnScreen()
{
DisplayNumOnScreen();
DisplayNameOnScreen();
DisplaySingerOnScreen();
DisplayAlbumOnScreen();
DisplayGenreOnScreen();
DisplayLyricsOnScreen();
};
/**
* @brief Set song Number from keyboard.
* @pre none.
* @post song Number is set.
*/
void SetNumFromKB();
/**
* @brief Set song Name from keyboard.
* @pre none.
* @post song Name is set.
*/
void SetNameFromKB();
/**
* @brief Set Singer Name from keyboard.
* @pre none.
* @post Singer Name is set.
*/
void SetSingerFromKB();
/**
* @brief Set Album Name from keyboard.
* @pre none.
* @post Album Name is set.
*/
void SetAlbumFromKB();
/**
* @brief Set Genre from keyboard.
* @pre none.
* @post Genre is set.
*/
void SetGenreFromKB();
/**
* @brief Set Lyrics from keyboard.
* @pre none.
* @post Lyrics is set.
*/
void SetLyricsFromKB();
/**
* @brief Set song information from keyboard.
* @pre none.
* @post song information is set.
*/
void SetInfoFromKB();
/**
* @brief Read a record from file.
* @pre the target file is opened.
* @post student record is set.
* @param fin file descriptor.
* @return return 1 if this function works well, otherwise 0.
*/
int ReadDataFromFile(ifstream& fin);
/**
* @brief Write a record into file.
* @pre the target file is opened. And the list should be initialized.
* @post the target file is included the new student record.
* @param fout file descriptor.
* @return return 1 if this function works well, otherwise 0.
*/
int WriteDataToFile(ofstream& fout);
/**
* @brief 두 MusicType의 Primary key가 같은지 비교함
* @pre 비교하고자 하는 MusicType이 초기화 되어있어야함
* @post x
* @param data 비교하고자 하는 데이터
* @return 같을경우 true, 다를경우 false
*/
bool operator==(MusicType data)
{
if (this->GetPkey() == data.GetPkey())
return true;
else
return false;
}
/**
* @brief 두 MusicType의 Primary key의 크기를 비교함
* @pre 비교하고자 하는 MusicType이 초기화 되어있어야함
* @post x
* @param data 비교하고자 하는 데이터
* @return 좌변이 클경우 true 작을경우 false
*/
bool operator>(MusicType data)
{
return (this->GetPkey() > data.GetPkey());
}
/**
* @brief 두 MusicType의 Primary key의 크기를 비교함
* @pre 비교하고자 하는 MusicType이 초기화 되어있어야함
* @post x
* @param data 비교하고자 하는 데이터
* @return 우변이 클경우 true 작을경우 false
*/
bool operator<(MusicType data)
{
return (this->GetPkey() < data.GetPkey());
}
protected:
int Num; //곡의 인덱스
string Name; //곡명
string Singer; //가수
string Album; //앨범
string Genre; //장르
string Lyrics; //가사
string Pkey; //Primary Key
};
#endif // _MusicType_H
#include "PLType.h"
PLType::PLType(const PLType& data)
{
PlayList = data.PlayList;
PLname = data.PLname;
length = data.length;
}
void PLType::Printall()
{
DoublyIter2<ManageType*> Mgiter(PlayList);
while (Mgiter.NotNull())
{
cout << " : " << Mgiter.GetCurrentNode().data->getName() << endl;
cout << "Index : " << Mgiter.GetCurrentNode().data->getIndex() << endl;
Mgiter.Next();
}
}
\ No newline at end of file
#pragma once
#include"ManageType.h"
#include"UnSortedLinkedList.h"
class PLType {
private:
UnSortedLinkedList<ManageType*> PlayList;
string PLname;
int length;
public:
PLType() { length = 0; PLname = ""; }
~PLType() {}
PLType(const PLType& data);
void setPLname(string N)
{
PLname = N;
}
string getPLname()
{
return PLname;
}
void AddListinList(ManageType* data)
{
PlayList.Add(data);
length++;
}
void Printall();
};
#pragma once
#ifndef _DOUBLY_ITER_H
#define _DOUBLY_ITER_H
#include"DoublyIter.h"
template <typename T>
struct NodeType {
T data; //각 노드의 데이터
NodeType* next;// 노드의 다음을 가리킬 포인터
NodeType* pre;
};
template<typename T>
class DoublyIter;
/*
* @bried 이 클래스는 더블소티드링크드리스트
*/
template<typename T>
class SortedLinkedList
{
friend class DoublyIter<T>;
public:
/**
* default constructor.
*/
SortedLinkedList();
/**
* destructor.
*/
~SortedLinkedList();
/**
* @brief 깊은 복사를 위한 SortedLinkedList의 복사 연산자
* @pre anotherList가 초기화되어 있어야한다.
* @post anotherList와 같은 정보를 가진 리스트가 생성된다
* @param anotherList 복사하고자 하는 SortedLinkedList
*/
SortedLinkedList(const SortedLinkedList<T>& anotherList);
/**
* @brief 링크드 리스트의 모든 노드를 제거한다.
* @pre None.
* @post 리스트가 비워진다.
*/
void MakeEmpty();
/**
* @brief 리스트의 길이 = 원소의 개수 를 리턴함
* @pre x
* @post 리턴값이 리스트의 길이가 된다
* @return 리스트의 길이 = 원소의 개수
*/
int GetLength()
{
return m_nLength;
}
/**
* @brief 새로운 노드의 값을 비교하여 맞는 위치에 추가한다
* @pre List is not Full(메모리에 빈 공간이 있어야 한다)
* @post 리스트에 아이템이 추가된다.
* @return 추가되면 1 아니면 0
* @param 추가하고자 하는 데이터값
*/
int Add(T& data);
/**
* @brief 입력한 정보와 같은 정보를 가진 리스트의 원소를 리스트에서 삭제한다
* @pre 리스트가 비어있지 않아야한다.
* @post 리스트의 원소가 삭제되고 길이가 짧아진다.
* @return 삭제됬으면 1 아니면 0
* @param data 삭제하고자 하는 데이터값
*/
int Delete(T& data);
/**
* @brief 리스트내의 정보를 바꾼다
* @pre 리스트에 하나이상의 원소가 있어야한다.
* @post 리스트내의 원소의 정보가 바뀐다
* @return 작동했으면 1 아니면 0
*/
int Replace(T& data);
/**
* @brief 리스트에서 Primarykey를 기준으로 일치하는 원소를 받아온다
* @pre 리스트내의 정보가 초기화되있어야 한다
* @post 키와 맞는 정보가 있으면 그것을 받아온다..
* @return 찾아왔으면 1, 못찾았으면 0
*/
int Get(T& item);
/**
* @brief 리스트가 비어있는지를 확인한다.
* @pre x
* @post x
* @return 비었으면 1, 아니면 0
*/
bool IsEmpty()
{
if (m_nLength == 0)
return true;
else
return false;
}
/**
* @brief 복사 생성자를 이용한 대입 연산자
* @pre anotherList가 정의되어 있어야한다.
* @post 깊은 복사된 리스트가 대입된다.
* @return 복사된 리스트
*/
SortedLinkedList<T> operator=(const SortedLinkedList<T> &anotherList);
private:
NodeType<T> *m_pList;
NodeType<T> *m_pLast;
int m_nLength;
};
//함수 정의부
template<typename T>
SortedLinkedList<T>::SortedLinkedList()
{
m_nLength = 0;
m_pList = NULL;
}
template<typename T>
SortedLinkedList<T>::~SortedLinkedList()
{
MakeEmpty();//메모리누수를 막기위해 노드의 데이터를 모두 제거한다
}
template<typename T>
void SortedLinkedList<T>::MakeEmpty()
{
NodeType<T> *tempptr;
DoublyIter<T> iter(*this);
while (iter.NotNull())
{
tempptr = iter.CurPointer;
iter.Next();
delete tempptr;
} //리스트내의 모든 노드를 제거
m_pList = NULL;
m_pLast = NULL;
m_nLength = 0;
}
template<typename T>
int SortedLinkedList<T>::Add(T &data)
{
NodeType<T> *Node = new NodeType<T>;
NodeType<T> *Pre;
DoublyIter<T> iter(*this);
bool Found = false;
T dummy;
Node->data = data;
Node->next = NULL;
Node->pre = NULL;
if (IsEmpty()) //비어있을 경우
{
m_pList = Node;
m_pLast = m_pList;
m_nLength++; //성공적으로 추가했으므로 길이를 늘려준다
}
//list에 노드가 있을경우
else
{
while (1)
{
//Pre = m_pCurPointer; //이전 노드를 가리키는 포인터 갱신, 첫 시작은 m_pList로 리스트의 첫부분이다
if (iter.CurPointer->data == Node->data)
break; //같은 데이터가 있을경우 추가하지 않고 반복문을 탈출한다..
if (iter.CurPointer->data > Node->data) //Node의 데이터가 현재 포인터의 값보다 작아질때까지 node가 들어갈 위치를 뒤로 민다.
{
if (iter.CurPointer->pre == NULL) //리스트 맨 앞 장소에 넣어야 할때 첫번째 원소로 삽입한다
{
Node->next = iter.CurPointer;
iter.CurPointer->pre = Node;
m_pList = Node;
m_nLength++; //성공적으로 추가했으므로 break 하기전에 길이를 늘려준다
break;
}
Node->next = iter.CurPointer;
Node->pre = iter.CurPointer->pre;
iter.CurPointer->pre->next = Node;
iter.CurPointer->pre = Node;
m_nLength++; //성공적으로 추가했으므로 break 하기전 길이를 늘려준다.
break;
}
//Node 포인터가 마지막 노드를 가리키면 그 뒤에 Node를 삽입한다.
if (iter.CurPointer->next == NULL)
{
Node->pre = iter.CurPointer;
iter.CurPointer->next = Node;
m_pLast = Node;
m_nLength++;
break;
}
iter.Next();
}
}
return 1;
}
template<typename T>
int SortedLinkedList<T>::Delete(T& data)
{
bool MoreToSearch, found;
NodeType<T> *Pre = NULL;
DoublyIter<T> iter(*this);
found = false;
MoreToSearch = iter.NotNull();
while (MoreToSearch && !found)
{
if (data == iter.CurPointer->data) //현재 가리키는 원소가 패러미터로 넣은 값과 같은가?
{
found = true; //찾았으므로 found = true
if (Pre == NULL) //찾은 항목이 첫번째 원소일경우
{
NodeType<T>* temp = iter.CurPointer; //첫번째 원소의 다음원소를 저장할 임시 포인터선언
delete m_pList; //첫원소를 삭제한다.
temp->pre = NULL;
m_pList = temp; //찾은 항목이 첫 항목일경우 다음 원소를 첫번째 원소로 한다.
}
else
{
Pre->next = iter.CurPointer->next;
iter.CurPointer->next->pre = Pre;
delete iter.CurPointer;
}
}
else
{
Pre = iter.CurPointer;
iter.Next();
MoreToSearch = (iter.NotNull());
} //못 찾을경우 m_CurPointer은 다음 원소를 가리킨다. 단 Pre는 현재원소를 가리킨다.
}
if (found) //찾았을 경우
{
m_nLength--;
return 1;
}
else //못 찾으면
return 0;
}
template<typename T>
int SortedLinkedList<T>::Replace(T& data)
{
bool MoreToSearch, found;
NodeType<T> *location;
location = m_pList;
found = false;
MoreToSearch = (location != NULL);
while (MoreToSearch && !found) //리스트의 끝이 아니면서 아직 몾찾을경우 반복한다
{
if (data == location->data) //일치하는 경우를 찾으면
{
found = true;
location->data = data;
} //찾았으므로 found 는 true가되고 해당위치에 data값을 넣는다
else
{
location = location->next;
MoreToSearch = (location != NULL); //리스트의 끝이 아닐경우 계속찾는다.
} //찾지 못했을 때 다음 location으로 옮긴다.
}
if (found) //찾았을 경우
{
return 1;
}
else
return 0; //못 찾음
}
template<typename T>
int SortedLinkedList<T>::Get(T& data)
{
bool MoreToSearch, found;
NodeType<T>* location;
location = m_pList;
found = false;
MoreToSearch = (location != NULL);
while (MoreToSearch && !found)
{
if (data == location->data) //일치하는 항목을 찾으면
{
found = true;
data = location->data;
}
else
{
location = location->next; //못찾으면 다음위치로 민다
MoreToSearch = (location != NULL); //다음위치가 마지막이 아닐경우 계속 찾는다.
}
}
if (found) //찾았으면
return 1;
else //못 찾았으면
{
return 0;
}
}
template<typename T>
SortedLinkedList<T>::SortedLinkedList(const SortedLinkedList<T>& anotherList)
{
NodeType<T> *m_pCurPointer;
m_pList = NULL;
m_pCurPointer = NULL;
if (anotherList.m_pList == NULL)
return;
else {
this->m_nLength = anotherList.m_nLength;
NodeType<T> *Node1 = new NodeType<T>;
NodeType<T> *preNode;
NodeType<T> *Node2;
m_pList = Node1;
Node1->data = anotherList.m_pList->data;
Node1->pre = NULL;
Node2 = anotherList.m_pList->next;
while (Node2 != NULL)
{
Node1->next = new NodeType<T>;
preNode = Node1;
Node1 = Node1->next;
Node1->data = Node2->data;
Node1->pre = preNode;
Node2 = Node2->next;
}
Node1->next = NULL;
}
}
template<typename T>
SortedLinkedList<T> SortedLinkedList<T>::operator=(const SortedLinkedList<T> &anotherList)
{
MakeEmpty();
SortedLinkedList<T> temp(anotherList);
return temp;
}
#endif // !_SORTED_LINKED_LIST_H
\ No newline at end of file
#pragma once
#ifndef _DOUBLY_ITER2_H
#define _DOUBLY_ITER2_H
#include"DoublyIter2.h"
template <typename T>
struct NodeType2 {
T data; //각 노드의 데이터
NodeType2* next;// 노드의 다음을 가리킬 포인터
NodeType2* pre;
};
template<typename T>
class DoublyIter2;
/*
* @bried 이 클래스는 더블소티드링크드리스트
*/
template<typename T>
class UnSortedLinkedList
{
friend class DoublyIter2<T>;
public:
/**
* default constructor.
*/
UnSortedLinkedList();
/**
* destructor.
*/
~UnSortedLinkedList();
/**
* @brief 깊은 복사를 위한 UnSortedLinkedList의 복사 연산자
* @pre anotherList가 초기화되어 있어야한다.
* @post anotherList와 같은 정보를 가진 리스트가 생성된다
* @param anotherList 복사하고자 하는 UnSortedLinkedList
*/
UnSortedLinkedList(const UnSortedLinkedList<T>& anotherList);
/**
* @brief 링크드 리스트의 모든 노드를 제거한다.
* @pre None.
* @post 리스트가 비워진다.
*/
void MakeEmpty();
/**
* @brief 리스트의 길이 = 원소의 개수 를 리턴함
* @pre x
* @post 리턴값이 리스트의 길이가 된다
* @return 리스트의 길이 = 원소의 개수
*/
int GetLength()
{
return m_nLength;
}
/**
* @brief 새로운 노드의 값을 비교하여 맞는 위치에 추가한다
* @pre List is not Full(메모리에 빈 공간이 있어야 한다)
* @post 리스트에 아이템이 추가된다.
* @return 추가되면 1 아니면 0
* @param 추가하고자 하는 데이터값
*/
int Add(T& data);
/**
* @brief 입력한 정보와 같은 정보를 가진 리스트의 원소를 리스트에서 삭제한다
* @pre 리스트가 비어있지 않아야한다.
* @post 리스트의 원소가 삭제되고 길이가 짧아진다.
* @return 삭제瑛만 1 아니면 0
* @param data 삭제하고자 하는 데이터값
*/
int Delete(T& data);
/**
* @brief 리스트내의 정보를 바꾼다
* @pre 리스트에 하나이상의 원소가 있어야한다.
* @post 리스트내의 원소의 정보가 바뀐다
* @return 작동했으면 1 아니면 0
*/
int Replace(T& data);
/**
* @brief 리스트에서 Primarykey를 기준으로 일치하는 원소를 받아온다
* @pre 리스트내의 정보가 초기화되있어야 한다
* @post 키와 맞는 정보가 있으면 그것을 받아온다..
* @return 찾아왔으면 1, 못찾았으면 0
*/
int Get(T& item);
/**
* @brief 리스트가 비어있는지를 확인한다.
* @pre x
* @post x
* @return 비었으면 1, 아니면 0
*/
bool IsEmpty() const
{
if (m_nLength == 0)
return true;
else
return false;
}
/**
* @brief 복사 생성자를 이용한 대입 연산자
* @pre anotherList가 정의되어 있어야한다.
* @post 깊은 복사된 리스트가 대입된다.
* @return 복사된 리스트
*/
UnSortedLinkedList<T> operator=(const UnSortedLinkedList<T> &anotherList);
private:
NodeType2<T> *m_pList;
NodeType2<T> *m_pLast;
int m_nLength;
};
//함수 정의부
template<typename T>
UnSortedLinkedList<T>::UnSortedLinkedList()
{
m_nLength = 0;
m_pList = NULL;
}
template<typename T>
UnSortedLinkedList<T>::~UnSortedLinkedList()
{
MakeEmpty();//메모리누수를 막기위해 노드의 데이터를 모두 제거한다
}
template<typename T>
void UnSortedLinkedList<T>::MakeEmpty()
{
NodeType2<T> *tempptr;
DoublyIter2<T> iter(*this);
while (iter.NotNull())
{
tempptr = iter.CurPointer;
iter.Next();
delete tempptr;
} //리스트내의 모든 노드를 제거
m_pList = NULL;
m_pLast = NULL;
m_nLength = 0;
}
template<typename T>
int UnSortedLinkedList<T>::Add(T &data)
{
NodeType2<T> *Node = new NodeType2<T>;
NodeType2<T> *Pre;
DoublyIter2<T> iter(*this);
bool Found = false;
T dummy;
Node->data = data;
Node->next = NULL;
Node->pre = NULL;
if (IsEmpty()) //비어있을 경우
{
m_pList = Node;
m_pLast = m_pList;
m_nLength++; //성공적으로 추가했으므로 길이를 늘려준다
}
//list에 노드가 있을경우
else
{
while (1)
{
//Pre = m_pCurPointer; //이전 노드를 가리키는 포인터 갱신, 첫 시작은 m_pList로 리스트의 첫부분이다
Pre = iter.CurPointer;
//Node 포인터가 마지막 노드를 가리키면 그 뒤에 Node를 삽입한다.
if (iter.CurPointer->next == NULL)
{
iter.CurPointer->next = Node;
Node->pre = iter.CurPointer;
m_pLast = Node;
m_nLength++;
break;
}
iter.Next();
}
}
return 1;
}
template<typename T>
int UnSortedLinkedList<T>::Delete(T& data)
{
bool MoreToSearch, found;
NodeType2<T> *Pre = NULL;
DoublyIter2<T> iter(*this);
found = false;
MoreToSearch = iter.NotNull();
while (MoreToSearch && !found)
{
if (data == iter.CurPointer->data) //현재 가리키는 원소가 패러미터로 넣은 값과 같은가?
{
found = true; //찾았으므로 found = true
if (Pre == NULL) //찾은 항목이 첫번째 원소일경우
{
NodeType2<T>* temp = iter.CurPointer; //첫번째 원소의 다음원소를 저장할 임시 포인터선언
delete m_pList; //첫원소를 삭제한다.
temp->pre = NULL;
m_pList = temp; //찾은 항목이 첫 항목일경우 다음 원소를 첫번째 원소로 한다.
}
else
{
Pre->next = iter.CurPointer->next;
iter.CurPointer->next->pre = Pre;
delete iter.CurPointer;
}
}
else
{
Pre = iter.CurPointer;
iter.Next();
MoreToSearch = (iter.NotNull());
} //못 찾을경우 m_CurPointer은 다음 원소를 가리킨다. 단 Pre는 현재원소를 가리킨다.
}
if (found) //찾았을 경우
{
m_nLength--;
return 1;
}
else //못 찾으면
return 0;
}
template<typename T>
int UnSortedLinkedList<T>::Replace(T& data)
{
bool MoreToSearch, found;
NodeType2<T> *location;
location = m_pList;
found = false;
MoreToSearch = (location != NULL);
while (MoreToSearch && !found) //리스트의 끝이 아니면서 아직 ▣@뺐嚥 반복한다
{
if (data == location->data) //일치하는 경우를 찾으면
{
found = true;
location->data = data;
} //찾았으므로 found 는 true가되고 해당위치에 data값을 넣는다
else
{
location = location->next;
MoreToSearch = (location != NULL); //리스트의 끝이 아닐경우 계속찾는다.
} //찾지 못했을 때 다음 location으로 옮긴다.
}
if (found) //찾았을 경우
{
return 1;
}
else
return 0; //못 찾음
}
template<typename T>
int UnSortedLinkedList<T>::Get(T& data)
{
bool MoreToSearch, found;
NodeType2<T>* location;
location = m_pList;
found = false;
MoreToSearch = (location != NULL);
while (MoreToSearch && !found)
{
if (data == location->data) //일치하는 항목을 찾으면
{
found = true;
data = location->data;
}
else
{
location = location->next; //못찾으면 다음위치로 민다
MoreToSearch = (location != NULL); //다음위치가 마지막이 아닐경우 계속 찾는다.
}
}
if (found) //찾았으면
return 1;
else //못 찾았으면
{
return 0;
}
}
template<typename T>
UnSortedLinkedList<T>::UnSortedLinkedList(const UnSortedLinkedList<T>& anotherList)
{
NodeType2<T> *m_pCurPointer;
m_pList = NULL;
m_pCurPointer = NULL;
if (anotherList.m_pList == NULL)
return;
else {
this->m_nLength = anotherList.m_nLength;
NodeType2<T> *Node1 = new NodeType2<T>;
NodeType2<T> *preNode;
NodeType2<T> *Node2;
m_pList = Node1;
Node1->data = anotherList.m_pList->data;
Node1->pre = NULL;
Node2 = anotherList.m_pList->next;
while (Node2 != NULL)
{
Node1->next = new NodeType2<T>;
preNode = Node1;
Node1 = Node1->next;
Node1->data = Node2->data;
Node1->pre = preNode;
Node2 = Node2->next;
}
Node1->next = NULL;
}
}
template<typename T>
UnSortedLinkedList<T> UnSortedLinkedList<T>::operator=(const UnSortedLinkedList<T> &anotherList)
{
MakeEmpty();
UnSortedLinkedList<T> temp(anotherList);
return temp;
}
#endif // !_SORTED_LINKED_LIST_H
\ No newline at end of file
/**
* @mainpage Array list.
* This is a simple example of Lab01 on data structures course.<br>
*
* - Doxygen GUI 설정법<br>
* Step 1: Doxygen 으로 문서화 할 프로젝트 경로 삽입.<br>
* Step 2: Wizard 탭에서 Project Name 설정.<br>
* Step 3: Wizard 탭에서 Source code directory 에 문서화 할 소스 경로 지정 후 Scan recursively 를 체크.
* [Step 1] 의 경로와 같은 경로를 삽입해도 됨.<br>
* Step 4: Destination directory 에 문서화한 데이터가 저장될 경로 지정.<br>
* Step 5: Wizard 탭의 Output 에서 LaTeX 체크 해제.<br>
* Step 6: Run 탭의 Run doxygen 수행 후, "Doxygen has finished" 확인.<br>
*
* - 한글사용을 위해서는 Doxywizard에서 아래와 같이 설정할 것.<br>
* Expert 탭 -> Input (Topics 에서 선택) -> INPUT_ENCODING 을 "EUC-KR" 로 설정.
*
* @date 2018-10-11
* @author 2016104132 안형준
*/
#include "Application.h"
/**
* program main function for data structures course.
*/
int main()
{
Application app; // Program application
app.Run(); // run program
return 0;
}
\ No newline at end of file