sscanf()
- 从一个字符串中读进与指定格式相符的数据。
函数原型:
int sscanf( const char *, const char *, ...);
int sscanf(const char *buffer,const char *format,[argument ]...);
buffer存储的数据
format格式控制字符串
argument 选择性设定字符串
sscanf会从buffer里读进数据,依照format的格式将数据写入到argument里。
示例:
sscanf("123-456*abc\ndedf","%d-%d*%s\n%s",int1,int2,buf3,buf4);
Strtok
分解字符串为一组字符串。s为要分解的字符,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。
原型
编辑
char *strtok(char s[], const char *delim);
功能
编辑
分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。
例如:strtok("abc,def,ghi",","),最后可以分割成为abc def ghi.尤其在点分十进制的IP中提取应用较多。
说明
编辑
strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。
返回值
编辑
从s开头开始的一个个被分割的串。当查找不到delim中的字符时,返回NULL。
所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
示例
官方示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[]="ab,cd,ef";
char *ptr;
printf("before strtok: str=%s\n",str);
printf("begin:\n");
ptr = strtok(str, ",");
while(ptr != NULL){
printf("str=%s\n",str);
printf("ptr=%s\n",ptr);
ptr = strtok(NULL, ",");
}
system("pause");
return 0;
}
将
字符串按照\n进行分割
// bufferParition.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
int _tmain()
{
char buffer[] = "turn/ \nDIAMONDS 7 \n/turn \nriver/ \nSPADES A \n/river \nhold/ \nSPADES A \n/hold \n" ;
char *ptr;
printf("before strtok: str=%s\n",buffer);
printf("begin:\n");
const char *strDelimit = "\n";
ptr = strtok(buffer, strDelimit);
int i = 0;
char bag[10][100];
while(ptr != NULL){
printf("ptr = %s\n",ptr);
i++;
ptr = strtok(NULL, strDelimit);
}
system("pause");
return 0;
}
另外一个实例,华为软件精英挑战赛2015,中对发送来的消息进行解析的示例。要将字符串进按照turn/ 和/turn这种类型划分。
// strstrTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <string.h>
int main(int argc,char **argv)
{
//char a[]="turn/ \nDIAMONDS 7 \n/turn \nriver/ \nSPADES A \n/river \nhold/ \nSPADES A \n/hold \n" ;
char a[]="turn/ \nHEARTS 2 \n/turn \nriver/ \nHEARTS 4 \n/river \nshowdown/ \ncommon/ \nDIAMONDS A \nSPADES 10 \nDIAMONDS 3 \nHEARTS 2 \nHEARTS 4 \n/common \n3: 3333 DIAMONDS Q SPADES A ONE_PAIR \n1: 4444 DIAMONDS 5 SPADES J STRAIGHT \n1: 7777 CLUBS 5 HEARTS 7 STRAIGHT \n7: 8888 HEARTS 6 HEARTS 9 HIGH_CARD \n2: 6666 CLUBS 4 CLUBS 10 TWO_PAIR \n6: 5555 CLUBS 8 CLUBS Q HIGH_CARD \n4: 1111 DIAMONDS 10 SPADES 8 ONE_PAIR \n5: 2222 SPADES K CLUBS J HIGH_CARD \n/showdown \npot-win/ \n4444: 8000 \n7777: 8000 \n/pot-win \nseat/ \nbutton: 3333 2000 6000 \nsmall blind: 4444 8000 8000 \nbig blind: 7777 8000 8000 \n8888 2000 6000 \n6666 2000 6000 \n5555 2000 6000 \n1111 2000 6000 \n2222 2000 6000 \n/seat \nblind/ \n4444: 50 \n7777: 100 \n/blind ";
printf("原始消息为:%s",a);
char *buffer = a; //需要解析的包
char *needle = "\n/"; //分割标识符,但并不是真正的分割处。比如"turn/ \nHEARTS 2 \n/turn \n"
//分割处就在\n/后面出现 空格+\n 的后面
char* buf = strstr( buffer, needle); //第一次划分
char message[10][1024]={"\0"}; //存储解析出的信息
int msgLength = 0; //解析出的信息条数
int connectFlag = 0; //仅用于解决showdown消息会不完整的问题,
//0表示没有消息合并,1表示有消息需要被合并,2表示已经被合并
while( buf != NULL )
{
int i = 0;
while (buf[i]!=' ')i++; //找到\n/标识符出现后第一次出现空格的地方
int cut = i+2; //他的后两位就是分割处
buf[cut-1]='\0';
//printf( "Message is :\n%s\n ", buffer);
strcpy(message[msgLength],buffer); //将解析出的消息存储到message里,并且加上\n(之前解析造成\n丢失)
strcat(message[msgLength],"\n");
//上一段消息不完整,需要与上一段消息合并
if (connectFlag == 1)
{
strcat(message[msgLength-1],message[msgLength]);
msgLength--;
connectFlag = 2; //表示已经合并
}
//如果消息头为showdown,并且connectFlag的状态不是2,就将connectFlag状态置为1
//表示这段消息以showdown开头,且不完整,需要与下一段消息合并
if (strncmp(message[msgLength],"showdown/ \n",3)==0 && connectFlag != 2 )
{
connectFlag = 1;
}
//memcpy(message[msgLength],buffer,sizeof(buffer));
msgLength++;
buffer = buf + cut;
buf = strstr( buffer, needle);
}
printf("一共%d段msg\n",msgLength);
for (int j = 0; j<msgLength ;j++)
{
printf("Message %d:\n%s",j,message[j]);
}
return 0;
}
结果如下
原始消息为:turn/
HEARTS 2
/turn
river/
HEARTS 4
/river
showdown/
common/
DIAMONDS A
SPADES 10
DIAMONDS 3
HEARTS 2
HEARTS 4
/common
3: 3333 DIAMONDS Q SPADES A ONE_PAIR
1: 4444 DIAMONDS 5 SPADES J STRAIGHT
1: 7777 CLUBS 5 HEARTS 7 STRAIGHT
7: 8888 HEARTS 6 HEARTS 9 HIGH_CARD
2: 6666 CLUBS 4 CLUBS 10 TWO_PAIR
6: 5555 CLUBS 8 CLUBS Q HIGH_CARD
4: 1111 DIAMONDS 10 SPADES 8 ONE_PAIR
5: 2222 SPADES K CLUBS J HIGH_CARD
/showdown
pot-win/
4444: 8000
7777: 8000
/pot-win
seat/
button: 3333 2000 6000
small blind: 4444 8000 8000
big blind: 7777 8000 8000
8888 2000 6000
6666 2000 6000
5555 2000 6000
1111 2000 6000
2222 2000 6000
/seat
blind/
4444: 50
7777: 100
/blind 一共6段msg
Message 0:
turn/
HEARTS 2
/turn
Message 1:
river/
HEARTS 4
/river
Message 2:
showdown/
common/
DIAMONDS A
SPADES 10
DIAMONDS 3
HEARTS 2
HEARTS 4
/common
3: 3333 DIAMONDS Q SPADES A ONE_PAIR
1: 4444 DIAMONDS 5 SPADES J STRAIGHT
1: 7777 CLUBS 5 HEARTS 7 STRAIGHT
7: 8888 HEARTS 6 HEARTS 9 HIGH_CARD
2: 6666 CLUBS 4 CLUBS 10 TWO_PAIR
6: 5555 CLUBS 8 CLUBS Q HIGH_CARD
4: 1111 DIAMONDS 10 SPADES 8 ONE_PAIR
5: 2222 SPADES K CLUBS J HIGH_CARD
/showdown
Message 3:
pot-win/
4444: 8000
7777: 8000
/pot-win
Message 4:
seat/
button: 3333 2000 6000
small blind: 4444 8000 8000
big blind: 7777 8000 8000
8888 2000 6000
6666 2000 6000
5555 2000 6000
1111 2000 6000
2222 2000 6000
/seat
Message 5:
blind/
4444: 50
7777: 100
/blind
strstr
strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
str1: 被查找目标 string expression to search.
str2: 要查找对象 The string expression to find.
返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。
例子:
1
2
3
|
char
str[]=
"1234xyz"
;
char
*str1=
strstr
(str,
"34"
);
cout << str1 << endl;
|
显示的是: 34xyz
#include <string.h>
#include <stdio.h>
int main(int argc,char **argv){
char a[]="aaa||a||bbb||c||ee||";
char *needle="||";
char *haystack=a;//不能直接char *haystack="aaa||a||bbb||c||ee||"; 会报内存不能写错误
char* buf = strstr( haystack, needle);
while( buf != NULL ){
buf[0]='\0';//在出现分隔符的位置设置结束符\0
printf( "%s\n", haystack);
haystack = buf + strlen(needle);
buf = strstr( haystack, needle);
}
return 0;
}
OUT 值:
aaa
a
bbb
c
ee