100 likes | 240 Views
문자열에서 pattern 찾기 - 문제이해 - 참고 코드. (F5 누르고 보세요 .) 최윤정. 문자열 str 에서 pattern 이 나타나는 위치와 횟수 !. str. pattern. str 에서 pattern 을 찾아보세요 . 눈으로는 금방 보이죠 ? 굉장히 많은 일들이 일어났는데 , 너무 빠른 속도로 일어나서 마치 한번에 한 것처럼 보이는 거에요 . 여러분이 생각한 것들을 한단계씩 delay 를 주어서 다시 천천히 생각합니다 . - 무엇과 무엇을 비교해야 하나 ?
E N D
문자열에서 pattern찾기-문제이해-참고 코드 (F5 누르고 보세요.) 최윤정
문자열str에서 pattern이 나타나는 위치와 횟수! str pattern • str에서 pattern을 찾아보세요. 눈으로는 금방 보이죠? • 굉장히 많은 일들이 일어났는데, 너무 빠른 속도로 일어나서 마치 한번에 한 것처럼 보이는 거에요. • 여러분이 생각한 것들을 한단계씩delay를 주어서 다시 천천히 생각합니다. • -무엇과 무엇을 비교해야 하나? • -언제까지 비교해야하나? • -비교해서 어떤 일이 있었을 때, pattern이 찾아졌다고 생각할 수 있나.
i str • 배열의 값은 한꺼번에 비교할 수 없고, 각 셀의 값을 하나하나 비교해야 했어요. • 그래서, str의 셀들, 즉 배열요소값과pattern의배열요소값을 나타내기 위해 index 가필요합니다. • 그래서, 이제부터는각 문자열의 각셀의 값 str[i] == pattern[p_i] 를 비교합니다. 단, • i 의 유효범위는 0~str의 길이-1만큼, • p_i는0부터 pattern의 길이-1만큼. 여기서는 2만큼 • 그런데, i는 굳이 끝자리까지 비교할 이유가 없죠. 10번째 값이 pattern의 첫자리와같다한들무의미하니까. • 그래서 i의 유효범위를 조정하자면 0 ~ (str의길이-1) – (pattern의 길이-1) . Ok죠? pattern p_i
6 4 8 3 2 7 5 0 9 1 str 그럼 이제부터는 각 index의 위치를 옮겨가면서 비교를 합니다. 무엇을 어떻게 비교할런지는 알아졌겠고, 언제까지 비교할 것인지가 문제죠? 우선, str의 가장 첫번째 문자열부터 • str[0] == pattern[0]; 을 비교합니다. 다르네요. 그럼 그 다음자리 • str[1] == pattern[0]; 다르죠? • str[2] == pattern[0]; 또 다르죠? • str[3] == pattern[0]; 이제 같네요. 같으니까 이제는 str과 pattern 의다음자리와도 비교합니다 • str[4] == pattern[1]; 같으니까, 또 pattern의다음자리. • str[5] == pattern[2]; 이제 같네요. • 모두 같아요. 모두 같다는 표현을 여러 가지로 해줄 수 있는데, 같았던 횟수와 pattern의 길이를 이용해보세요. pattern 1 0 2 2 1
i str 그럼 정리를 해봐요. i와 p_i를 이용해서 str[i] 와 pattern[p_i] 의 비교. i는 0부터 ~ 7까지, p_i는 0~2 까지, //실제로는 길이 구해서 하세요.~! 만약에 (str[i] !=pattern[p_i] ) 이면 i++ 같으면이제 i++, p_i++ 언제까지? 두 값이 다를 때까지. 그래서, 값이 같았던 횟수(다른 counter 변수를쓰던가, i 의 값을이용해도 되요)와 pattern 의길이를 봅니다. pattern //source 만들 수 있겠죠. //우선 생각해 보시고들, 나중에 올려줄께요. intfind_patter(char str[], char pattern[]){ //pattern의문자가 발견되는 곳부터찾아서, // 내부 비교를 수행합니다. } p_i
Ver1. 오로지비교만. char *str="12345aabc890abcd"; char *pattern="abc"; inti; // str용 인덱스 intp_i; //pattern용 인덱스 for(i=0; i < strlen(str) - strlen(pattern)+1; i++){ p_i=0; if ( str[i]==pattern[p_i] && str[i+1]==pattern[p_i+1] && str[i+2]==pattern[p_i+2]) ….. 또는 if ( str[i]==pattern[p_i] &&){ else if (str[i+1] == pattern[p_i+1]) ……. else if (str[i+2] == pattern[p_i+2]) ..… else if (str[i+2] == pattern[p_i+2]) ……….. 언제까지 이렇게 할 수는 없지요!! • for(k=0; k < strlen(pattern); k++){ • if ( str[i+0] == pattern[0]) count++; • if ( str[i+1] == pattern[1]) count++; • if ( str[i+2] == pattern[2]) count++; • }
Ver2. 비교와 반복을 적절히 char *str="12345aabc890abcd"; char *pattern="abc"; inti; // str용 인덱스 intp_i; //pattern용 인덱스 for(i=0; i < strlen(str) - strlen(pattern)+1; i++){ p_i=0; if( str[i] == pattern[p_i] ) { for(p_i=0; str[i + p_i ]==pattern[p_i] && p_i < strlen(pattern); i++, p_i++) { ; // 같은 문자가 나올 때까지 위 인덱스들을 증가시킵니다. } //위 루프를 마친후에p_i가 pattern의 길이가 같다면, 문자열이 발견되었다고 볼 수 있지요? if( p_i == strlen(pattern)) { printf("%d 에서 문자열 발견 \n",j); i += p_i; //발견하고 끝이 아니라, i의 위치를 j만큼 건너뛰도록 조정합니다. } } 천천히 로직을 잡아서 코딩해 봅니다. printf("str[%d]: %c ==? pattern[%d]: %c \n",i, str[i], p_i, pattern[p_i]); //이 쯤에서 출력해보면서 테스트하세요.
Ver3. 비교 + 반복을 좀 더 세련되게 char *str="12345aabc890abcd"; char *pattern="abc"; inti; // str용 인덱스 intp_i; //pattern용 인덱스 for(i=0; i < strlen(str) - strlen(pattern)+1; i++){ for( p_i=0; str[i+p_i]==pattern[p_i] && p_i < strlen(pattern);p_i++) { ; } if( p_i == strlen(pattern)) { printf("%d 에서 문자열 발견 \n",j); i += p_i; //발견하고 끝이 아니라, i의 위치를 j만큼 건너뛰도록 조정합니다. } } 불필요하게 반복되는 부분을 없애주면서 코드를 정리해갑니다.
Ver4. 주요작업은 함수로! 시작 문자가 같을 때 모든 문자열을 비교하자. char *str="12345aabc890abcd"; char *pattern="abc"; inti; // str용 인덱스 intp_i; //pattern용 인덱스 for(i=0; i < strlen(str) - strlen(pattern)+1; i++){ if( check_str(&str[i], pattern) == 1) { printf("%d 번에서 문자열 발견 \n”,i); i += strlen(pattern); // strlen(pattern) 은 여러 번, 변수에 저장해두고 사용하는 편이 좋습니다. } } • intcheck_str(char *str, char*pattern) • { • //기타 예외처리if(*str!= *pattern) return 0; //더 이상 볼 것도 없이 out.! • return my_strcmp(str, pattern); // 같으면 1, 다르면 0. • } • intmy_strcmp(char *str, char *pattern) • { • inti; • for(i=0; str[i]==pattern[i] && i< strlen(pattern); i++) • ; • if (i==strlen(pattern)) return 1; • return 0; • }
Ver5. 완성된 find_pattern(char str[], char pattern[]) intfind_pattern(char *str, char *pattern){ inti; // str용 인덱스 //약간의 예외처리 if( strlne(str) < strlen(pattern)) return -1 ; // 찾기 불가능. for(i=0; i < strlen(str) - strlen(pattern)+1; i++){ if( check_str(str+i, pattern) == 1) { //str+ i == &str[i] printf("%d 번에서 문자열 발견 \n”,i); i += strlen(pattern); } } 여러 작업에서도 활용할 수 있도록 함수의 인자나return 값들은 조정합니다. • intcheck_str(char *str, char*pattern) • { • //기타 예외처리if(*str!= *pattern) return -1; //더 이상 볼 것도 없이 out.! • return my_strcmp(str, pattern); // 같으면 0, 다르면 -1. • } • intmy_strcmp(char *str, char *pattern) • { • inti; • for(i=0; str[i]==pattern[i] && i< strlen(pattern); i++) • ; • if (i==strlen(pattern)) return 0; • return-1; • }