C语言中的字符串搜索与格式
简单介绍一下:在C中,我有一个充满数据的缓冲区,如下所示:C语言中的字符串搜索与格式,c,string,search,buffer,C,String,Search,Buffer,简单介绍一下:在C中,我有一个充满数据的缓冲区,如下所示: char buffer[255]="CODE=12345-MODE-12453-CODE1-12355" 我的问题是如何搜索这个。例如,对于CODE=12345,请记住数字会发生变化,因此我希望在CODE=part之后使用通配符或预设的空格量进行如下搜索:CODE=**** 此方法不会编译最后一个要尝试的方法 #include <stdio.h> #include <string.h> #include <
char buffer[255]="CODE=12345-MODE-12453-CODE1-12355"
我的问题是如何搜索这个。例如,对于CODE=12345,请记住数字会发生变化,因此我希望在CODE=part之后使用通配符或预设的空格量进行如下搜索:CODE=****
此方法不会编译最后一个要尝试的方法
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
char buf[255]="CODE=12345-MODE-12453-CODE1-12355";
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input)
{
char *p = (char*) input, *buf, *pbuf;
if((buf = malloc(256)) == NULL)
return NULL;
pbuf = buf;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim white-space after 'code'
if(*p != '=')
return NULL;
STRIP(p); // remove '='
TRIMSPACES(p); //trim white-spaces after '='
/* copy the value until found a '-'
note: you must be control the size of it,
for avoid overflow. we allocated size, that's 256
or do subsequent calls to realloc()
*/
while(*p != '\0' && *p != '-')
*pbuf ++ = *p++;
// break;
}
p ++;
}
//put 0-terminator.
*pbuf ++ = '\0';
return buf;
}
//
}
您可以使用sscanf功能:
int number;
sscanf(buffer, "CODE = %i", &number);
要使其正常工作,缓冲区必须以null结尾。您可以使用sscanf函数:
int number;
sscanf(buffer, "CODE = %i", &number);
要使其正常工作,缓冲区必须以null结尾。假设CODE=part总是出现在字符串的开头,这很容易:
sscanf(buffer, "CODE = %d", &number);
…但您希望缓冲区为字符[255],而不是无符号长
编辑:如果CODE=part不一定在字符串的开头,则可以使用strstr在缓冲区中查找代码,从该点开始执行sscanf,然后紧跟其后查看:
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
编辑2:
例如,您可以这样使用:
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
// This is full of other junk as well
char buffer[255]="CODE=12345 MODE-12453 CODE=12355" ;
int i;
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
for (i=0; i<current; i++)
printf("%d\n", codes[i]);
return 0;
}
…正确读取两个CODE=xxx部分,但跳过MODE=yyy部分。假设CODE=part始终位于字符串的开头,这很容易:
sscanf(buffer, "CODE = %d", &number);
…但您希望缓冲区为字符[255],而不是无符号长
编辑:如果CODE=part不一定在字符串的开头,则可以使用strstr在缓冲区中查找代码,从该点开始执行sscanf,然后紧跟其后查看:
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
编辑2:
例如,您可以这样使用:
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
// This is full of other junk as well
char buffer[255]="CODE=12345 MODE-12453 CODE=12355" ;
int i;
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
for (i=0; i<current; i++)
printf("%d\n", codes[i]);
return 0;
}
…正确读取两个CODE=xxx部分,但跳过MODE=yyy部分。另一种方法代替sscanf: 或者更稳健的方式。。更复杂一点:
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input, size_t limit)
{
char *p = (char*) input, *buf, *pbuf;
size_t i = 0;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim all white-spaces after 'code'
/* check we have a '=' after CODE (without spaces).
if there is not, returns NULL
*/
if(*p != '=')
return NULL;
/* ok. We have.. now we don't need of it
just remove it from we output string.
*/
STRIP(p);
/* remove again all white-spaces after '=' */
TRIMSPACES(p);
/* the rest of string is not valid,
because are white-spaces values.
*/
if(*p == '\0')
return NULL;
/* allocate space for store the value
between code= and -.
this limit is set into second parameter.
*/
if((buf = malloc(limit)) == NULL)
return NULL;
/* copy the value until found a '-'
note: you must be control the size of it,
for don't overflow. we allocated 256 bytes.
if the string is greater it, do implementation with
subjecents call to realloc()
*/
pbuf = buf;
while(*p != '\0' && *p != '-' && i < limit) {
*pbuf ++ = *p++;
i ++;
}
*pbuf ++ = '\0';
return buf;
}
p ++;
}
return NULL;
}
输出:
代码=12345
看看这个
如果您不想区分大小写,可以使用that's POSIX函数。另一种方法来代替sscanf:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getcode(const char *str, const char *pattern){
//pattern: char is match, space is skip, * is collect
static const char *p=NULL;
char *retbuf, *pat;
int i, match, skip, patlen;
if(str != NULL) p=str;
if(p==NULL || *p=='\0') return NULL;
if(NULL==(retbuf=(char*)malloc((strlen(p)+1)*sizeof(char))))
return NULL;
pat = (char*)pattern;
patlen = strlen(pat);
i = match = skip = 0;
while(*p){
if(isspace(*p)){
++p;
++skip;
continue;
}
if(*pat){
if(*p == *pat){
++match;
++p;
++pat;
} else if(*pat == '*'){
++match;
retbuf[i++]=*p++;
++pat;
} else {
if(match){//reset
pat=(char*)pattern;
p -= match + skip -1;
i = match = skip = 0;
} else //next
++p;
}
} else {
break;
}
}
if(i){//has match
retbuf[i++]='\0';
retbuf=realloc(retbuf, i);
return retbuf;
} else {
free(retbuf);
return NULL;
}
}
int main (){
char *code;
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(" CODE = 12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode("CODE-12345-MODE-12453-CODE1-12355", "CODE=*****");
if(code==NULL)printf("not match\n");//not match
code=getcode("CODE=12345-MODE-12453-CODE=12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE=*****");
printf("\"%s\"\n",code);//"12355"
free(code);
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE1-*****");
printf("\"%s\"\n",code);//"12355"
free(code);
return 0;
}
或者更稳健的方式。。更复杂一点:
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input, size_t limit)
{
char *p = (char*) input, *buf, *pbuf;
size_t i = 0;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim all white-spaces after 'code'
/* check we have a '=' after CODE (without spaces).
if there is not, returns NULL
*/
if(*p != '=')
return NULL;
/* ok. We have.. now we don't need of it
just remove it from we output string.
*/
STRIP(p);
/* remove again all white-spaces after '=' */
TRIMSPACES(p);
/* the rest of string is not valid,
because are white-spaces values.
*/
if(*p == '\0')
return NULL;
/* allocate space for store the value
between code= and -.
this limit is set into second parameter.
*/
if((buf = malloc(limit)) == NULL)
return NULL;
/* copy the value until found a '-'
note: you must be control the size of it,
for don't overflow. we allocated 256 bytes.
if the string is greater it, do implementation with
subjecents call to realloc()
*/
pbuf = buf;
while(*p != '\0' && *p != '-' && i < limit) {
*pbuf ++ = *p++;
i ++;
}
*pbuf ++ = '\0';
return buf;
}
p ++;
}
return NULL;
}
输出:
代码=12345
看看这个
如果您不区分情况,可以使用POSIX函数。
谢谢。我更改了缓冲区,但是代码出现在字符串的中间,整个输出缓冲区都来自USB设备,所以字符串都在缓冲器上。所以我只能返回第一个字符串。对不起,我想我在上面编辑了你的文章,但是现在它不会返回任何数字。另外,我注意到一些代码不仅仅是code=12345,还有一些代码有尾部,比如code=12345-001。这也是一个问题。文本代码在循环中不能是常量。。。您可以合理地解决这个问题,使用一个索引为current的const char*数组,该数组有一个硬编码的标识符列表来驱动迭代,也可以防止缓冲区溢出,但每次都需要从缓冲区进行搜索,检查strstr是否找到了第一个字符或前面有连字符的字符。@user1539199:我觉得你需要更好地定义你真正想要的。它是任意字符串,后面跟着=,跟着一个或多个数字,用虚线分隔?谢谢我改变了缓冲区,但是代码出现在字符串的中间,整个输出缓冲区都来自USB设备,所以字符串都在缓冲器上。所以我只能返回第一个字符串。对不起,我想我在上面编辑了你的文章,但是现在它不会返回任何数字。另外,我注意到一些代码不仅仅是code=12345,还有一些代码有尾部,比如code=12345-001。这也是一个问题。文本代码在循环中不能是常量。。。您可以合理地解决这个问题,使用一个索引为current的const char*数组,该数组有一个硬编码的标识符列表来驱动迭代,也可以防止缓冲区溢出,但每次都需要从缓冲区进行搜索,检查strstr是否找到了第一个字符或前面有连字符的字符。@user1539199:我觉得你需要更好地定义你真正想要的。这是一个任意字符串,后跟=,后跟一个或多个数字,用破折号分隔吗?这不会搜索-它只在缓冲区最开始出现CODE=时匹配。如果不能保证,可以使用strstr查找以CODE开头的子字符串,并将sscanf应用于该缓冲区位置。是,但并非如此简单-您还需要检查strstr匹配之前的字符是第一个还是连字符。此外,如果sscanf…==1或您不知道sscanf是否匹配…这不会搜索-它仅在缓冲区最开始出现CODE=时匹配。如果不能保证,可以使用strstr定位以CODE开头的子字符串,并将sscanf应用于该缓冲区位置。是,但并非如此简单-您还需要检查strstr匹配之前的字符是第一个还是连字符。此外,如果sscanf…==1或者你不知道sscanf是否匹配……感谢我尝试的两种方法,顶部返回12345模式,所以t的方向错误#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getcode(const char *str, const char *pattern){
//pattern: char is match, space is skip, * is collect
static const char *p=NULL;
char *retbuf, *pat;
int i, match, skip, patlen;
if(str != NULL) p=str;
if(p==NULL || *p=='\0') return NULL;
if(NULL==(retbuf=(char*)malloc((strlen(p)+1)*sizeof(char))))
return NULL;
pat = (char*)pattern;
patlen = strlen(pat);
i = match = skip = 0;
while(*p){
if(isspace(*p)){
++p;
++skip;
continue;
}
if(*pat){
if(*p == *pat){
++match;
++p;
++pat;
} else if(*pat == '*'){
++match;
retbuf[i++]=*p++;
++pat;
} else {
if(match){//reset
pat=(char*)pattern;
p -= match + skip -1;
i = match = skip = 0;
} else //next
++p;
}
} else {
break;
}
}
if(i){//has match
retbuf[i++]='\0';
retbuf=realloc(retbuf, i);
return retbuf;
} else {
free(retbuf);
return NULL;
}
}
int main (){
char *code;
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(" CODE = 12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode("CODE-12345-MODE-12453-CODE1-12355", "CODE=*****");
if(code==NULL)printf("not match\n");//not match
code=getcode("CODE=12345-MODE-12453-CODE=12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE=*****");
printf("\"%s\"\n",code);//"12355"
free(code);
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE1-*****");
printf("\"%s\"\n",code);//"12355"
free(code);
return 0;
}
如果我把它改为mode,它将返回null。第二个不会编译抛出了3个错误,我似乎可以解决:-@用户1539199:您尝试了哪些输入?你收到了什么警告?但是请查看getcode的更新。我使用gcc-3-Wall-mno cygwin foo.ctthe-mno cygwin标志是一个cygwin spefi,我得到了预期的输出,即12345位数字。感谢代码板现在在ifbuf=malloclimit==NULL行上抛出了一个错误,无法将void转换为char**VS2010Can发布您正在使用的错误消息和编译器吗?microsoftvisual studio 2010看起来像是内存alloc bit void to char错误。感谢我尝试的两种方法,top返回12345模式,但方法错误,然后说我将其更改为模式,返回null。第二个不会编译抛出了3个错误,我似乎可以解决:-@用户1539199:您尝试了哪些输入?你收到了什么警告?但是请查看getcode的更新。我使用gcc-3-Wall-mno cygwin foo.ctthe-mno cygwin标志是一个cygwin spefi,我得到了预期的输出,即12345位数字。感谢代码板现在在ifbuf=malloclimit==NULL行上抛出了一个错误,无法将void转换为char**VS2010Can发布您正在使用的错误消息和编译器吗?microsoftvisual studio 2010看起来像是内存分配位void to char错误。您真的想在代码后使用=,但在模式和代码1后使用连字符吗?似乎符号不一致……你真的想在代码后面加一个=,但在MODE和CODE1后面加上连字符吗?似乎不是一个一致的符号…谢谢你所有的回复,它在最后运行良好,非常感谢。谢谢你所有的回复,它在最后运行良好,非常感谢。