#include<iostream>
#include<string>
using namespace std;
// 앨범 클래스를 만듭니다.
// 앨범 클래스를 만듭니다. 정렬하는 함수를 제외하고 모든 함수를 다 private 로 숨겨줍니다.
// 0. 제목과 작곡가가 써있는 문장에서 띄어쓰기가 중복되어 있으면 하나로 줄이고
// 0. 제목에 붙어있는 1. 과 같은 순서 번호는 제거 합니다.
// 0. (-) 대시 문자가 ( 제목 - 작곡가 ) 로 쓰이지 않고, 다른 곳에 있으면 공백으로 바꿉니다.
// 0. 또한 제목에 붙어있는 (-)대시 문자는 제목에 한번 띄어쓰기를 하고 (-)대시문자가 오도록 합니다
// 1. 작곡가의 두번째 이름에 맞춰서 작곡가의 이름을 재 배열 합니다. ( 작곡가의 성 뒤로 이름이 오도록 )
// 2. 하지만 작곡가의 이름이 없을 경우 (no author listed) 에는 작곡가의 이름이 재배열되지 않도록 합니다.
// 3. 작곡가의 이름에 맞춰 알파벳 순으로 배열을 정렬을 한 후, 음악 제목 또한 a, an, the
// 같은 관사를 제외한 앞글자에 맞춰서 알파벳 순으로 배열을 재 정렬합니다.
class Album {
public:
void sortFunc(const int& size, string returnArray[]);
// 음악을 정렬하는 함수 입니다.
// 파라미터로 음악의 갯수와, 정렬된 배열로 받아올 배열을 넣습니다.
private:
string strRemovedIndex(const string& songStr);
// 음악 제목에있는 인덱스번호를 지우는 함수입니다.
void findBlankAndTrim(string& songStr);
// 음악 제목에 있는 공백들을 하나로 줄이는 함수입니다.
void eraseDash(string& str);
// 제목과 작곡가 사이에 있는 대쉬를 제외한 대쉬를 공백으로 바꾸는 함수 입니다.
string authorNameChange(string str);
// 작곡가의 이름을 [성 이름] 순으로 바꾸는 함수 입니다.
void authorSorting(string str[], const int& size);
// 작곡가의 이름을 알파벳순으로 정렬하는 함수 입니다.
void titleSorting(string str[], const int& size);
// 제목의 이름을 알파벳 순으로 정렬하는 함수 입니다.
const string songArray[9] = { "1. Adagio \"MoonLight\" Sonata- Ludwig Van Beethoven",
"2. An Alexis- F.H.Hummel and J.N.Hummel",
"3. A La- Bien Aimee- Ben Schutt",
"4. At Sunset- E. MacDowell",
"5. Angelus- J.Massenet",
"6. Anitra\'s Dance- Edward Grieg",
"7. Erin is my Home- no author listed",
"8. Ase's- Death- Edward Grieg",
"9. The Brain Death - no author listed",
};
// 음악배열 입니다.
};
int main() {
Album songs;
// 메인 함수에서는, 앨범 클래스를 하나 만들고,
string sortedSongArray[9];
// 정렬된 배열을 받을 string 배열을 하나 선언 합니다.
songs.sortFunc(9, sortedSongArray);
// 앨범클래스 인스턴스를 정렬하여 sortedSongArray 에 넣어줍니다.
for(int i = 0; i < 9; i++)
cout << sortedSongArray[i] << "\n";
// 정렬된 배열을 출력하는 반복문 입니다.
return 0;
};
void Album::sortFunc(const int& size, string returnArray[]) {
// 음악앨범을 정렬하는 함수 입니다.
// 앞서 0 - 3으로 계획한것과 같은 것을 실행하는 함수 입니다.
for(int i = 0; i < size; i++) {
returnArray[i] = strRemovedIndex(songArray[i]);
// strRemovedIndex는, 인덱스번호를 지운 string을 반환 하는 함수 입니다.
// strRemovedIndex 함수 안에 중복되는 빈 공간을 하나로 줄이고
// 대쉬문자를 하나만 남기는 함수가 있습니다.
// 음악앨범의 길이만큼 반복문을 반복하며,
// 정렬된 배열을 넣어줄 배열의 요소에 하나씩 제목의 인덱스번호를 지워서 string을 넣어줍니다.
}
titleSorting(returnArray, size);
// 음악앨범에 있는 것들을 재 정렬 하는 함수 입니다.
// 여기서 작곡가의 이름을 재배열하고, 작곡가의 이름을 알파벳 순서에 맞춰서 재배열하고,
// 그 후 제목의 이름을 알파벳 순서에 맞춰서 재배열 하는 함수가 있습니다.
}
string Album::strRemovedIndex(const string& songStr) {
string newSongStr = songStr.substr(songStr.find('.') + 2);
// 인덱스번호를 없애고 반환하기 위한 string 값에 넣어줍니다.
findBlankAndTrim(newSongStr);
// 반환 하기 위한 string 값을 파라미터 값으로 받아서 중복된 공백을 줄여줍니다.
eraseDash(newSongStr);
// 반환 하기 위한 string 값을 파라미터 값으로 받아서 중복된 대쉬 문자를 줄여줍니다.
return newSongStr;
// 인덱스번호를 없애고 중복된 공백과 대쉬문자를 줄인 새로운 음악을 반환 합니다.
// 이는 정렬될 배열의 요소로 들어갑니다.
}
void Album::findBlankAndTrim(string& songStr) {
for(int i = 0; i < songStr.length(); i++) {
if(i + 1 < songStr.length()) {
while(songStr[i] == ' ' && songStr[i + 1] == ' ') {
string newSongStr = songStr.substr(0, i) + songStr.substr(i + 1);
songStr = newSongStr;
}
}
}
// 문장을 반복하며 빈 공간을 찾습니다.
// 빈공간 다음에 빈 공간이 또 있으면 그 만큼 하나를 줄여줍니다.
// 빈공간 다음에 빈 공간이 없을 때 까지 반복합니다. (한번 빈공간이 나오면 빈공간이 하나밖에 안나오도록)
}
void Album::eraseDash(string& str) {
int count = 0;
int index = -1;
int lastIndex;
string newStr = str;
for(int i = 0; i < str.length(); i++){
if(str[i] == '-') {
count++;
lastIndex = i;
}
};
// 제목과 작곡가 사이에 있는 - 는 항상 모든 - 문자 뒤에 있습니다
// 이를 통해서 맨마지막에 있는 - 의 index 번호를 lastIndex 로 받습니다.
for(int i = 0; i < str.length(); i++) {
if(str[i] == '-') {
index = i;
if(count > 1 && index != lastIndex) {
newStr = str.substr(0, i) + str.substr(i + 1, str.length());
}
// lastIndex 가 아닌 곳에 있는 - 를 지워줍니다.
}
}
for(int i = 0; i < newStr.length(); i++) {
if(newStr[i] == '-') {
index = i;
}
} // - 문자가 있는 곳의 위치를 받습니다. (find 함수를 사용해도 됨)
if(newStr.substr(index, 1) == "-") {
if(newStr[index - 1] == ' ') {
newStr = newStr.substr(0, index) + "-" + newStr.substr(index + 1, newStr.length());
} else {
newStr = newStr.substr(0, index) + " -" + newStr.substr(index + 1, newStr.length());
}
// 대쉬문자 뒤에 공백이 있으면 제목과 띄어주지 않고,
// 대쉬문자와 제목이 붙어 있으면 띄워 줍니다.
}
str = newStr;
// 대쉬문자를 줄이고 제목과 띄운 문자를 원래 문장에 대입 해줍니다.
}
void Album::titleSorting(string str[], const int& size) {
// 제목과 작곡가를 정렬하는 함수 입니다.
authorSorting(str, size);
// 작곡가의 이름을 재배열하고 알파벳순으로 재 정렬 하는 함수 입니다.
string aAnThe[6] = {"a ", "A ", "an ", "An ", "the ", "The "};
// 관사 문장이 들어 있는 배열 입니다.
const int anAnTheLength = 6;
// 관사 문장이 들어 있는 배열의 길이 입니다.
string titleArray[size];
// 관사 문장 다음에 들어 있는 제목 또는 제목의 첫 글자들의 배열입니다.
for(int i = 0; i < size; i++) {
for(int j = 0; j < anAnTheLength; j++) {
int index = str[i].find(aAnThe[j]);
if(index < str[i].length() && index == 0) {
switch (j) {
case 0:
case 1:
titleArray[i] = str[i].substr(index + 2, 1);
break;
// 관사가 A일때, 배열의 순서에 맞춰서 첫글자가 들어있을 배열에 넣어줍니다
case 2:
case 3:
titleArray[i] = str[i].substr(index + 3, 1);
break;
// 관사가 An 일때, 배열의 순서에 맞춰서 첫글자가 들어있을 배열에 넣어줍니다
case 4:
case 5:
titleArray[i] = str[i].substr(index + 4, 1);
break;
// 관사가 The 일때, 배열의 순서에 맞춰서 첫글자가 들어있을 배열에 넣어줍니다
default:
break;
}
}
}
if(titleArray[i].length() == 0) {
titleArray[i] = str[i].substr(0, 1);
}
// 만약 관사가 없으면, 제목의 맨 첫 글자를 첫 글자 배열에 넣어 줍니다.
}
for(int i = 0; i < size; i++) {
for(int j = i + 1; j < size; j++) {
if(titleArray[i].compare(titleArray[j]) > 0) {
string tempChar = titleArray[i];
titleArray[i] = titleArray[j];
titleArray[j] = tempChar;
string tempStr = str[i];
str[i] = str[j];
str[j] = tempStr;
}
}
}
// 정렬 알고리즘을 통해서 알파벳 순서로 정렬을 해줍니다.
}
void Album::authorSorting(string str[], const int& size) {
string newStr;
for(int i = 0; i < size; i++) {
int index = str[i].find('-');
newStr = str[i].substr(0, index + 1) + authorNameChange(str[i].substr(index + 1));
// 제목과 작곡가의 이름을 분리 시켜서 작곡가의 이름은 authorNameChange 를 통해서 순서를 바꾸고 그것 과
// 원 제목을 더해서 새로운 문장으로 넣어줍니다.
for(int j = 0; j < newStr.length(); j++) {
if(newStr[j] == '-' && newStr[j + 1] != ' ') {
newStr.replace(j + 1, newStr.length()," " + newStr.substr(j + 1));
// 대쉬문자 다음에 띄어져있지 않으면 공백을 넣어줍니다.
}
}
str[i] = newStr;
// 반복문으로 새로운 작곡가의 이름을 정렬될 배열의 요소 값으로 각각 넣어줍니다.
}
for(int i = 0; i < size; i++) {
for(int j = i + 1; j < size; j++) {
basic_string<char> iChar;
basic_string<char> jChar;
int iIndex = str[i].find('-');
int jIndex = str[j].find('-');
iChar = str[i].substr(iIndex + 2).substr(0,1);
jChar = str[j].substr(jIndex + 2).substr(0,1);
if(iChar > jChar) {
string temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
}
// 정렬 알고리즘을 통해, 알파벳 순서에 맞춰서 재 정렬을 해줍니다.
for(int i = 0 ; i < size; i++) {
int iIndex = str[i].find('-');
if (str[i].substr(iIndex + 2) == "no author listed") {
string temp = str[i];
str[i] = str[size - 1];
str[size - 1] = temp;
}
}
// 만약 작곡가의 이름이 no author listed 이면, 배열의 맨 뒤로 옮깁니다.
};
string Album::authorNameChange(const string str) {
// 작곡가의 이름을 [성 이름] 순으로 바꿔주는 함수 입니다.
int lastIndex;
string newStr;
if(str.find("and") < str.length()) {
return authorNameChange(str.substr(0, str.find(" and"))) + " and " + authorNameChange(str.substr(str.find("and") + 3));
}
// 만약에 이름에 and 가 들어 있으면 and 앞 뒤로 나눠서 성과 이름의 순서를 바꾸고 다시 합친 값을 반환 합니다.
// and 앞 각각은 재귀하여 순서를 바꿉니다. (and 가 들어 있지 않고, string 값으로 반환 하기 때문에 가능)
if(str.find('.') < str.length()) {
for(int i = 0; i < str.length(); i++) {
if(str[i] == '.') {
lastIndex = i;
}
}
return str.substr(lastIndex + 1) + str.substr(0, lastIndex + 1);
} else {
if(str != " no author listed") {
for(int i = 0; i < str.length(); i++) {
if (str[i] == ' ') {
lastIndex = i;
}
}
return str.substr(lastIndex, str.length()) + str.substr(0, lastIndex);
}
return str;
}
// . 으로 성과 이름을 구분 하거나, 공백으로 구분을 하는데 케이스를 .이 있을 때와 공백이 있을 때 로 나눕니다.
// 성과 이름을 바꾸고나서 그 문자열을 반환 합니다. 이는 정렬될 배열의 각각의 문장요소에 넣어집니다.
// 만약 작곡가의 이름이 no author listed 이면 그대로 반환 합니다.
}