シリーズ記事ディレクトリ
文字関数と文字列関数の詳細説明(1) strlen strcpy strcat strcmp
文字関数と文字列関数の詳しい解説(2) strncpy strncat strncmp strstr strtok (およびそのアナログ実装)
文字関数と文字列関数の詳細解説(3) strerror memcpy memmove memset memcmp (および一部の文字分類関数)
目次
2. 無制限の長さの文字列関数 strcpy strcat strcmp
このシリーズでは、C言語の文字関数や文字列関数の使い方と、それに関連してよく発生するエラーの原因と、エラーを回避するために注意すべき点について説明します。(初出: strlen strcpy strcat strcmp)
1. 文字列の長さを調べる関数 strlen
1.ストレン
(1) strlenの使用
C言語のstrlen関数は、文字列中に「\0」が現れるまでの文字数をカウントし、文字列中に「\0」が現れるとカウントを停止します。つまり、文字列の長さをカウントしたい場合は、文字列の末尾に「\0」が必要です。それ以外の場合、strlen は「\0」が見つかるまで次のメモリの検索を続けます。
int main()
{
char arr[] = "abcdefg"; //在字符串中默认在结尾处会有一个"\0"
printf("%d\n", strlen(arr)); //此处返回的便是七
}
strlen 関数が「\0」に遭遇したときにカウントを停止することを確認するには、文字列に「\0」を追加して、戻り結果が変わるかどうかを確認します。
int main()
{
char arr[] = "abc\0defg"; //我们在c的后面添加了\0,strlen会在找到"\0"时停止计数
printf("%d\n", strlen(arr)); //此时返回的结果应该是3
}
(2)ストレン使用上の注意
1. 文字列の長さをカウントする場合、次のコードを記述してはなりません。
//错误示范
int main()
{
char arr[] = { 'a', 'b', 'c' };
printf("%d\n", strlen(arr));
return 0;
}
この配列には「\0」が存在しないため、strlen 関数はメモリ内を検索し続け、非常に危険です。
2. 2つの文字列の長さのコードを比較したい場合、次のようなコードを書くことがよくあります。
//错误示范
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
printf(">\n");
else
printf("<\n");
return 0;
}
//我们常常认为此处返回的结果应该是 "<" ,但返回的结果让我们很是意外
ここで注意する必要があります: 最初の戻り結果は 3 で、2 番目の戻り結果は 6 (3-6=-3) であると考えますが、これはゼロ未満ではありませんか。ここでは strlen 関数自体を返す必要があります。 。
strlen 関数の関数型は size_t なので、size_t の定義に進みます。
実際には符号なし整数を返すことがわかります。そのため、上記のプログラムは実際には符号なし整数 -3 を返し、正の数を返すため、「>」が出力されます。
(3) strlenのシミュレーション実装
size_t my_strlen(const char* str) //使用const让目标字符串内容不可变吧,增加程序健壮性
{
assert(str); //此处加上断言,如若str是空指针,则直接停止程序,并打印错误信息
const char* star=str;
const char* end=str;
while (*end != '\0')
{
end++;
}
return end - star;
}
int main()
{
printf("%u",my_strlen("adfsdf"));
return 0;
}
結果:
2. 無制限の長さの文字列関数 strcpy strcat strcmp
1.strcpy
(1) strcpyの使用
strcpyは文字列をコピーするために使用されます。2 つのアドレスを渡す必要があります。1 つはターゲット空間の最初のアドレスで、もう 1 つはソース文字列の最初のアドレスです。コピーの処理中、strcpy はソース文字列内の「\0」をコピーの終了マークとして使用します。また、「\0」もターゲット スペースにコピーされます。
int main()
{
char arr[10] = "xxxxxxxxx";
char arr2[] = { 'a','b','\0','c' };
strcpy(arr,arr2);
printf("%s",arr);
return 0;
}
(2) strcpy使用時の注意点
1. ターゲット領域は、ソース文字列を保持するのに十分な大きさでなければなりません。
ターゲット領域がソース文字列を収容するのに十分でない場合は、次のコードを実行します。
//错误示范
int main()
{
char arr[2] = {0};
char arr2[] = "abcdefg";
strcpy(arr,arr2);
printf("%s",arr);
return 0;
}
2. 次のコードに示すように、ターゲット空間は変数である必要があります。
//错误示范
int main()
{
char* p = "hello world";//常量字符串
char arr2[] = "abcdef";
strcpy(p, arr2);
printf("%s\n", p);
return 0;
}
(3) strcpyのシミュレーション実装
char* my_strcpy(char* dest, const char* source)
{
assert(dest);
assert(source);
char* ret = dest;
while (*dest++=*source++)
{
;
}
return ret;
}
int main()
{
char arr[20] = { 0 };
char arr2[] = "davadvasdv";
printf("%s",my_strcpy(arr,arr2));
return 0;
}
結果:
2.壊れた
(1) strcatの使用
strcat 関数は、ターゲット文字列の後にソース文字列を追加するために使用されます。ターゲット文字列で「\0」が見つかった後、ソース文字列が追加され、ソース文字列の「\0」が終了マークとして使用されます。
int main()
{
char arr[8] = "arc";
char arr1[] = "arrr";
printf("%s",strcat(arr,arr1));//以arr1的"\0"作为结束标志,并且会将arr中的"\0"替换掉
}
//这里返回arrarrr
「\0」で終了していないかどうかをテストするには、次のコードをデバッグできます。
int main()
{
char arr[8] = "arc";
char arr1[] = "arr\0r";
printf("%s",strcat(arr,arr1));
}
デバッグ後の結果は次のようになります。
(2) strcat使用時の注意事項
1. ソース文字列は「\0」で終わる必要があります。末尾が「\0」でない場合は、見つかるまでメモリ内の「\0」を検索し続けます。
//错误示范
int main()
{
char arr[8] = "arc";
char arr1[] = {'a','b','c'}; //这里没有"\0",我们看看调试后的结果
printf("%s",strcat(arr,arr1));
}
2. ターゲット領域は、2 つの文字列の内容を保持するのに十分な大きさでなければなりません。
//错误示范
int main()
{
char arr[4] = "arc";
char arr1[] = "asdasd";
printf("%s",strcat(arr,arr1));
return 0;
}
3. ターゲット空間は可変である必要があります(strcpy使用上の注意事項の2番目を参照)
4. strcat 関数は自分自身を追加できず、自分自身を追加するときに自分の "\0" を上書きするため、無限に追加できるため、例外が発生します。
//错误示范
int main()
{
char arr[4] = "arc";
printf("%s",strcat(arr,arr));
return 0;
}
(3) strcatのシミュレーション実装
char* my_strcat(char* dest,const char* source)
{
assert(dest);
assert(source);
char* ret = dest;
while (*dest)
{
dest++;
}
while(*dest++=*source++)
{
;
}
return ret;
}
int main()
{
char arr[10] = "abc";
char arr1[] = "def";
printf("%s", my_strcat(arr, arr1));
return 0;
}
3.strcmp
(1) strcmpの使用
strmp関数は比較的シンプルで使い方さえわかれば基本的には間違えることはありません。
int main()
{
char arr1[] = "abc"; //比较的是对应字符的ascii码值的大小
char arr2[] = "abf";
if (strcmp(arr1,arr2) < 0)
printf("arr1<arr2\n");
else if (strcmp(arr1, arr2) > 0)
printf("arr1>arr2\n");
else
printf("arr1==arr2\n");
return 0;
}
(2) strcmp使用時の注意事項
なお、2つの文字列には終了記号「\0」が必要です。詳しくは上記で紹介した関数を参照してください。ここではあまり詳しく説明しません。
(3) strcmpのシミュレーション実装
int my_strcmp(const char* s1, const char* s2)
{
assert(s1);
assert(s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
return *s1 - *s2;
}
注:暗闇の中でカラフルである必要がありますが、小さいながらも川や山を照らします。