자료구조와 알고리즘/문제풀이

[Baekjoon] 단계별로 풀어보기 : 문자열

순정법사 2023.08.17

 

이번 알고리즘 문제 풀이는 C로 진행했습니다 

코드에 오탈자나 문제가 있으면 언제든지 댓글로 알려주세요!

 

 

 


 

 

 

A. 문자열

 

문자열 단계

정수를 문자열로 입력받는 문제. Python처럼 정수 크기에 제한이 없다면 상관 없으나, 예제 3은 일반적인 정수 자료형에 담기에 너무 크다는 점에 주목합시다.

www.acmicpc.net

 

1. 문자와 문자열

a. 문제지  : 27866

 

b. 정답

📚 풀이

#include <stdio.h>
#include <string.h>

int main() {
    char S[1001];  // 단어를 저장할 배열, 최대 길이보다 큰 크기로 지정
    int i;  // 정수 i를 저장할 변수

    // 단어 입력 받기
    scanf("%s", S);

    // 정수 i 입력 받기
    scanf("%d", &i);

    // 인덱스가 올바른 범위 내에 있는지 확인
    if (i >= 1 && i <= strlen(S)) {
        // i번째 글자 출력 (인덱스는 0부터 시작하지만 문제에서는 1부터 시작하므로 i - 1 사용)
        printf("%c\n", S[i - 1]);
    } else {
        // 올바르지 않은 인덱스일 경우 메시지 출력
        printf("Invalid index\n");
    }

    return 0;
}

 

 

2. 단어 길이 재기

a. 문제지  : 2743

 

b. 정답

📚 풀이

#include <stdio.h>
#include <string.h>

int main() {
    char word[100];

    // 단어 입력 받기
    scanf("%s", word);
        
    // 단어의 길이 구하기
    int length = strlen(word);
    
    // 단어의 길이가 100 이하일 경우에만 출력
    if (length <= 100) {
        printf("%d\n", length);
    } else {
        printf("단어 길이가 100을 초과했습니다.\n");
    }

    return 0;
}

 

 

3. 문자열

a. 문제지  : 9086

 

b. 정답

📚 풀이

#include <stdio.h>
#include <string.h>

int main() {
    int count; // 테스트 케이스의 개수를 저장할 변수

    // 반복 횟수 입력 받기
    scanf("%d", &count);

    // 테스트 케이스 수 만큼 반복
    for (int i = 0; i < count; i++) {
        char word[1001]; // 입력받을 문자열을 저장할 배열
        scanf("%s", word); // 문자열 입력 받기

        int word_length = strlen(word); // 문자열의 길이 계산

        // 단어의 길이가 0보다 큰 경우에만 첫 글자와 마지막 글자 출력
        if (word_length > 0) {
            printf("%c%c\n", word[0], word[word_length - 1]);
        }
    }
       
    return 0;
}

 

 

4. 아스키 코드

a. 문제지  : 11654

 

b. 알고리즘 / 설명

입력된 글자는 %c 형식 지정자를 사용하여 입력 받아 아스키 코드 값을 출력하기 위해 %d 형식 지정자를 사용

 

c. 정답

📚 풀이

#include <stdio.h>

int main() {
    char ch; // 알파벳 소문자, 대문자, 숫자 중 하나를 저장할 변수

    // 글자 입력 받기
    scanf("%c", &ch); // 사용자로부터 글자를 입력받아 ch 변수에 저장

    // 아스키 코드 값 출력
    printf("%d\n", ch); // 변수 ch에 저장된 글자의 아스키 코드 값을 출력

    return 0;
}

 

 

5. 숫자의 합

a. 문제지  : 11720

 

b. 풀이

C 언어에서 문자들은 내부적으로 아스키(ASCII) 코드 값을 가지고 숫자들은 연속적인 아스키 코드 값을 가짐

ex) 문자 '0' 값은 48, '1'은 49, '2'는 50, ..., '9'는 57

따라서 숫자 문자를 정수로 변환하려면 해당 문자의 아스키 코드 값에서 '0' 문자의 아스키 코드 값을 뺀 값을 사용하면 됨

ex) 문자 '0'의 아스키 코드 값인 48('0')을 빼주면 숫자 0, '1'의 아스키 코드 값인 49를 빼주면 숫자 1 ... 

따라서 아래 풀이에서 주어진 문자열에서 숫자 문자들을 숫자로 변환하기 위해 numStr[i] - '0' 연산 수행

 

c. 정답

📚 풀이

#include <stdio.h>

int main() {
    int N; // 숫자의 개수
    scanf("%d", &N); // 숫자의 개수 입력 받기

    char numStr[101]; // 숫자들을 문자열로 입력 받을 배열
    scanf("%s", numStr); // 숫자들 입력 받기

    int sum = 0; // 숫자들의 합을 저장할 변수

    // 입력받은 문자열의 각 자릿수를 숫자로 변환하여 합에 더하기
    for (int i = 0; i < N; i++) {
        int digit = numStr[i] - '0'; // 문자를 숫자로 변환
        sum += digit; // 합에 더하기
    }

    printf("%d\n", sum); // 합 출력

    return 0;
}

 

 

