이 함수는 하위 문자열 needle
가 다른 문자열 haystack
에 존재하는지 여부 및 존재하는 경우 위치를 반환하고 그렇지 않은 경우 0을 반환합니다. 위치가 0이면 찾을 수 없습니다.
이 코드를 개선하는 방법, 특히 더 나은 오류 처리 방법을 찾고 있습니다.
#include <stdio.h> #include <stdlib.h> #include <string.h> size_t contains(const char * needle, const char *haystack); int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; printf("Position: %lu", contains(needle, haystack)); return EXIT_SUCCESS; } size_t contains(const char * needle, const char *haystack) { if(needle == NULL || haystack == NULL) { return 0; } long int first_char_pos = -1; size_t len_h = strlen(haystack); size_t len_n = strlen(needle); size_t i, j; size_t exist_count = 0; // Find the first character. If it doesn"t exist, we"re done. for(i = 0; i < len_h; i++) { if((haystack[i] == needle[0]) && (first_char_pos == -1)) { first_char_pos = i; exist_count++; } } if(first_char_pos == -1) { return 0; } printf("First char match index: %li\n", first_char_pos); printf("Char: %c\n", haystack[first_char_pos]); size_t current_index = (size_t) first_char_pos; for(i = first_char_pos; i < len_h; i++) { if(haystack[i] == needle[exist_count] && (i == (current_index + 1))) { current_index = i; exist_count++; } printf("Exist count: %lu\n", exist_count); //<--Debugging if(exist_count == len_n) { return first_char_pos; } } return 0; }
댓글
답변
몇 가지 언급 :
-
마지막 줄 뒤에 줄 바꿈을 추가해야합니다.
$ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $
-
무엇을 모르겠습니다. 사용하는 컴파일러이지만
gcc
및-Wall -Wextra -pedantic
로 컴파일하면 다음을 얻을 수 있습니다.gcc -O2 nh.c -lm -o nh -Wall -Wextra -pedantic nh.c: In function ‘contains’: nh.c:25:15: warning: unused variable ‘j’ [-Wunused-variable] size_t i, j; ^
-
코드 형식은 더 일관되어야합니다. 예를 들어이 줄에서는
needle
앞에 공백을 넣지 만 앞에 공백을 넣지 마십시오.haystack
:size_t contains(const char * needle, const char *haystack);
-
%lu
는size_t
유형에 대한 이식 가능한 지정자가 아닙니다. C99에 도입 된%zu
를 사용해야합니다. -
내가 말한 내용 :
위치가있는 경우 위치를 반환하고 그렇지 않은 경우 0을 반환합니다. 위치가 0이면 찾을 수 없습니다.
정말 좋지 않습니다. 예를 들어 다음과 같이 0을 반환합니다.
char *needle = "This"; char *haystack = "This is a dinosaurtest.";
이렇게하면 0도 반환됩니다.
char *needle = "non-existent"; char *haystack = "This is a dinosaurtest.";
이 두 가지 예에서 성공과 실패의 차이를 구분할 수 없습니다. 실제로 atoi()
에는 동일한 문제가 있습니다. 어떤 운영 체제를 사용하는지 모르겠습니다. 하지만 가능한 경우 반환 유형으로 ssize_t
를 사용하고 실패 할 경우 -1을 반환 할 수 있습니다.
답변
@Arkadiusz Drabczyk의 이전 답변에 추가 :
contains
의 간단하고 사소한 구현은 다음과 같습니다. 다음과 같이 수행됩니다.
ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; }
그러면이 프로그램 (위에서 언급 한대로 약간 변경됨)이 작동합니다.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; char *haystack2 = "This does not contain the string."; printf("Position: %zd\n", contains(needle, haystack)); printf("Position: %zd\n", contains(needle, haystack2)); return EXIT_SUCCESS; }
출력 :
위치 : 18
위치 : -1
Comments
- 입력이 NULL이 아닌지 확인하고 ju st는이를 위해 언어 확장을 사용합니다 (GCC의 경우
__attribute__((nonnull))
).NULL
는이 함수에 대한 입력으로 예상 할 수없는 항목이며 불필요한 코드 줄을 한두 줄 추가합니다. 다음과 같은 함수 문서를 작성하고 싶습니다. "이 함수에 대한 입력이 NULL 포인터이면 동작이 정의되지 않습니다. ". - @CacahueteFrito 원래 코드가 해냈고 호환성을 위해 노력하고 싶습니다 (OP가 어떻게 사용했는지 알 수 있습니까?).
-
ssize_t
:#include <sys/types.h>
. 다른 옵션은 대신#include <stddef.h>
에서ptrdiff_t
를 사용하는 것입니다. 실제로 포인터 차이를 반환합니다.? needle_in_haystack - haystack :
Answer
코드가 작동하지 않습니다. haystack
"abbc"
및 iv에 대해 0
를 반환합니다. id = “17bb661e2a”>
"bc"
(haystack
에 needle
포함) .
Answer
첫 번째 루프와 모든 길이 계산이 필요하지 않습니다. Btw., 첫 번째 문자가 발견되면 함수는 성공하지 못하지만 첫 번째 문자의 두 번째 발생 만 needle에 맞습니다.
작업은 몇 줄로 줄일 수 있습니다.
int contains(char *buf, char *needle) { char *src, *srch, *srcp; for(src=buf; *src; src++) { for(srch = needle, srcp = src; *srch && *srcp && *srch == *srcp; srch++, srcp++); if(!*srch) return src - buf; } return -1; }
댓글
- 이와 같이보다 간결하고 효율적인 C 코드를 더 잘 작성하는 좋은 방법은 무엇입니까? ?이렇게하면 K & R C가 생각납니다.
strstr()
. 'strnstr()
라는 더 안전한 버전이 있습니다. 다음에서 구현을 찾을 수 있습니다. github.com/lattera/freebsd/blob/master/lib/libc/string/ …contains("tt", "test")
가 true를 반환해야합니까?