【问题标题】:extracting data between two semicolons in C在C中提取两个分号之间的数据
【发布时间】:2016-01-19 17:11:15
【问题描述】:

我正在尝试编写实用程序类型的函数,但不会因为太复杂而无法从分号分隔的字符串中提取值。在此示例中,我尝试提取 X=bc,但在将值分配给 *cpp 时收到的是分段错误

我做错了什么?

int main()
{
    char x[500]="a;X=bc;def;ghi";
    char* cp=x,*cpp;

    while ((cp=strstr(cp,";")))
    {
        cp++;

        if ((*cp)=='X' && (*cp+1)=='=')
        {
            cp+=2;
            break;
        }
    }

    if ((cpp=strstr(cp,";")))
    {
        *cpp='\0';
    }

    printf("'%s' '%s'\n",x,cp);
    return 0;
}

【问题讨论】:

  • 因为你只想要 一个 char,所以使用 strchr(cp,';') 而不是 strstr(cp,";")。它要快得多。

标签: c pointers substring


【解决方案1】:

这一行是错误的:

    if ((*cp)=='X' && (*cp+1)=='=')

应该是:

    if ((*cp)=='X' && *(cp+1)=='=')

或者更好:

    if (cp[0]=='X' && cp[1]=='=')

请注意,编写的代码非常脆弱 - 有很多方法可能会失败 - 尝试养成防御性编程的习惯 - 始终假设任何可能失败的事情都会失败并且相应地编写你的代码,这样当事情没有按预期工作时,它至少会优雅地失败

另一个提示,当我在这里时:学习一些基本的调试技术 - 我不能立即看出代码有什么问题,所以我在代码中添加了一些 printf,以便我可以获得关于发生了什么的更多信息on - 很快就发现cp 在第一个循环之后是NULL,从那里更容易看到问题。或者,我可以在调试器中单步执行代码 - 任何一种技术都会在一两分钟内将您直接带到这个错误。

【讨论】:

    【解决方案2】:

    因为你得到了答案,所以我只能告诉你另一种方法:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    void checkString(char *string1, char *string2){
        char *string3;
        char *s1, *s2, *s3;
    
        size_t lenstring1 = strlen(string1);
        size_t lenstring2 = strlen(string2);
    
        if (lenstring2 < 1){
            printf("There is no substring found");
            exit(1);
        }
    
        size_t i=0,j=0;
        int found=0;
    
        s1 = string1;
        s2 = string2;
    
    
        for(i = 0; i < lenstring1; i++){
            if(*s1 == *s2){
                s3 = s1;
                for(j = 0;j < lenstring2;j++){
                    if(*s3 == *s2){
                      s3++;s2++;
                    }else{
                        break;
                    }
                }
    
                s2 = string2;
                if(j == strlen(string2)){
                    found = 1;
                    string3=string2;
                  }
              }
            s1++;
        }
    
        if(found != 0){
            printf("%s\n",string3);
    
        }else{
            printf("No match Found");
        }
    }
    
    int main(void){
        char string1[] = "a;X=bc;def;ghi";
        char string2[] = "X=bc";
    
        checkString(string1, string2);
        return 0;
    }
    

    输出:

    X=bc

    【讨论】:

      【解决方案3】:

      您可能想考虑使用标准库函数strtok,这听起来非常适合这项任务。它接受一个字符串并根据作为参数给出的一个或多个分隔符将其分隔为标记。

      此代码应该可以帮助您入门:

      #include <stdio.h>
      #include <string.h>
      
      int main(void)
      {
              char *token;
              char *parsed;
              char input[] ="a;X=bc;def;ghi";
              parsed = input;
              while(token = strtok(parsed, ";"))
              {
                      parsed = NULL;
                      puts(token);
              }
              return 0;
      }
      

      第一次调用strtok 使用要解析的实际字符串作为第一个参数,而随后的调用使用NULL。如果没有更多令牌(或根本没有令牌),strtok 返回NULL

      不过,在使用此功能时有几点需要牢记:

      1. 原型是char *strtok(char *str, const char *delim);。这意味着str 必须是可写的。因此,您不能假设它不会被修改。
      2. 如果您打算在程序中使用线程,从多个线程调用strtok 会导致错误,因为它使用全局状态来存储最后返回的令牌。 POSIX 定义了该函数的线程安全形式,其原型为char *strtok_r(char *str, const char *delim, char **saveptr);,最后一个参数用于在调用之间存储数据。有了这样的接口,就不需要使用全局状态,saveptr 可以存储为局部变量。

      此功能的documentation 应该可以解答您的所有疑问。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多