6. 알파벳 찾기

a. 문제지  : 10809

 

b. 알고리즘 / 풀이

  1. 문자열 S 입력을 받음
  2. 알파벳 등장 위치 저장 배열 alp을 생성하고, 각 요소를 -1로 초기화 (알파벳 수: 26)
  3. 문자열 S 길이 계산하여 len에 저장
  4. 문자열 S 순회하며 다음 수행
    a) 현재 문자가 알파벳 소문자인 경우, 해당 알파벳 인덱스 계산 ('a'는 0, 'b'는 1, ... 'z'는 25)
    b) alp 배열에서 해당 알파벳 인덱스 값이 -1인 경우, 즉 처음 등장 시 현재 위치 저장
  5. alp 배열 순회하며 각 알파벳 처음 등장 위치 출력

 

c. 정답

📚 풀이

#include <stdio.h>
#include <string.h>

int main(){
    char S[100];
    scanf("%s", S);  // 문자열 입력 받음
    
    int alp[26];
    for(int i=0; i<26; i++){
        alp[i] = -1;  // 배열을 -1로 초기화 (각 알파벳의 인덱스를 저장할 배열)
    }
    
    int len = strlen(S);  // 입력된 문자열의 길이
    for(int i=0; i<len; i++){
        int index  = S[i] - 'a';  // 해당 알파벳의 인덱스 계산 ('a'는 0, 'b'는 1, ... 'z'는 25)
        if(alp[index] == -1){  // 해당 알파벳의 인덱스가 아직 설정되지 않았다면
            alp[index] = i;  // 현재 인덱스를 저장
        }
    }
    
    for(int i=0; i<26; i++){
        printf("%d ", alp[i]);  // 각 알파벳의 인덱스 출력
    }
    
    return 0;
}

 

 

7. 문자열 반복

a. 문제지  : 2675

 

b. 알고리즘 / 풀이

  1. 테스트 케이스 T 입력
  2. 각 테스트 케이스마다 반복
    a) 반복 횟수 R과 문자열 S 입력
    b) 문자열 S 길이 계산
    c) 문자열의 각 문자에 대해 현재 문자를 R번 반복하여 출력
    d) 줄바꿈 출력

 

c. 정답

📚 풀이

#include <stdio.h>
#include <string.h>

int main(){
    int T; // 테스트 케이스의 개수
    scanf("%d", &T); // 테스트 케이스 개수 입력 받음
    
    for(int i=0; i<T; i++){ // 테스트 케이스 개수만큼 반복
        int R; // 반복 횟수
        char S[21]; // 문자열 (길이가 최대 20)
        scanf("%d %s", &R, S); // 반복 횟수와 문자열 입력 받음
        
        int len = strlen(S); // 문자열의 길이 계산
        for(int j=0; j<len; j++){ // 문자열의 각 문자에 대해 반복
            for(int k=0; k<R; k++){ // R번 반복하여 출력
                printf("%c", S[j]); // 문자 출력
            }
        }
        printf("\n"); // 테스트 케이스마다 줄바꿈
    }
    
    return 0;
}

 

 

8. 단어의 개수

a. 문제지  : 1152

 

b. 알고리즘 / 풀이

  1. 문자열을 저장할 배열 word를 선언하고, 단어의 개수를 저장할 변수 count와 문자열의 길이를 저장할 변수 len을 초기화
  2. scanf 함수를 사용하여 공백을 포함한 한 줄 입력
  3. 입력된 문자열의 길이를 strlen 함수를 사용하여 계산
  4. 만약 입력 문자열이 한 글자이고 그 글자가 공백인 경우, count를 출력하고 프로그램을 종료
  5. 입력 문자열을 순회하면서 공백 문자를 찾아 단어의 개수인 count를 증가
  6. 마지막에 count + 1을 출력하여 마지막 단어의 개수도 더해진 값을 출력

 

c. 정답

📚 풀이

#include <stdio.h>
#include <string.h>

int main() {
    char word[1000000];  // 입력 문자열을 저장할 배열
    int count = 0, len;  // 단어의 개수와 문자열의 길이를 저장하는 변수
    
    scanf("%[^\n]s", word);  // 공백을 포함한 한 줄을 입력 받음
    len = strlen(word);  // 입력된 문자열의 길이 계산
    
    // 입력 문자열이 한 글자이고, 그 글자가 공백인 경우
    if (len == 1 && word[0] == ' ') {
        printf("%d", count);  // 단어 개수 출력
        return 0;  // 프로그램 종료
    }
    
    // 입력 문자열을 순회하면서 단어의 개수를 세는 반복문
    for (int i = 1; i < len - 1; i++) {
        if (word[i] == ' ') {  // 공백 문자를 만나면
            count++;  // 단어 개수 증가
        }
    }
    
    printf("%d", count + 1);  // 단어 개수 출력 (+1은 마지막 단어를 위함)
    
    return 0;
}

 

 

9. 상수

a. 문제지  : 2908

 

b. 정답

📚 풀이 1 : 변환 함수 작성

#include <stdio.h>

