[C언어-기초실습-6] 입력된 문자열이 회문인지 체크하시오?
[C언어-기초실습-6] 입력된 문자열이 회문인지 체크하시오?
- 다운 사이트 : https://sourceforge.net/projects/orwelldevcpp/
- 웹컴파일러 : https://www.tutorialspoint.com/compile_c_online.php
오늘은 회문을 체크하는 코딩을 연습하도록 하겠습니다. 회문이라는 것은 앞으로 읽으나 뒤로 읽으나 같은 단어로 구성된 문자열을 마합니다. 예로 "aba" 앞으로 읽으나 뒤로 읽으나 같은 형태를 말하는 것이죠. 이 회문을 프로그램 상 어떻게 찾아내는지 이제 알아 봅시다.
1. 문제의 이해
회문이란 앞으로 읽으나 뒤로 읽으나 문장이 같을 때 이 문자열을 회문이라고 합니다.
예로 " wow"라는 문자열을 앞으로 읽어나 뒤로 읽으나 같은 문자열입니다. 이걸 코딩을 한다면 어떻게 해야 할까요.
우선 문자열을 한글짜씩 쪼개야 합니다.
예) "wow"
이 문자열은 어디에 저장 될까요. 배열변수에 저장되겠죠.
char str[3] = "wow"
앞으로 뒤로 읽어도 같은 문자열인지 체크하기 위해서는 앞글자와 뒷글자를 서로 일치하는지 체크하면 됩니다. 그런데 체크는 언제까지 할가요. 전체 문자열을 2로 나눈 글자수 만큼 체크하면 됩니다
for(i=0;i<문자열길이/2;i++}{
if(str[i]!=str[문자열길이-1-i]){
printf("회문이 아니다 \n");
break;
}
}
문자열의 각 문자를 대칭으로 비교하는데 for문으로 표현하면 전체 문자열 길이만큼 for문을 돌릴 필요가 없습니다. 서로 앞뒤 문자를 비교를 하기 때문에 절반의 루프를 돌면 됩니다. 그래서 문자열길이/2만큼 for문 i를 돌리면 됩니다.
그리고,
if(str[i]!=str[문자열길이-1-i]){ }
i=0일 때 str[i]는str[문자열길이-1-i] 표현은 앞첫글자 str[0]와 뒷첫글자 str[문자열길이-1-0]을 비교합니다. i가 1씩 증가할 때마다 앞 두번째글자와 뒷 두번째 글자를 비교합니다. 그런데 문자열길이는 NULL 문자열 포함한 문자열 길이의 수를 나타내는데 문자열은 주소지 0번째 부터 이기에 3글자이면 strlen(str)의 값은 3이 반환 됩니다. 마지막 글자의 위치는 문자열길이 -1을 해야 해당 위치를 가리키기 때문에 "문자열길이-1-i"라 표현합니다.
str_L=strlen(inputStr);
for(i=0;i<str_L/2;i++){
if(inputStr[i]!=inputStr[str_L-1-i]){
printf("회문이 아니다!\n");
break;
}
}
배열변수 선언과 문자열 입력
char inputStr[10];
printf("문자열을 입력하시오? ");
scanf("%s",inputStr);
scanf()함수로 서식문자 "%s"을 이용하여 inputStr배열번지에 문자열을 저장하게 됩니다.
참고로 다음 함수로도 표현이 가능합니다.
gets(inputStr);
표현은 여러분들의 자유 입니다.
포인트 배열변수 선언과 문자열 입력
포인트 배열변수를 선언하여 문자열을 입력 받을 수도 있습니다.
char *inputStr = malloc(sizeof(char) * 10);
printf("문자열을 입력하시오? ");
scanf("%s",inputStr);
//gets(inputStr);
문자열 길이
#include <stdlib.h>
int str_L;
str_L=strlen(inputStr);
2. 코딩
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
int main(int argc, char *argv[]) {
char inputStr[10];
//char *inputStr = malloc(sizeof(char) * 10);
int i;
int str_L;
printf("문자열을 입력하시오? ");
scanf("%s",inputStr);
//gets(inputStr);
str_L=strlen(inputStr);
for(i=0;i<str_L/2;i++){
if(inputStr[i]!=inputStr[str_L-1-i]){
printf("회문이 아니다! =>");
break;
}
}
printf("%s \n",inputStr);
system("pause");
return 0;
}
참고로,
printf("%s \n",inputStr);
이 표현을 쪼개서 한글짜식 출력 한다면 다음과 같습니다.
for(i=0;i<str_L;i++){
printf("%c",inputStr[i]);
}
printf("\n");
표현이 다양하죠.
[결과]
3. 사용자 정의 함수로 main()함수 코딩을 간단화
[전체소스]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
int Palindrome(char *str){
int i;
int str_L;
int state=1;
str_L=strlen(str);
for(i=0;i<str_L/2;i++){
if(str[i]!=str[str_L-1-i]){
state=0;
break;
}
}
return state;
}
int main(int argc, char *argv[]) {
char inputStr[10];
int i;
int chk;
printf("문자열을 입력하시오? ");
scanf("%s",inputStr);
chk=Palindrome(inputStr); //회문 체크
if(chk==1) printf("%s은 회문이다.\n",inputStr);
else printf("%s은 회문이 아니다.\n",inputStr);
system("pause");
return 0;
}
위 소스를 보시면 회문을 찾는 처리문을 전부 사용자 정의 함수로 만들어서 코딩을 옮겼습니다. 그래서 main()함수를 보시면 최소화 된 코딩으로 보기가 편해졌습니다. main()함수 내 코딩을 보면 뭘 코딩 한지 가독성이 높아졌을 거에요. 이렇게 특정 알고리즘을 따로 사용자 정의 함수로 표현하면 단지 main()함수 내에서는 함수명만 코딩해서 그 의미를 쉽게 알아볼 수 있습니다.
[결과]
마무리
오늘은 회문을 구하는 코딩을 해보았는데 같은 표현의 코딩을 좀 다르게 코딩하는 법을 다뤘네요. 그리고 회문 알고리즘을 사용자 정의 함수로 외부로 빼내 main()함수 코딩을 최소화 시켜보았습니다. 여기서 사용자 정의 함수로 표현한 회문 알고리즘을 재귀함수로 표현이 가능한데 그 부분은 일부러 여러분들이 지난 시간에 연습한 실습 재귀함수 코딩을 한 실습 약수와 소수 구하는 실습 두편의 내용을 잘 읽고 원리를 이해하셔서 오늘 회문 구하는 원리를 재귀함수로 수정하시면 됩니다. 재귀함수의 원리를 이용한다면 딱하나 문자열을 비교할 때 일치하면 다시 자기 자신함수를 재호출하여 다음 글자를 비교하는 식으로 재귀함수를 표현 하면 됩니다. 약수와 소수 구하는 코딩에서 살펴본 재귀함수의 원리를 이해하시면 충분히 이 실습 내용도 재귀함수로 표현이 가능 할 거라 생각 됩니다.
한번 도전해 보세요.