나름 이틀동안 고민하고 애먹은 부분을 해소한 경험이 생겼기에 기록을 남기게 되었다.
전공과목 중 <문제해결기법> 과제를 풀면서 그려본 sudo-code.
문제에서 입력받는 정보와 출력해야 하는 정보를 간략하게 정리하고 어떤 툴로 문제를 접근할 것인지 스케치한 것이다.
이 문제는 exact match (찾고자하는 search string과 search string을 찾을 대상인 given string을 입력받아 몇 개의 sub-string(search string과 일치하는 given string의 부분)의 갯수를 count해 출력하는) 문제이다. 여기까지는 for문을 중첩으로 한번 사용하고 if 조건문을 이용해 풀 수 있었는데 문제는 다음이었다.
다음 문제는 partial match인데 search string으로 wildcard(*)를 입력받을 때를 고려해야 한다.
wildcard를 고려해야 한다는 말은, 입력받는 search string을 *을 기준으로 part1과 part2로 분류해야 하고, part1을 찾기 위한 exact match for loop 하나와 그 안에 조건문을 작성하여 part2를 찾기 위한 exact match for loop를 한번 더 작성해야 한다. 큰 툴을 보면 간단해 보이지만, for loop이 많이 사용되기 때문에 그만큼 for 문의 조건을 설정하는 것이 보다 까다로워진다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main() {
char given[200];
char search[20];
char part_1[20];
char part_2[20];
int i;
int j;
int m;
int l;
int how_many_search=0;
part_1[0] = '\0';
part_2[0] = '\0';
/*배열 초기화*/
printf("Type the string: ");
gets_s(given);
printf("Type the string to search (use * for wildcard): ");
gets_s(search);
int g_length = strlen(given);
int s_length = strlen(search);
for (i = 0; i < s_length; i++) {
if (search[i] == '*') {
/* If '*' is found, break out of the loop */
break;
}
part_1[i] = search[i];
}
part_1[i] = '\0';
if (search[i] == '*') {
/* Copy the remainder of the string to part_2 */
strcpy(part_2, search+i+1);
}
int p1_length = strlen(part_1);
int p2_length = strlen(part_2);
/*search for match _ part_1*/
for (int k = 0; k < g_length; k++) {
int sum_1 = 0;
for (j = 0; j < p1_length; j++) {
if (given[k + j] != part_1[j]) {
sum_1++;
break; /*if it is not sub-string, stop comparing*/
}
}
if (sum_1 == 0) {
/*search for match _ part_2*/
for (l = k+j; l < g_length; l++) {
int sum_2 = 0;
for (m = 0; m < p2_length; m++) {
if (given[l + m] != part_2[m]) {
sum_2++;
break; /*if it is not sub-string, stop comparing*/
}
}
if (sum_2 == 0) {
how_many_search++;
/*if it is sub-string, count match number*/
k = k + l + m;
/*To prevent double match counting*/
}
}
}
}
printf("Partial count: %d", how_many_search);
/*print match count number*/
return 0;
}
15일에 내가 생각한 코드다.
주어진 test dataset 중에서 7)을 빼고는 정상적인 출력값이 출력되었는데, 7)이 제대로 출력되지 않아 그 이유를 찾는 데 시간을 몰두했다. 급기야는 내가 예상한 출력값(출력값이 주어지지 않았음)이 틀렸는지 의심을 하게 되었다. 다른 dataset은 잘 출력되니까, 코드에 의심을 더한다기보다는 주어지는 string과 예상 출력값에 의구심을 두게 되었던 것 같다.
이 문제해결기법을 스터디 과목으로 진행하는 튜터링과 멘토링 선배님들께 여쭤보기 위해 한글파일까지 만들었을 정도였으니...!! ㅋㅋ,, 정말 나에겐 난감했다. 아예 코드가 틀린 것도 아니고 왜 저 dataset 하나만 제대로 안 나올까? 하는 생각이었다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main() {
char given[200];
char search[20];
char part_1[20];
char part_2[20];
int i;
int j;
int m;
int l;
int how_many_search=0;
part_1[0] = '\0';
part_2[0] = '\0';
printf("Type the string: ");
gets_s(given);
printf("Type the string to search (use * for wildcard): ");
gets_s(search);
int g_length = strlen(given);
int s_length = strlen(search);
for (i = 0; i < s_length; i++) {
if (search[i] == '*') {
/*If '*' is found, break out of the loop.*/
break;
}
part_1[i] = search[i];
}
part_1[i] = '\0';
if (search[i] == '*') {
/*Copy the remainder of the string to part_2*/
strcpy(part_2, search+i+1);
}
int p1_length = strlen(part_1);
int p2_length = strlen(part_2);
/*search for match*/
for (int k = 0; k < g_length; k++) {
int sum_1 = 0;
for (j = 0; j < p1_length; j++) {
if (given[k + j] != part_1[j]) {
sum_1++;
break; /*if it is not sub-string, stop comparing*/
}
}
if (sum_1 > 0) continue;
for (l = k+j; l < g_length; l++) {
int sum_2 = 0;
for (m = 0; m < p2_length; m++) {
if (given[l + m] != part_2[m]) {
sum_2++;
break; /*if it is not sub-string, stop comparing*/
}
}
if (sum_2 > 0) continue;
how_many_search++;
/*if it is sub-string, count match number*/
k = l + m; /*move search index to next to the find sub-string index*/
break; /*Go to search part 1 for loop!*/
}
}
printf("Partial count: %d", how_many_search);
/*print match count number*/
return 0;
}
결론을 먼저 말하자면, 최종 수정된 코드다.
사실 메인 tool에 오류가 있었다기 보다도, 마지막 if 조건문에서 변수 값 할당과 어떻게 종료할 것인가에 대한 이해 및 코드부족이었다.
[오류]
1) sum_2 가 0 인 것까지 확인한 후, 다시 given string에서 part1의 string을 찾아야 하기 때문에, index k의 값을 k+l+m이 아닌, l+m으로 할당해야 한다.
-> 이러한 오류가 일어난 것에 대한 내 생각은 k에다가 l+m의 값을 더해야 한다는 생각에 이렇게 작성하게 된 것 같은데, 생각해 보면 l은 이미 k+j의 값이기 때문에 k=k+l+m을 하게 된다면 k를 두 번 더하는 셈, 즉 중복을 카운팅하게 되는 셈이다.
2) 그리고 1)의 명령이 끝나면 다시 given string에서 part1의 string을 찾는 for문(맨 위의 for문)으로 돌아가야 하기 때문에, break를 써줘야 한다는 것. 만약 이 break가 없다면 part1을 찾은 후 그 이후의 part2의 개수만을 세는 꼴이 된다.
3) 7)의 dataset이 주어졌을 때, 내가 생각한 출력값은 5 또는 6이었는데, 실은 4였다. 왜냐하면 7)의 search string이 hong *dong, 즉 hong과 * 사이의 하나의 공백이 존재한다. 근데 코드에서 보다시피, 우리는 search string을 나눌 때, *을 기준으로 분류하기 때문에 결국 part1은 'hong'이 아닌 'hong '을 저장하게 된다. 따라서 7)의 dataset 중 'honggil dong'은 count에 포함되지 않는 것!
(+) 이 외의 수정은 코드의 가독성 및 효율을 위해 수정된 부분으로 개념의 오류는 아니었다.
.
.
.
사실 이러한 오류를 발견한 것은 온전한 나의 힘으로 한 것이 아닌 멘토링 멘토분과 함께 발견한 것이었다. 그래서 그 과정을 기록해 두면 이후에 문제가 발생했을 때, 이 절차를 떠올리고 스스로 문제를 해결할 수 있는 힘이 더 강해지지 않을까 하여 그 절차를 기록해두려 한다.
* 어디서 오류가 났는지 파악하는 것이 중요 -> 확신이 없는 코드 문 뒤에 printf로 그 값이 제대로 돌아가는지 확인해 보기
=> 사실 이 방법이 이번의 오류를 찾을 때, 가장 큰 도움이 되었다. for문에서 계속해서 값이 바뀌는 변수를 출력하게 했는데 한 번밖에 작동하지 않는 것을 보고, 2)의 오류를 찾아낸 것!
* dataset의 길이를 조절해 보면서(줄이거나, 늘리거나) 오류를 파악할 수 있음
=> 주어진 7)의 dataest - given string이 길기도 했고, 짧은 given string에서는 오류를 보이지 않아 그 길이를 줄여 출력값을 비교해 보며 오류를 파악하려는 접근을 시도할 수 있었다.
.
.
.
간단해 보이지만 사실 이러한 절차가 익숙하지 않으면, 오류 앞에서 당황하기 마련이다. 더하여 차근차근 코드를 살펴보고, 문제에 대한 정확한 이해를 위해서라도 주석다는 습관을 들여야겠다.
'studylog' 카테고리의 다른 글
231018 TIL (1) | 2023.10.18 |
---|---|
231017 TIL (0) | 2023.10.18 |
231013 TIL (2) | 2023.10.13 |
~231012 TIL (0) | 2023.10.12 |
230924 TIL (0) | 2023.09.24 |