実用的な小さなアプリケーションを使用して、C言語での文字列操作とその使用法に関連する4つの関数を記録します。
-
strtok_r
-
sstrstr
-
sstrtok
- サトイ
質問は
最初の投稿に変数定義を導きます:
char str[] = "led,100,0,80,15";//一个字符串,第一个逗号前的字符串设定为某个命令,后面的是参数
特定のアプリケーションシナリオが、上記のstr [] = "led、100,0,80,15"のような文字列の文字列をコンマで区切って受信するとします。ただし、文字列の最初の文字列はAの種類の命令を表します。 LEDをオンにするなど、後ろの数字は、さまざまなLEDの輝度値などのパラメーターを示します。
では、コンピュータはどのようにして各文字列を区別し、対応する数値パラメータを取得する必要がありますか?
以下では、この問題を解決するためのC言語のいくつかの関数を紹介します。
関数の紹介と例
strtok_rは、
最初に文字列を命令形式とパラメーター形式に分割する必要があり、strtok_r関数が必要です。
関数定義:
char *strtok_r(char * __restrict__ _Str, const char * __restrict__ _Delim, char ** __restrict__ __last);
-
パラメータ:元の文字列、区切り文字、分割後の残りの文字列
- 戻り値:セグメント化された文字列。一致する文字列がない場合は、nullポインタが返されます。
注:この関数は破壊的な操作です。元の文字列strは分割処理後に変更され、分割文字列になります。!!
上記の質問のstrを元の文字列として渡し、区切り文字はコンマで、分割は上記で定義されたparas変数に格納され、戻り値は上記で定義されたcmd変数に格納されます。
char *cmd;//表示命令
char *paras;//表示命令后的参数
cmd = strtok_r(str, ",", ¶s);
printf("cmd:%s\r\n", cmd);//获得字符串的第一串字符
printf("paras:%s\r\n", paras);//获取后续字符串
テスト結果の表示:
cmd:led
paras:100,0,80,15
必要なコマンドとパラメーターの2つの文字列が正常に分割されていることがわかります。
strstr
がパラメータコマンド文字列を取得するために、コマンドが有効かどうか、つまり、コンピュータが以前に文字列を保存したことがあるかどうかを判断する必要がある場合もあります。このテストは、文字列を配列内の対応する文字列と照合することでシミュレートできます。 。strstr関数を使用する必要があり、その関数は次のように定義されます。
char *strstr(const char *_Str,const char *_SubStr);
-
パラメータ:元の文字列、検索する部分文字列
- 戻り値:ソース文字列で最初に出現する部分文字列のアドレス。それ以外の場合はNULLが返されます。
最初に文字列配列funname [5]をクエリ用にカスタマイズしてから、マッチングと比較を順番に実行できます。
char *funname[5] = {"music", "play", "A_led1", "led2", "led"};//自定义的函数名称列表
char *ret;
int i;
for (i = 0; i < 5;i++)
{
ret = strstr(funname[i], cmd);
if(ret!=NULL)
{
printf("find cmd in funname[%d]\r\n", i);
printf("ret:%s\r\n", ret);
break;
}
}
if(i==5)
{
printf("can't find cmd in funname[]");
}
試験結果:
find cmd in funname[2]
ret:led1
ここでのcmd文字列は、上記でセグメント化されたLEDです。今回は、A_led1に含まれるLED文字と一致します。テストコードは、一致するものが見つかる限りforループから抜け出すように設定されているため、最後の文字列と正確に一致するものはありません。同じ文字列。、実際のプログラミングに注意してください。
実際の使用では、strstrを使用して文字列を照合する場合、異なる文字列間の違いを定義して、正しく区別できるようにすることができます。テストで定義されたfunnameは、strstrの使用法を示すためだけのものです。
strtokは
コマンド文字列の有効性を判断しました。次に、次のパラメータを分割する必要があります。実際には、strtok_rメソッドを引き続き使用できます。ただし、カットを保存するために使用される別の同様の関数strtokを使用できます。分割された文字列のパラメータの場合、関数は次のように定義されます。
char *strtok(char * __restrict__ _Str,const char * __restrict__ _Delim);
-
パラメータ:元の文字列、区切り文字
- 戻り値:セグメント化された文字列。一致する文字列がない場合は、nullポインタが返されます。
注:この関数を初めて使用するときは、元の文字列を渡す必要があり、その後の継続的な使用のために、NULLを渡す必要があります。実際、最初の操作の後、渡される元の文字列はに変更されています。最初の分割文字列。
char* para[4];
para[0] = strtok(paras, ",");
int j= 1;
while(paras != NULL)
{
para[j++] = strtok(NULL, ",");
if(j==4)
break;
}
printf("para[0]:%s\r\n", para[0]);
printf("para[1]:%s\r\n", para[1]);
printf("para[2]:%s\r\n", para[2]);
printf("para[3]:%s\r\n", para[3]);
演算結果:
para[0]:100
para[1]:0
para[2]:80
para[3]:15
以下のパラメータも正常に分離されていることがわかります。
atoiの
上で区切られたパラメーター番号は文字列型であり、実際の使用では対応する整数形式が必要になる場合があります。atoi関数を使用して以下を変換できます。
int atoi(const char *_Str);
-
パラメータ:数字の文字列
- 戻り値:対応する整数値。変換できない場合は0を返します。
int p1、p2、p3、p4;
p1 = atoi(para [0]);
p2 = atoi(para [1]);
p3 = atoi(para [2]);
p4 = atoi(para [3]);
printf( "%d、%d、%d、%d \ r \ n"、p1、p2、p3、p4);
测试结果:
100,0,80,15
%d形式的打印也正确,说明转换成功。
另外,可以测试一下atoi的其它使用情况:
//数値に変換できない文字列をテストします
printf( "atoi(hello):%d \ r \ n"、atoi( "hello"));
//浮動小数点文字列をテストします
printf( "atoi(3.14 ):%d \ r \ n "、atoi(" 3.14 "));
输出:
atoi(hello):0
atoi(3.14):3
可以看出,不能转换的会返回0,浮点型字符串只返回整数部分。
至此,文章开头提出的问题已经解决,下面贴出完整测试代码。
**完整测试程序**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char funname [5] = {"music"、 "play"、 "A_led1"、 "led2"、 "led"}; //カスタム関数名のリストcharstr
[] = "led、100、 0,80,15" ; // Aの文字列は、最初のコンマは、特定のコマンドに設定し、次のパラメータでされる前に、文字列
のchar cmdと; //示し、コマンド
のchar *パラスは; //コマンドを示し、コマンドの後Parameterprintf
( "str =%s \ r \ n"、str);
//strtok_r==================================
/*
char *strtok_r(char * __restrict__ _Str, const char * __restrict__ _Delim, char ** __restrict__ __last);
参数:原始字符串,分隔符,切分后剩余的字符串
返回值:切分掉的字符串
*/
printf("\r\ntest [strtok_r] --------------------->\r\n");
cmd = strtok_r(str, ",", ¶s);
printf("cmd:%s\r\n", cmd);//获得字符串的第一串字符
printf("paras:%s\r\n", paras);//获取后续字符串
printf("str:%s\r\n",str);//------原str已经被破坏了!!!
//strstr=====================================
/*
char *strstr(const char *_Str,const char *_SubStr);
参数:原始字符串,要查找的子字符串
返回值:子字符串在源字符串中首次出现的地址,无则返回NULL
*/
printf("\r\ntest [strstr] --------------------->\r\n");
char *ret;
int i;
for (i = 0; i < 5;i++)
{
ret = strstr(funname [i]、cmd);
if(ret!= NULL)
{
printf( "funname [%d] \ r \ nでcmdを検索"、i);
printf( "ret:%s \ r \ n"、ret);
ブレーク;
}
}
if(i == 5)
{
printf( "funname []"でcmdが見つかりません);
}
//strtok====================================
/*
char *strtok(char * __restrict__ _Str,const char * __restrict__ _Delim)
参数:原始字符串,分隔符
返回值:切分掉的字符串
*/
printf("\r\ntest [strtok] --------------------->\r\n");
char* para[4];
para[0] = strtok(paras, ",");
int j= 1;
while(paras != NULL)
{
para [j ++] = strtok(NULL、 "、");
if(j == 4)
break;
}
printf( "para [0]:%s \ r \ n"、para [0]);
printf( "para [1]:%s \ r \ n"、para [1]);
printf( "para [2]:%s \ r \ n"、para [2]);
printf( "para [3]:%s \ r \ n"、para [3]);
//字符串转数字================================
/*
int atoi(const char *_Str);
参数:字符串
返回值:字符串对应的数字值
*/
printf("\r\ntest [atoi] --------------------->\r\n");
int p1,p2,p3,p4;
p1= atoi(para[0]);
p2= atoi(para[1]);
p3= atoi(para[2]);
p4= atoi(para[3]);
printf("%d,%d,%d,%d\r\n",p1,p2,p3,p4);
//测试不能转化为数字的字符串
printf("atoi(hello): %d\r\n", atoi("hello"));
//测试浮点型字符串
printf("atoi(3.14): %d\r\n", atoi("3.14"));
return 0;
}
运行结果:
str = led、100,0,80,15
テスト[strtok_r] --------------------->
cmd:led
paras:100,0,80,15
str:led
test [strstr] --------------------->
funname [2]
ret:led1でcmdを見つけます
テスト[strtok] --------------------->
para [0]:100
para [1]:0
para [2]:80
para [3]:15
test [atoi] --------------------->
100,0,80,15
atoi(hello):0
atoi(3.14):3