1.strlen-文字列の長さを見つけます
1.1strlenの宣言と使用
strlen、基本的な英語があれば、この関数が文字通りの意味で何に使用されているかを知ることは難しくありません。strは文字列、文字列の意味、lenは長さ、長さの意味です。つまり、strlenは、文字列の長さを見つける関数です。cplusplus Webサイトを使用して、strlenの関数宣言と各パラメーターの意味を観察します。
strlenに必要な文字列の長さは、文字列の終わりまでの文字数であることがわかります。つまり、文字列「hello world」があると仮定すると、必要な文字列の長さは、「\0」の前のすべての文字数である11です。次に、この文字列の長さが戻り値によって返されるため、文字列の長さを知りたい場合は、戻り値を受け取る変数を定義する必要があります。その場合、パラメータ部分はもちろん文字列の最初のアドレスです。
1.2strlenの使用法
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "hello world";
char* str2 = "hello world";
int len1 = strlen(str1);//数组名表首元素地址
int len2 = strlen(str2);//str2 指针变量存放的也是首元素地址
printf("%d\n", len1);
printf("%d\n", len2);
//这种写法也可以输出长度
//printf("%d\n", strlen(str1));
//printf("%d\n", strlen(str2));
return 0;
}
注意すべき点の1つは、strlenの戻り値がsize_t型であり、これは符号なし整数であるということです。その意味は、長さを見つけるときに負の数を見つけることができないため、メモリがある程度最適化されることです(符号付き整数を使用すると、負の数を格納するために使用されるスペースが無駄になります)。
1.3strlenのシミュレーション実装
上記のstrlenの原理を分析したので、今は学んだことを使用して、独自のstrlen関数を「作成」します。
#include <stdio.h>
#include <assert.h>
unsigned int my_strlen(const char* str)//我们不改变字符串的内容,所以用 const 来进行修饰
{
assert(str);//避免是一个空指针
unsigned int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char str1[] = "hello world";
char* str2 = "hello world";
int ret1 = my_strlen(str1);
int ret2 = my_strlen(str2);
printf("%d\n", ret1);
printf("%d\n", ret2);
return 0;
}
2.strcpy-文字列のコピー
2.1strcpyの宣言と使用
私たちはその直訳、strテーブル文字列、つまり文字列、cpyテーブルコピー、つまりコピーを理解しています。つまり、strcpy関数は文字列をコピーするために使用されます。次に、cplusplus Webサイトを使用して、strcpyの宣言と各パラメーターの意味を観察します。
strcpyの機能を知るために変換し、ソースポインターが指す文字列を、宛先ポインターが指す配列にコピーします。コピーされたコンテンツには、文字列ターミネーターが含まれます。また、宛先ポインターが指す配列には、コピー後に内容を保持するのに 十分なスペースが必要です。
このことから、strcpyには2つのパラメーターが必要であることがわかります。1つは配列で、もう1つは文字列です。また、配列のスペースは十分に大きくなければなりません。戻り値は、返された配列がコピーされる前のアドレスです。これの意味は、コピーの前にコンテンツが失われるのを防ぐことです。
2.2strcpyの使用法
#include <stdio.h>
#include <string.h>
int main()
{
char dest[20] = "row your boat";
char src[] = "hello world";
strcpy(dest, src);
printf("%s\n", dest);
return 0;
}
これはstrcpyの最も一般的な使用法です。覚えておく必要があるのは、コピーされたコンテンツに「\0」が含まれていることです。つまり、コピーした文字列の長さが配列の元の文字列ほど長くなくても、C言語の観点から、「\ 0」の後の内容は、「\0」を含めます。最初から数えません。文字列の内容。
2.3strcpyのシミュレーション実装
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)//dest 指向的数组空间是要被改变的,但是 src 指向的字符串不需要改变
{
assert(dest && src);//防止其中某个是无效指针
char* ret = dest;
while (*dest++ = *src++)
; //注意 while 循环执行了空语句
return ret;
}
int main()
{
char dest[30] = "gently down the stream";
char src[] = "life is but a dream";
my_strcpy(dest, src);
printf("%s\n", dest);
return 0;
}
3.strcmp-文字列の比較
3.1strcmpの宣言と使用
同じことが当てはまります。直訳により、この関数が何に使用されるかを大まかに理解できます。strテーブル文字列、つまり文字列、cmpテーブル比較、つまり比較。また、 cplusplus Webサイトを通じて、この関数の宣言と各パラメーターの意味を確認します。
この関数を翻訳することで、この関数の原理を知ることができます。原則は次のとおりです。比較は2つの文字列の最初の文字から始まります。2つの文字が等しい場合、2つの文字列は、2つの文字が等しくなくなるまで次の文字のペアを比較してから、サイズを比較します。最初の文字が2番目の文字よりも小さい場合は0未満の整数を返し、等しい場合は0を返し、より大きい場合は0より大きい整数を返します。
その引数は両方とも、比較する文字列です。理解を容易にするために、図面の形で理解しています。
3.2strcmpの使用法
#include <stdio.h>
#include <string.h>
int main()
{
char* str1 = "abbbcd";
char* str2 = "abbbdd";
int ret = strcmp(str1, str2);
if (ret > 0)
printf("str1 > str2\n");
else if (ret < 0)
printf("str1 < str2\n");
else
printf("str1 == str2\n");
return 0;
}
3.3strcmpのシミュレーション実装
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)//两个字符串的内容都不需要修改,用 const 修饰
{
assert(str1 && str2);//防止是无效指针
while (*str1 == *str2)//如果相等则进入循环
{
if (*str1 == '\0')//*str1 == '\0' 了并且进入循环了,说明两个字符串比较完成了,没有不相等的字符
return 0;
str1++;
str2++;
}
return *str1 - *str2;//两个字符的差作为返回值
}
int main()
{
char* str1 = "abbbcd";
char* str2 = "abbbdd";
int ret = my_strcmp(str1, str2);
if (ret > 0)
printf("str1 > str2\n");
else if (ret < 0)
printf("str1 < str2\n");
else
printf("str1 == str2\n");
return 0;
}
4.strcat-文字列追加
4.1strcatの宣言と使用
cplusplus Webサイト を使用して、strcatの宣言と各パラメーターの意味を確認します。
strcat関数が使用されるまで翻訳します。ソースポインタが指す文字列を宛先ポインタが指す配列に追加し、十分なスペースがあり(文字列に追加しようとしましたが失敗しました)、追加された場所文字列の「\0」を指す宛先ポインタです。つまり、この位置からコピーします。追加された「\0 」の位置は最初の「\0」の位置であることに注意してください。
4.2strcatの使用法
#include <stdio.h>
#include <string.h>
int main()
{
char str1[50] = "row row row your boat,";
char* str2 = "gently down the stream";
strcat(str1, str2);
printf("%s\n", str1);
return 0;
}
4.3strcatのシミュレーション実装
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)//src 指向的字符串是不改变内容的,所以用 const 修饰
{
assert(dest && src);//确保两个指针有效
char* ret = dest;
while (*dest)
dest++;//先找到 dest 指向的数组的第一个 '\0' 的位置
while (*dest++ = *src++)//拷贝
;
return ret;
}
int main()
{
char str1[50] = "row row row your boat,";
char* str2 = "gently down the stream";
my_strcat(str1, str2);
printf("%s\n", str1);
return 0;
}
5.strncpy-長さ制限のある文字列コピー
5.1strncpyの宣言と使用
strncpyとstrcpyの違いは、strncpyにはもう1つのパラメーターがあることです。このパラメーターは符号なし整数です。つまり、コピーするコンテンツのバイト数をカスタマイズできます。これにより、使用が大幅に容易になり、C言語の柔軟性が向上します。
5.2strncpyの使用
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "row your boat";
char str2[] = "hello world";
strncpy(str1, str2, 3);//我们从 str2 中拷贝三个字节的内容到 str1 去
printf("%s\n", str1);
return 0;
}
3バイトのコンテンツのみをコピーすると、 strncpyは最後に「\ 0」を追加しない(つまり、必要 な数のコンテンツをコピーする)ため、出力が非常に奇妙であることがわかります。これは、結果として、コピーする前に、str1配列の内容を確認できます。
5.3strncpyのシミュレーション実装
#include <stdio.h>
#include <assert.h>
char* my_strncpy(char* dest, const char* src, unsigned int num)
{
assert(dest && src);//确保两个指针有效
char* ret = dest;
while (num--)//拷贝几个字节
{
*dest = *src;
dest++;
src++;
}
return ret;
}
int main()
{
char str1[20] = "row your boat";
char str2[] = "hello world";
my_strncpy(str1, str2, 3);
printf("%s\n", str1);
return 0;
}
6.strncmp-長さ制限のある文字列の比較
6.1strncmpの宣言と使用
strncmpとstrcmpの機能はまったく同じであり、原理もまったく同じです。つまり、strcmpをマスターすれば、strncmpをマスターできます。strncmpには、バイトを表す符号なし整数であるstrcmpよりも1つ多いパラメーターがあります。つまり、比較するバイト数です。この関数の宣言と各パラメーターの意味は、 cplusplusWebサイトで確認できます。
6.2strncmpの使用
#include <stdio.h>
#include <string.h>
int main()
{
char* str1 = "abbbcd";
char* str2 = "abbbdd";
int ret=strncmp(str1, str2,3);//我们只想比较字符串的前三个字节
if (ret > 0)
printf("str1 > str2\n");
else if (ret < 0)
printf("str1 < str2\n");
else
printf("str1 == str2\n");
return 0;
}
6.3strncmpのシミュレーション実装
#include <stdio.h>
#include <assert.h>
int my_strncmp(const char* str1, const char* str2, unsigned int num)//两个字符串的内容都不需要变,所以用 const 修饰
{
assert(str1 && str2);
while (num-- && *str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char* str1 = "abbbcd";
char* str2 = "abbbdd";
int ret = my_strncmp(str1, str2, 3);//我们只想比较字符串的前三个字节
if (ret > 0)
printf("str1 > str2\n");
else if (ret < 0)
printf("str1 < str2\n");
else
printf("str1 == str2\n");
return 0;
}
7.strncat-制限された長さの文字列を追加します
7.1strncatの宣言と使用
同様に、strcatをマスターすれば、strncatをマスターできます。strncatには、バイト数を意味するunsignedintegerの追加パラメーターがあります。つまり、別の文字列の末尾に追加する文字数をカスタマイズできます。strncatの宣言と各パラメーターの意味は、 cplusplusWebサイトで確認できます。
7.2strncatの使用
#include <stdio.h>
#include <string.h>
int main()
{
char str1[50] = "row row row your boat,";
char str2[] = "gently down the stream";
strncat(str1, str2, 6);//我们只想追加 6 个字节的字符到 str1 中
printf("%s\n", str1);
return 0;
}
ここで注意を払うと、問題が見つかります。追加する文字の最後の6バイトには「\0」が含まれていませんが、最終出力が出力されると、文字列の最後に「\0」が付けられているようです。次に、これはstrncatの特性に言及する必要があります。つまり、strncatは、追加される文字列の後に「\0」を追加します。
7.3strncatのシミュレーション実装
#include <stdio.h>
#include <assert.h>
char* my_strncat(char* dest, const char* src, unsigned int num)//str2 中的字符串不需要被修改,所以用 const 修饰
{
assert(dest && src);//确保两个指针是有效指针
char* ret = dest;//记录返回值
while (*dest)//先找到 dest 指向的 '\0' 的位置
dest++;
while (num-- && (*dest++ = *src++) )//拷贝限制的字节数
;
*dest = '\0';
return ret;
}
int main()
{
char str1[50] = "row row row your boat,";
char str2[] = "gently down the stream";
my_strncat(str1, str2, 8);
printf("%s\n", str1);
return 0;
}
まとめ
上記では、長さ制限のない文字列関数と長さ制限のある文字列関数について説明しました。では、制限付きと制限なしの違いは何ですか?まず第一に、文字列全体しか操作できないため、無制限の文字列関数の柔軟性は比較的低くなります。ただし、制限付き文字列関数の柔軟性は比較的高く、操作する文字数はカスタマイズできます。また、長さが制限された文字列関数は、長さが制限されていない文字列関数よりも安全です。制限付きは制限なしより安全であることに注意してください。
8.strstr-文字列検索
8.1strstrの宣言と使用
strstrは文字通り2つの文字列です。その意味は、文字列の1つで別の文字列を見つけることです。strstrの宣言と各パラメーターの意味は、 cplusplusWebサイトで確認できます。
strstrを翻訳することで、strstrのいくつかの原則を知ることができます。文字列2が文字列1で見つかった場合、文字列1の文字列2の最初のアドレスが返されます。文字列が見つからない場合は、nullポインタが返されます。
8.2strstrの使用
#include <stdio.h>
#include <string.h>
int main()
{
char* str1 = "row row row your boat,gently down the stream";
char* str2 = "row your boat";
char* ret = strstr(str1, str2);//在 str1 中查找 str2
printf("%s\n", ret);
return 0;
}
戻り値は、str1で最初に出現したstr2の最初のアドレスである ことがわかります。
8.3strstrの模擬実装
#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* str1, const char* str2)//不需要改变其内容,用 const 修饰
{
assert(str1 && str2);//避免是无效指针
const char* s1 = str1;
const char* s2 = str2;
const char* cp = str1;//这个指针变量是至关重要的
while (*cp)
{
s1 = cp;
s2 = str2;
//在 str1 中查找 str2 的核心循环
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')//查找完成
return (char*)cp;
cp++;
}
return NULL;
}
int main()
{
char* str1 = "row row row your boat,gently down the stream";
char* str2 = "row your boat";
char* ret = my_strstr(str1, str2);
printf("%s\n", ret);
return 0;
}
絵を描いて、その考えを詳しく説明し ましょう。
9.strtok-文字列のスライス
9.1strtokの宣言と有用性
この関数については、基本的な使用法を理解するだけで済みます。cplusplus Webサイトを使用して、strtokの宣言と各パラメーターの意味を観察します。
この英語の段落は長すぎます。コア部分について説明します。strtokに2つのパラメーターを提供します。1つは文字列で、もう1つはカットするトークンです。トークンが文字列に含まれている場合、トークンが返される前の位置は「\0」と文字列のアドレスに変更されます。パラメータを2回渡す場合は、nullポインタを渡すだけで済みます。
9.2strtokの使用
#include <stdio.h>
#include <string.h>
int main()
{
char* str1 = "row@row~row%your^boat,gently@down~the^stream";
char* str2 = "@~%^";
//将 str1 拷贝至 tmp 数组,这样不会丢失 str1 的原始数据
char tmp[50] = { 0 };
strcpy(tmp, str1);
char* ret = NULL;
for (ret = strtok(tmp, str2); ret != NULL; ret = strtok(NULL, str2))
{
printf("%s ", ret);
}
return 0;
}
10.strerror-エラーコードの解析
10.1ストラーの宣言と使用
私たちが普及する必要がある1つのポイントは、C言語では、プログラムエラーが発生すると、0、1、2、3、...などの整数である非表示のグローバル変数errnoが存在することです。さまざまなエラーメッセージを表します。strerrorの役割は、このエラーコードを変換することです。cplusplus Webサイトを通じて、 strerrorの宣言と各パラメーターの意味を 確認できます。
10.2strerrorの使用
#include <stdio.h>
#include <string.h>
int main()
{
FILE* p;
p = fopen("test.txt", "r");//在我们的工程目录下并没有 test.txt 这个文件
if (p == NULL)//那么打不开 p 就是一个空指针
{
printf("%s\n", strerror(errno));//这里就会解释为什么是空指针的原因
}
return 0;
}