코테/항해99

[99클럽 코테 스터디 1일차 TIL] # 문자열

쪼성윤 2024. 10. 28. 14:51

드디어 기다리던 99 클럽 코테 스터디가 시작되었다. 설레는 마음으로 첫 문제를 풀어보도록 하자!

 

문제 설명


대소문자가 구별없는 문자열을 받아, 'p'와 'y'의 개수를 비교분석해 출력하는 문제이다.

https://school.programmers.co.kr/learn/courses/30/lessons/12916

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

 

 

생각 흐름


우선 먼저 보자마자, C++ 언어 특성상 활용할 수 있는 문자열 클래스인 string 클래스를 생각해 보았다.

 

문자열 내에서 문자를 찾아주는 find() 함수,  s.length()대로 반복해서 일일이 찾아내는 for문,  개수를 저장할 변수 선언 등을 떠올렸던 것 같다.

 

먼저 find() 함수를 써보기로 하였다. 함수 이름이 직관적이어서 멋있다고 해야 하나..

하지만 find() 함수에 대소문자 총 4개의 문자를 넣어 유무를 판별하는 것이 쉽지 않다는 것을 알게 되었다.

 

단순하게 하나씩 끊어 문자로 보고 일일이 비교해 보는 반복문을 작성해 보기로 하였다. 

string 클래스를 사용하기 위해 헤더파일 <string> 클래스를 추가해 주고 string s;라는 변수를 선언해 주어 받아오며

이를 문자열의 크기로 반복문을 돌려 일일이 비교하는 작업을 거쳤다.

 

#include <string>
#include <iostream>
using namespace std;

int cp, cy; // p, y의 개수

bool solution(string s)
{
    bool answer = true;
    
    for (int i = 0; i < s.length(); i++)  {
        if (s[i] == 'p' || s[i] == 'P') {
            cp++;
        }
        if (s[i] == 'y' || s[i] == 'Y') {
            cy++;
        }
    }
    
    if (cp == cy) {
        return answer;
    }
    else return false;
}

int main () {
    string s;
    getline (cin, s);
    
    if (solution(s) == true) return true;
    else return false;
    
}

 

공부한 내용 정리

 

string 클래스?


  1. C++ STL에서 제공하는 클래스로, 말 그대로 string(문자열)을 다루는 클래스입니다.
  2. C에서는 char* 또는 char []의 형태로 문자열을 다뤘다면, C++에서는 문자열을 하나의 변수 type처럼 사용하며, 문자열을 훨씬 다양하고 쉽게 다룰 수 있게 해 줍니다.
  3. char*, char []과 다르게 문자열 끝에 '\0' 문자가 들어가지 않으며, 문자열의 길이들 동적으로 변경 가능합니다.

 

string 클래스의 특징


  • 특징 1 : 문자의 끝에 null문자(‘\0’) 등이 포함되지 않는다.
  • 특징 2 : 마치 배열처럼 한 문자씩 다룰 수 있다.
  • 특징 3 : string 클래스끼리는 문자열을 합치는 것이 + 연산자 하나만으로 가능하다.
  • 특징 4 : 문자열을 사전순으로 정렬할 때도 string 변수를 사용하면 편리하다.
  • 이 외에 다양하게 쓸 수 있는 멤버함수들이 존재합니다.

 

string의 인덱스 접근


  • 배열처럼 접근하기
    • string str = “TEST”; 일 때, str [0] 은 ‘T’를 반환. 이때 반환되는 문자는 char 형임에 주의!
  • . at(index)로 접근하기
    • string str = “TEST”; 일 때, str.at(1) 은 ‘E’를 반환. 이때 반환되는 문자는 char 형임에 주의!

 

string 클래스의 멤버 함수

 

 

이번 문제를 풀면서 사용하려 했던 함수인데 자세히 모르는 것 같아서 공부해 보았습니다.

1. find() 함수

find 함수는 <string> 헤더파일, <algorithm> 헤더파일에서 제공하는 두 가지 함수가 있다.

 

<string>의 find 함수

사용 : 내 문자열. find (찾을 문자열, 시작 위치);
원형 : size_t find (const char * arr, size_t index = 0) const;

 

string s = "Hello My Name is metoday.";

int non;
non = s.find("h"); //non == npos

cout << s.find("e"); // 출력 : 1
cout << s.find("e" , 2); // 출력 : 12
cout << s.find("Myapple" , 5 , 2) // 출력 : 6 (Myapple에서 2번째 문자까지 찾기)

 

  • 대소문자 구별을 하기 때문에 h를 찾지 못했다. 찾지 못하면 npos를 반환한다.
  • 찾고자 하는 문자가 여러 개 있을 때 시작 위치를 잘 설정하면 원하는 문자의 위치를 얻을 수 있다.
  • 찾을 문자열의 길이가 2로 입력되었기 때문에 "Myapple"에서 "My"를 찾게 설정되어서 6이 출력된 것이다.

