“ 문자열 ”는 C의 함수를 포함합니다.

이 함수는 하위 문자열 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; } 

댓글

  • " contains . 코드가 의도 한대로 작동하지 않는 것 같습니다.
  • 이미 존재합니다 : strstr(). ' strnstr()라는 더 안전한 버전이 있습니다. 다음에서 구현을 찾을 수 있습니다. github.com/lattera/freebsd/blob/master/lib/libc/string/ …
  • @RolandIllig : 이유를 설명해 주시겠습니까?
  • contains("tt", "test")가 true를 반환해야합니까?
  • @ CacahueteFrito 그래서, 프로그램 불변에 의존하거나 데이터를 패치하거나 오류를보고하는 대신 드문 상황에서 데이터 손상을 감추기 위해 사용성 성능에 상당한 비용을 지불합니까? 모든면에서 좋지 않은 생각 인 것 같습니다.

답변

몇 가지 언급 :

  • 마지막 줄 뒤에 줄 바꿈을 추가해야합니다.

     $ ./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); 
  • %lusize_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" (haystackneedle 포함) .

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가 생각납니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다