Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的字符串搜索与格式_C_String_Search_Buffer - Fatal编程技术网

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 <

简单介绍一下:在C中,我有一个充满数据的缓冲区,如下所示:

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后面加上连字符吗?似乎不是一个一致的符号…谢谢你所有的回复,它在最后运行良好,非常感谢。谢谢你所有的回复,它在最后运行良好,非常感谢。