npos 활용법

string s = "Hello World";

int index = s.find('a');

if (index == string::npos) {
	cout << "Not Found.";
}
else {
	cout << index;
}

// 출력 : Not Found.

 

 

<algorithm>의 find 함수

 

vector에서의 사용

find (v.begin(), v.end(), 찾을 값)
vector <int> v = {2, 1, 4, 5, 3};
vector <int> :: iterator it;

it = find(v.begin(), v.end(), 3);

cout << *it << "\n"; // 출력 : 3;
cout << it - v.begin() << "\n"; // 출력 : 4

 

  • find는 찾는 값을 가리키고 있는 iterator를 반환한다.
  • 그래서 *를 붙이면 if가 가리키는 값을 반환하고,
  • it - v.begin()을 해주면 가리키는 값의 index를 반환한다.
  • 찾는 값이 없는 경우 it은 v.end()를 가리킨다.
vector<int> v = {1, 2, 3, 4, 5};
vector<int>::iterator it;

it = find(v.begin() , v.end() , 6);
if(it == v.end()){
	cout << "Not Found.";
}
else{
	cout << "index : " << it - v.begin() ;
}

//출력 : Not Found.

 

 

arr (배열)에서도 사용방법은 같다.

 

돌아보기


문제를 풀고 다른 사람들의 풀이를 찾아보는 과정에서 

C++ 에는 대문자를 소문자로, 소문자를 대문자로 바꿔주는 함수로 풀면 더 간결하게 작성할 수 있다는 것을 알게 되었다.

 

한쪽으로 바꿔주어 훨씬 문제를 해결하는 것에 있어 시간을 단축시킬 수 있다는 점에서 흥미로웠던 것 같다.

 

 

toupper(), tolower() 함수

 

1) 헤더파일: <cctype>

 

2) tolower 함수 원형 및 설명

int tolower (int c);

매개변수: 문자를 인자로 받습니다. 문자를 넣게 되면 아스키코드표에 기반한 10진수로 변환되어 들어가며, 숫자가 들어가게 되어도 아스키 코드 표에 기반한 숫자로 인식합니다.
즉 int 타입인 65번이 들어오면 내부적으로는 'A'로 인식합니다.
문자 'A'가 들어오면 아스키 코드표에 기반하여 65번으로 받게 됩니다.

반환형: 매개변수로 들어온 인자가 대문자인 경우 소문자로 반환해 줍니다.
인자로 소문자가 들어올 경우 소문자를 반환해 줍니다.
인자로 대소문자가 아닌 다른 문자가 들어온 경우 해당 문자 그대로 반환합니다.
결론적으로 대문자만 소문자로 변경하고 다른 모든 문자는 그대로 반환하는 함수입니다.

 

3) toupper 함수 원형 및 설명

int toupper(int c);

매개변수 : 문자를 인자로 받습니다. 문자를 넣게 되면 아스키코드표에 기반한 10진 수로 변환되어 들어가며,
숫자가 들어가게 되어도 아스키 코드 표에 기반한 숫자로 인식합니다.

반환형 : 소문자만 대문자로 변경해서 반환해 주고 다른 모든 문자는 그대로 반환하는 함수입니다.

 

** tolower, toupper 함수의 원리는 아스키코드표를 보면 쉽게 알 수 있습니다.'a'는 97번이고, 'A'는 65번입니다. toupper라면 'a'인 97번이 들어오면 -32를 하여 65번에 해당하는 'A'를 반환하는 것입니다.
반대로 tolower 함수에 'A'인 65번이 들어오면 +32를 하여 97번에 해당하는 소문자 'a'를 반환하는 것입니다.'A', 'a'를 한번 보면 이렇습니다.

 

 

#include <bits/stdc++.h>
using namespace std;

int cp, cy; // p, y의 개수

bool solution(string s) {
    bool answer = true;

    for (int i = 0; i < s.length(); i++) {
        s[i] = tolower(s[i]);

        if (s[i] == 'p') {
            cp++;
        }
        if (s[i] == 'y') {
            cy++;
        }
    }

    if (cp != cy) {
        answer = false;
    }
    
    return answer;
}


int main() {
    string s;
    cin >> s;

    bool check = solution(s);

    if (check == true) cout << boolalpha << true;
    else cout << boolalpha << false;

    return 0;
}