この関数はチェックします部分文字列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.";
これを使用すると、ゼロも返されます:
char *needle = "non-existent"; char *haystack = "This is a dinosaurtest.";
この2つの例では、成功と失敗の違いがわかりません。実際、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
コメント
- 入力がNULLでないことのチェックを削除し、juそのための言語拡張を使用します(GCCでは
__attribute__((nonnull))
)。NULL
は、この関数の入力としては決して期待できないものであり、1行または2行の不要なコードが追加されます。関数のドキュメントに次のように記述したいと思います。"この関数への入力がNULLポインターの場合、動作は未定義です。"。 - @CacahueteFrito元のコードで実行されたので、互換性を追求したいと思います(OPがどのように使用していたかは誰にもわかりません)。
- div id = “1078bb5adc”>
:#include <sys/types.h>
。別のオプションは、代わりに#include <stddef.h>
からptrdiff_t
を使用することです。実際にはポインタの違いを返しています:? needle_in_haystack - haystack :
回答
コードが機能しません。haystack
"abbc"
とivに対して0
が返されますid = “17bb661e2a”>
"bc"
(haystack
にneedle
が含まれている場合でも) 。
回答
最初のループとすべての長さの計算は必要ありません。ところで、最初の文字が見つかった場合、関数は成功しませんが、最初の文字の2番目の出現のみが針に適合します。
タスクは数行に減らすことができます:
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 & RCを思い出させます。
strstr()
。 'はstrnstr()
と呼ばれるより安全なバージョンがあります。実装はここにあります: github.com/lattera/freebsd/blob/master/lib/libc/string/ …contains("tt", "test")
はtrueを返す必要がありますか?