// 주어진 수를 거꾸로 읽어 새로운 수를 생성하는 함수
int reverse(int num) {
    int reversed = 0;
    while (num > 0) {
        reversed = reversed * 10 + num % 10;  // 현재 자릿수를 거꾸로 더함
        num /= 10;  // 다음 자릿수로 이동
    }
    return reversed;
}

int main() {
    int A, B;
    scanf("%d %d", &A, &B);

    int reversedA = reverse(A);  // A를 거꾸로 읽은 수
    int reversedB = reverse(B);  // B를 거꾸로 읽은 수

    int maxReversed = (reversedA > reversedB) ? reversedA : reversedB;  // 두 거꾸로 읽은 수 중 큰 값 선택

    printf("%d\n", maxReversed);  // 큰 값 출력

    return 0;
}

 

📚 풀이 2 : 단순 계산

#include <stdio.h>

int main() {
    int A, B; // 입력으로 받을 세 자리 수 A와 B
    scanf("%d %d", &A, &B);
    
    int newA = 0, newB = 0; // 거꾸로 읽은 수를 저장할 변수
    // 각 자릿수를 바꿔서 거꾸로 읽은 수 계산
    newA += A / 100 + (A / 10) % 10 * 10 + (A % 100 - ((A / 10) % 10 * 10)) * 100;
    newB += B / 100 + (B / 10) % 10 * 10 + (B % 100 - ((B / 10) % 10 * 10)) * 100;
    
    if (newA > newB) { // 거꾸로 읽은 수 중 큰 값을 출력
        printf("%d", newA);
    } else {
        printf("%d", newB);
    }
    
    return 0;
}

 

 

10. 다이얼

a. 문제지  : 5622

 

b. 알고리즘 / 풀이

  1. 문자열 입력을 받아서 변수 word에 저장
  2. 필요한 최소 시간을 나타낼 변수 time을 0으로 초기화
  3. 문자열의 각 문자를 순회하면서 다음을 수행
    a) 현재 문자를 대문자 알파벳으로 변환하여 숫자로 변환 (A: 0, B: 1, ..., Z: 25)
    b) 다이얼의 숫자 범위에 따라서 필요한 시간을 계산하여 time에 더함
  4. 최소 시간인 time을 출력

 

c. 정답

📚 풀이 1 : if문으로 풀이하기

#include <stdio.h>

int main() {
    char word[16];  // 입력받을 단어 (최대 길이: 15)
    scanf("%s", word);
    
    int time = 0;  // 필요한 최소 시간을 저장할 변수
    
    for (int i = 0; word[i] != '\0'; i++) {
        int dialNum = word[i] - 'A';  // 알파벳에 해당하는 다이얼 숫자 계산
        if (dialNum >= 0 && dialNum <= 2)  // ABC
            time += 3;
        else if (dialNum >= 3 && dialNum <= 5)  // DEF
            time += 4;
        else if (dialNum >= 6 && dialNum <= 8)  // GHI
            time += 5;
        else if (dialNum >= 9 && dialNum <= 11)  // JKL
            time += 6;
        else if (dialNum >= 12 && dialNum <= 14)  // MNO
            time += 7;
        else if (dialNum >= 15 && dialNum <= 18)  // PQRS
            time += 8;
        else if (dialNum >= 19 && dialNum <= 21)  // TUV
            time += 9;
        else if (dialNum >= 22 && dialNum <= 25)  // WXYZ
            time += 10;
    }
    
    printf("%d\n", time);
    
    return 0;
}

 

📚 풀이 2 : switch문으로 풀이하기

#include <stdio.h>

int main() {
    char word[16];  // 입력받을 단어 (최대 길이: 15)
    scanf("%s", word);  // 단어 입력받음
    
    int time = 0;  // 필요한 최소 시간을 저장할 변수 초기화
    
    for (int i = 0; word[i] != '\0'; i++) {  // 문자열의 끝(null 문자)에 도달할 때까지 반복
        int dialChar = word[i] - 'A';  // 입력된 알파벳을 대문자 'A'를 기준으로 숫자로 변환
        
        switch (dialChar) {  // 다이얼 숫자에 따라 필요한 시간을 계산
            case 0: case 1: case 2:
                time += 3;
                break;
            case 3: case 4: case 5:
                time += 4;
                break;
            case 6: case 7: case 8:
                time += 5;
                break;
            case 9: case 10: case 11:
                time += 6;
                break;
            case 12: case 13: case 14:
                time += 7;
                break;
            case 15: case 16: case 17: case 18:
                time += 8;
                break;
            case 19: case 20: case 21:
                time += 9;
                break;
            case 22: case 23: case 24: case 25:
                time += 10;
                break;
        }
    }
    
    printf("%d", time);  // 필요한 최소 시간 출력
    return 0;
}

 

11. 그대로 출력하기

a. 문제지  : 11718

 

b. 정답

📚 풀이

#include <stdio.h>

int main() {
    char line[101]; // 각 줄을 저장할 문자열 배열

    while (scanf(" %[^\n]", line) != EOF) { // 한 줄씩 입력을 받아옴
        printf("%s\n", line); // 입력받은 줄을 그대로 출력하고 줄바꿈
    }

    return 0;
}