C++ 스터디 #8: 문자열
시간 | 2021년 6월 29일 화요일 20:00 ~ 22:00 |
장소 | ZOOM |
참가자 | - |
출처: 천인국, “어서와 C++는 처음이지!”, INFINITY BOOKS
https://blockdmask.tistory.com/308 [개발자 지망생]
1. string 클래스
C++은 객체 지향 언어입니다. 이번 여름 방학부터 본격적으로 객체 지향 방법에 대해 배우게 될 것입니다.
문자열은 문자들의 나열입니다. C 언어에서는 문자열을 char형 배열로 나타내고 strcat()과 같은 어려운 함수 등을 사용해 문자열을 다룹니다. 하지만 C++ 언어에서는 string 클래스를 이용하여 문자열을 쉽게 저장하고 처리할 수 있습니다. string은 문자열을 나타내기 위하여 작성된 클래스입니다. string 클래스 안에는 문자열 저장 및 허리에 필요한 변수들과 함수들이 정의되어 있습니다.
2. 문자열 선언
2.1. 문자열 선언 예시
#include <iostream> #include <string> using namespace std; int main() { string s1 = "Hello"; string s2 = {"World!"}; string s3(3, 'a'); cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; return 0; }
3. 문자열의 결합(+ 연산자 이용)
string 클래스를 사용하면 문자열들을 '+' 연산자를 이용하여 간단하게 결합할 수 있습니다.
3.1 문자열의 결합 예시
#include <iostream> #include <string> using namespace std; int main() { string s1 = "Slow", s2 = "steady"; string s3 = "the race."; string s4; s4 = s1 + " and " + s2 + " wins " + s3; cout << s4 << endl; return 0; }
4. 문자열의 비교(비교 연산자 이용)
string 클래스를 사용하면 비교 연산자(==, >, <)들을 이용하여 문자열이 서로 같은지, 사전 순서로 어떤 문자가 앞에 오는지 알 수 있습니다.
4.1 문자열의 비교 예시
#include <iostream> #include <string> using namespace std; int main() { string s1 = "a", s2 = "b"; if (s1 == s2) cout << "동일한 문자열입니다." << endl; else cout << "동일한 문자열이 아닙니다." << endl; if (s1 > s2) cout << "s2이 앞에 있습니다." << endl; else if(s1 <s2) cout << "s1이 앞에 있습니다." << endl; return 0; }
5. getline 사용
cin을 사용해 string을 입력하면 공백 문자가 있으면 입력이 멈춥니다. 예를 들어 “고려대학교 기계공학부”를 입력하면 “고려대학교”만 입력되고 나머지 단어들은 입력을 대기하게 됩니다. 이때 getline() 함수를 사용하여 띄어쓰기가 포함된 한 줄을 전부 읽어줄 수 있습니다.
5.1. getline 사용 예시
#include <iostream> #include <string> using namespace std; int main() { /*string s1; cin >> s1; cout << s1 << endl;*/ string s2; getline(cin, s2); cout << s2 << endl; return 0; }
6. 문자열과 배열
문자열을 배열처럼 다룰 수 있습니다. 만약 s=“String”이란 문자열이 있다면 s[0]='S', s[5]='g' 이런식으로 표현할 수 있습니다.
6.1. 문자열과 배열 예시
#include <iostream> #include <string> using namespace std; int main() { string s = "apple"; for (int i = 0; i < 5; i++) cout << s[i] << endl; return 0; }
7. string 클래스 멤버 함수 호출
멤버 함수 | 설명 | ||
---|---|---|---|
s.insert(pos, s2) | s의 pos위치에 s2를 삽입 | ||
s.find(s2) | s에서 문자열 s2가 발견되는 첫번째 인덱스를 반환 | ||
s.at(pos) | s에서 pos 위치에 있는 문자를 반환 | ||
s.erase(pos, len) | s의 pos 위치부터 len만큼을 삭제 | ||
s.empty() | s가 비어있으면 true를 반환 |
7.1. insert, find
#include <iostream> #include <string> using namespace std; int main() { string s1 = "String", s2 = "Test"; string s3 = "t"; cout << s1.insert(2, s2) << endl; cout << s1 << endl; cout << s1.find(s3) << endl; return 0; }
7.2. at, erase, empty
#include <iostream> #include <string> using namespace std; int main() { string s1 = "String"; cout << s1.at(2) << endl; cout << s1.erase(2, 2) << endl; cout << s1 << endl; s1.clear(); cout << s1.empty() << endl; cout << s1 << endl; return 0; }
7.3. append
#include <iostream> #include <string> using namespace std; int main() { string str1("String"); cout << str1 << endl; str1.append(" Test"); cout << str1 << endl; str1.append(" Test Test", 3, 5); cout << str1 << endl; str1.append(" Test Test", 7); cout << str1 << endl; str1.append(3, 'T'); cout << str1 << endl; return 0; }
8. 번외-변수 생성
8.1. rand 사용
#include <iostream> #include <cstdlib> using namespace std; int main() { cout << rand() << endl; cout << rand() << endl; cout << rand() << endl; cout << rand() << endl; cout << rand() << endl; return 0; }
8.2. srand 사용
#include <iostream> #include <cstdlib> using namespace std; int main() { cout<<"1. rand()"<<endl; cout << rand() << endl; cout << rand() << endl; cout << "2. rand()와 동일한 시드의 srand()" << endl; srand(32323); cout << rand() << endl; srand(32323); cout << rand() << endl; srand(32323); cout << rand() << endl; cout << "3. rand()와 4개의 시드 srand()" << endl; for (int i = 0; i < 4; ++i) { srand(i); cout << rand() << endl; } return 0; }
8.3. time 사용
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { cout << time(NULL) << endl; srand((unsigned int)time(NULL)); cout << rand() % 10 << endl; return 0; }
9. 예제
9.1. 예제(1): 행맨 게임 만들기
행맨 게임은 빈칸으로 구성된 문자열이 주어지고 사용자는 문자열에 들어갈 글자들을 하나씩 추축해서 맞추는 게임이다.
Tip. 다음은 빈칸으로 주어질 단어 예시이다. 난수를 사용해 실행할 때마다 다른 문제가 출제되게 만든다. 2.1에서 소개한 방법을 이용해 빈칸으로 구성된 문자열을 만든다.
string solution; string list[] = { "the", "c++", "programming", "language", }; srand((unsigned int)time(NULL)); int n = rand() % 4; solution = list[n]; string guess(solution.length(), '_');
[정답 예시]
#include <iostream> #include <string> #include <cstdlib> #include <ctime> using namespace std; int main() { char ch; string solution; string list[] = { "the", "c++", "programming", "language", }; srand((unsigned int)time(NULL)); int n = rand() % 4; solution = list[n]; string guess(solution.length(), '_'); while (true) { cout << guess << endl; cout << "글자를 입력하시오: "; cin >> ch; for (int i=0;i< solution.length();i++) { if (ch == solution[i]) { guess[i] = ch; } } if (solution == guess) { cout << solution << endl; cout << "성공하였습니다.!"; break; } } return 0; }
9.2. 예제(2): 가장 긴 문자열 출력
사용자로부터 문자열 5개를 읽어서 가장 긴 문자열을 화면에 출력한다.
Tip. string의 배열을 만들어서 사용자의 입력을 저장하고 string 클래스의 멤버 함수인 size()를 사용한다.
[정답 예시]
#include <iostream> #include <string> using namespace std; int main() { string s1[5]; string max = s1[0]; for (int i = 0; i < sizeof(s1) / sizeof(string); i++) { cout << "문자열을 입력하시오: "; cin >> s1[i]; if (s1[i].size() > max.size()) max = s1[i]; } cout << "제일 긴 문자열: " << max << endl; return 0; }
9.3. 예제(3): 난수 생성
0부터 9까지의 난수를 100번 생성하여 가장 많이 생성된 수를 출력하는 프로그램을 작성하시오.
[정답 예시]
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { int list[10] = {}; int max = 0; srand((unsigned int)time(NULL)); for (int i = 0; i < 100; i++) { int num = rand() % 10; list[num]++; if (list[num] >= list[max]) max = num; } cout << "가장 많이 생성된 수: " << max; return 0; }
9.4. 예제(4): 철자 교정 프로그램
간단한 철자 교정 프로그램을 작성하여 보자. 문자열을 입력으로 받아서 문자열 안에 마침표가 있으면 문자열의 첫 번째 문자가 대문자인지를 건사한다. 만약 대문자가 아니면 대문자로 변환한다. 또한 문장의 끝에 마침표가 존재하는지를 검사한다. 역시 마침표가 없으면 넣어준다. 즉 입력된 문자열이 “c++ is easy”라면 “C++ is easy.”로 변환하여 화면에 출력한다.
[정답 예시]
#include <iostream> #include <string> using namespace std; int main() { string s; cout << "문자열을 입력하시오: "; getline(cin, s); s[0] = toupper(s[0]); if (s[s.length() - 1] != '.') s += "."; cout << "결과 문자열: " << s << endl; return 0; }
9.5. 예제(5): 문자가 나타나는 빈도 출력
사용자로부터 받은 문자열에서 각각의 문자가 나타나는 빈도를 계산하여 출력하는 프로그램을 작성하시오.(단, 영어 소문자만 입력된다.)
Tip. 문자는 아스키코드로 표현되고 0에서 255까지의 값을 가진다. 따라서 크기가 256인 정수 배열을 선언하고 다음과 같이 반복 루프를 통하여 빈도를 구한다.
int counter[256] = { 0 }; string s; cout << "문자열을 입력하시오: "; getline(cin, s); for (int i = 0; i < s.size(); i++) { counter[s[i]]++; }
[정답 예시]
#include <iostream> #include <string> using namespace std; int main() { int counter[256] = { 0 }; string s; cout << "문자열을 입력하시오: "; getline(cin, s); for (int i = 0; i < s.size(); i++) { counter[s[i]]++; } for (int i = 'a'; i <= 'z'; i++) { cout << (char)i << ": " << counter[i] << endl; } return 0; }
9.6. 예제(6): 암호의 안전 여부 판단
사용자로부터 암호를 입력받는다. 사용자의 암호가 해킹에 대하여 안전한지의 여부를 검사한다. 만약 암호 안에 대문자, 소문자, 숫자가 모두 들어있으면 안전한 암호로 간주한다. 만약 사용자의 암호가 3가지 종류의 문자를 다 가지고 있지 않으면 프로그램은 보안을 위하여 더 강한 암호를 고려하라고 제안한다.
Tip. bool 자료형을 이용해 해결하는 방법도 있다.
[정답 예시]
#include <iostream> #include <string> using namespace std; int main() { string pw; int low = 0, up = 0, num = 0; cout << "암호를 입력하세요: "; getline(cin, pw); bool is_lower = false, is_upper = false, is_numeric = false; for (int i = 0; i < pw.length(); i++) { if (pw[i] >= 'a' && pw[i] <= 'z') is_lower = true; else if (pw[i] >= 'A' && pw[i] <= 'Z') is_upper = true; else if (pw[i] >= '0' && pw[i] <= '9') is_numeric = true; } if ((is_lower && is_upper && is_numeric) == true) { cout << "안전합니다." << endl; } else cout << "안전하지 않습니다." << endl; return 0; }
9.7. 예제(7): 애나그램(anagram) 게임
단어 애나그램(anagram) 게임을 작성해보자. 영어 단어를 이루는 글자들이 뒤죽박죽 섞인 것을 받아서 순서대로 재배치하는 게임을 애나그램 게임이라 한다.
Tip. 문자열 안의 글자들을 섞으려면 난수가 필요하다. 2개의 난수를 발생시켜서 그 위치의 글자들을 서로 바꾸면 된다. 이것을 문자열의 길이만큼 반복한다. 물론 난수의 범위는 문자열의 안이어야 한다.
[정답 예시]
#include <iostream> #include <string> #include <cstdlib> #include <ctime> using namespace std; int main() { string s1 = "apple"; string s2 = s1; string answer; char temp; srand((unsigned int)time(NULL)); for (int i = 0; i < 5; i++) { int n1 = rand() % 5; int n2 = rand() % 5; temp = s1[n1]; s1[n1] = s1[n2]; s1[n2] = temp; } while (1) { cout << s1 << "은 어떤 단어가 스크램블된 것일까요?"; cin >> answer; if (s2 == answer) { cout << "축하합니다." << endl; break; } } return 0; }