“文字列”には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; } 

コメント

  • "に。コードが意図したとおりに機能するかどうかは疑わしいです。
  • これはすでに存在します: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."; 

これを使用すると、ゼロも返されます:

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"haystackneedleが含まれている場合でも) 。

回答

最初のループとすべての長さの計算は必要ありません。ところで、最初の文字が見つかった場合、関数は成功しませんが、最初の文字の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を思い出させます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です