본문 바로가기
studylog

231015~16 TIL

by Nam Kyeongmin 2023. 10. 16.

나름 이틀동안 고민하고 애먹은 부분을 해소한 경험이 생겼기에 기록을 남기게 되었다.

전공과목 중 <문제해결기법> 과제를 풀면서 그려본 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과 예상 출력값에 의구심을 두게 되었던 것 같다.

 

231016 문해기 질문.hwpx
0.56MB

이 문제해결기법을 스터디 과목으로 진행하는 튜터링과 멘토링 선배님들께 여쭤보기 위해 한글파일까지 만들었을 정도였으니...!! ㅋㅋ,, 정말 나에겐 난감했다. 아예 코드가 틀린 것도 아니고 왜 저 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