백준 - 단어 공부(1157번)

nyun-nye·2025년 1월 22일

백준 스터디

목록 보기
2/15

백준 - 단어 공부(1157번)

문제

  • 알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

입력

  • 첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.

출력

  • 첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다. 단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.

오랜만에 C언어로 문제를 풀어서 그런지 언어 사용하는 것에 익숙해지는데 시간이 꽤 오래 걸렸다. 아래는 문제를 해결하는 과정에서 어려움을 겪었던 문법들이다.

시행 착오

문제 해결의 단계는 아래와 같다.

  1. 단어를 입력받아야한다. C에서는 문자열 자체를 입력받기가 어려워 배열로 문자열을 받으려 시도했다. 이때 가변배열을 사용하려했으나 주의할 점은 입력받을 때 문자열의 길이가 정해지지 않는다는 것이다. 이를 해결하고자 realloc()으로 재할당을 시도했다.
  2. 입력받은 단어를 대문자로 변환한다. 이 과정에서 toupper(); 함수를 사용한다. <ctype.h>를 include 해야한다.
  3. 대문자로 변환한 알파벳에서 각각 입력받은 횟수를 배열에 저장한다.
  4. 각 알파벳 중 가장 많이 사용된 알파벳의 갯수를 알아낸다. 이를 max 변수에 저장한다.
  5. 가장 많이 사용된 알파벳이 여러 개 존재하는 경우를 판별하기 위해 max 값만큼의 값을 가진 알파벳이 2개 이상이면 "?"를 출력한다.

1차 시도

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
  int main() {
      int size = 10;
      int count = 0;
      char string[26] = { 0 }; // 알파벳 26개를 카운트하기 위한 배열
      char* word = (char*)malloc(size * sizeof(char));
      int max = 0;
      int index = 0;
      int check = 0;

      for (int i = 0;; i++) {
          if (count == size) {
              size *= 2;
              word = realloc(word, size * sizeof(char));
          }

          scanf("%c", &word[i]);
          count++;
          if (word[i] == '\n') {
              word[i] = '\0'; // 문자열의 끝을 표시
              break;
          }
      }

      for (int i = 0; i < count; i++) {
          word[i] = toupper(word[i]);
          if (word[i] >= 'A' && word[i] <= 'Z') {
              string[word[i] - 'A']++;
          }
      }

      for (int i = 0; i < 26; i++) {
          if (string[i] > 0 && string[i] > max) {
              max = string[i];
              index = i;
          }
      }

      for (int i = 0; i < 26; i++) {
          if (string[i] > 0 && string[i] == max) {
              check++;
          }
          if (check >= 2) {
              printf("?");
              return;
          }
      }

      printf("%c", index + 'A');

      free(word); // 동적 메모리 해제
      return 0;
  }

이 부분에서 문제가 된 점은 string 배열을 char 타입으로 설정한 것이다. string 배열은 각 알파벳의 갯수를 카운트하기 위한 배열이므로 int 타입으로 수정하고 난 후 해결되었다.

2차 시도

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h> // 이게 머지?
int main() { // 런타임 에러
      int size = 10;
      int count = 0;
      int string[26] = { 0 }; // 알파벳 26개를 카운트하기 위한 배열
      char* word = (char*)malloc(size * sizeof(char));
      int max = 0;
      int index = 0;
      int check = 0;

      for (int i = 0;; i++) {
          if (count == size) {
              size *= 2;
              word = realloc(word, size * sizeof(char));
          }

          scanf("%c", &word[i]);
          count++;
          if (word[i] == '\n') {
              word[i] = '\0'; // 문자열의 끝을 표시
              break;
          }
      }

      for (int i = 0; i < count; i++) {
          word[i] = toupper(word[i]);
          if (word[i] >= 'A' && word[i] <= 'Z') {
              string[word[i] - 'A']++;
          }
      }

      for (int i = 0; i < 26; i++) {
          if (string[i] > 0 && string[i] > max) {
              max = string[i];
              index = i;
          }
      }

      for (int i = 0; i < 26; i++) {
          if (string[i] > 0 && string[i] == max) {
              check++;
          }
          if (check >= 2) {
              printf("?");
              return;
          }
      }

      printf("%c", index + 'A');

      free(word); // 동적 메모리 해제
      return 0;
  }

string 배열의 타입을 int로 수정하고 난 후에는 런타임 에러가 발생하였다. 여러 문제점을 찾아보았다.

내가 생각한 문제점

  1. 배열의 동적 할당
    배열을 동적으로 할당받지 않고 처리하면 이 문제를 해결할 수 있을지도 모른다. 또한, 굳이 이 문제에서 배열을 동적으로 처리할 필요성이 없다고 느껴진다. 문제를 다시 읽어보니 문제 내에서 단어의 길이가 정해져 있기 때문이다.
  2. \n문제
    문자열의 끝을 표시할 때 \n을 사용할 이유가 없다. 단어는 공백이 없고, scanf 함수는 공백이 입력되면 자동으로 입력이 끝났다고 처리하기 때문이다.
  3. 전반적인 코드의 복잡성
    코드가 전체적으로 복잡하게 짜여있다고 생각되었다. 코드를 조금 더 간결하게 구성하여 문제점이 한 눈에 보이게 할 필요가 있다.

이러한 문제점들을 개선하여 제출한 답은 아래와 같다.

제출한 답

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h> // toupper 사용 위함
#include <string.h> // strlen 사용 위함


int main() {
	char word[1000000];
	scanf("%s", word);
	int len = strlen(word);
	int string[26] = {0}; // 26개 알파벳
	int max=0;
	int count = 0;
	int index;
	
	for (int i = 0; i < len; i++) {
		word[i] = toupper(word[i]);
		string[word[i] - 'A']++;
	}
	for (int i = 0; i < 26; i++) {
		if (string[i] > 0 && max < string[i]) {
			max = string[i];
			index = i;
		}
	}
	for (int i = 0; i < 26; i++) {
		if (max == string[i])
			count++;
	}
	if (count > 1) {
		printf("?");
	}
	else {
		printf("%c", 'A' + index);
	}
}
💡한줄평
C언어를 2023년 1학기에 학습하고 그 이후로 오랜만에 C언어로 문제풀이를 진행했다. 그래서 그런지 C문법에 익숙해지는데 시간이 조금 걸릴 것 같다. 앞으로 C로 문제 많이 풀어봐야징~
profile
시야가 넓은 개발자가 되기를 희망합니다.

0개의 댓글