用少数分隔符之一拆分字符串?

时间:2016-07-30 14:32:26

标签: c

我有这个

A > B,或A < BA==B

使用strtok我将破坏数据,我的目标是获得某种我可以检查的结构:

  1. 我有什么样的分隔符
  2. 可以访问它的两面(A和B)。
  3. 这样:

    if ( > )
    do something with A and B
    else if (==)
    do something with A and B 
    

    我知道这听起来很简单,但总是很麻烦。

    编辑:

    我所做的就是这个任务似乎太长了:

    for (int k=1;k<strlen(p);k++)
    {
    
        char left[4]="" ;
        char right[12]="" ;
    
    
    
        switch(p[k])
        {
    
    
            case '>' :
            {
                long num =strstr(p,">") - p ;
                strncpy(left,p,num);
                strncpy(right,p+num+1,strlen(p)-num-1);
    
    
                break;
            }
    
    
    
            case '<' :
            {
                long num =strstr(p,"<") - p ;
                strncpy(left,p,num);
                strncpy(right,p+num+1,strlen(p)-num-1);
    
    
                break;
            }
    
    
            case '=' :
    
            {
                long num =strstr(p,"=") - p ;
                strncpy(left,p,num);
                strncpy(right,p+num+1,strlen(p)-num-1);
    
    
                break;
            }
    
            case '!' :
            {
                long num =strstr(p,"!") - p ;
                strncpy(left,p,num);
                strncpy(right,p+num+1,strlen(p)-num-1);
    
    
                break;
            }
    
            default :
            {}
        }
    
    
    }
    

2 个答案:

答案 0 :(得分:3)

对于只想解析由两个操作数和一个运算符组成的简单字符串的简单情况,没有“表达式”这可能有效

#include <stdio.h>
#include <string.h>

int
main(void)
{
    const char *string = "A > B";
    char lho[100];
    char op[3];
    char rho[100];
    if (sscanf(string, "%99[^=><]%2[=><]%99[^=><]", lho, op, rho) == 3) {
        fprintf(stdout, "left hand operand: %s\n", lho);
        fprintf(stdout, "operator: %s\n", op);
        fprintf(stdout, "right hand operand: %s\n", rho);
    }
    return 0;
}

这绝不是最好的方法,只是表明你可以使用它。此外,我没有想太多,我编写代码向您展示可能的解决方案。我其实不喜欢它,我不会用它

答案 1 :(得分:1)

这是一个通用程序:

  1. 对于给定的集合delimiters,使用strstr检查它们是否出现在输入字符串中。作为奖励,我的下面的代码允许双倍&#39; <<>等条目;它检查所有并尽可能使用最长的。
  2. 确定要使用的最佳分隔符后,启动时会有指针。然后你可以
  3. ..将左侧的所有内容复制到left变量;
  4. ..将分隔符本身复制到delim变量中(为了保持一致性);和
  5. ..将分隔符右侧的所有内容复制到right变量中。
  6. 第4点是“一致性”。与其他两个变量。你也可以创建一个枚举(LESSEQUALSMORENOT_EQUAL(在我的例子中)并返回它,因为可能性集仅限于这些

    在代码中:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    const char *delimiters[] = {
        "<", ">", "==", "<>", NULL
    };
    
    int split_string (const char *input, char **dest_left, char **dest_delim, char **dest_right)
    {
        int iterator;
        int best_fit_delim;
        char *ptr;
    
        /* (optionally) clean whitespace at start */
        while (isspace(*input))
            input++;
    
        /* look for the longest delimiter we can find */
        best_fit_delim = -1;
        iterator = 0;
        while (delimiters[iterator])
        {
            ptr = strstr (input, delimiters[iterator]);
            if (ptr)
            {
                if (best_fit_delim == -1 || strlen(delimiters[iterator]) > strlen(delimiters[best_fit_delim]))
                    best_fit_delim = iterator;
            }
            iterator++;
        }
    
        /* did we find anything? */
        if (best_fit_delim == -1)
            return 0;
    
        /* reset ptr to this found one */
        ptr = strstr (input, delimiters[best_fit_delim]);
    
        /* copy left hand side */
        iterator = ptr - input;
        /* clean whitespace at end */
        while (iterator > 0 && isspace(input[iterator-1]))
            iterator--;
        *dest_left = malloc (iterator + 1);
        memcpy (*dest_left, input, iterator);
        (*dest_left)[iterator] = 0;
    
        /* the delimiter itself */
        *dest_delim = malloc(strlen(delimiters[best_fit_delim])+1);
        strcpy (*dest_delim, delimiters[best_fit_delim]);
    
        /* update the pointer to point to *end* of delimiter */
        ptr += strlen(delimiters[best_fit_delim]);
        /* skip whitespace at start */
        while (isspace(*ptr))
            ptr++;
    
        /* copy right hand side */
        *dest_right = malloc (strlen(ptr) + 1);
        strcpy (*dest_right, ptr);
    
        return 1;
    }
    
    int main (void)
    {
        char *source_str = "A <> B";
        char *left, *delim, *right;
    
        if (!split_string (source_str, &left, &delim, &right))
        {
            printf ("invalid input\n");
        } else
        {
            printf ("left: \"%s\"\n", left);
            printf ("delim: \"%s\"\n", delim);
            printf ("right: \"%s\"\n", right);
    
            free (left);
            free (delim);
            free (right);
        }
        return 0;
    }
    

    导致A <> B

    left: "A"
    delim: "<>"
    right: "B"
    

    如果您只需要检查<==>的列表,则代码可以更小一些;然后你可以使用strchr,对于单个字符(如果找到=,请检查下一个字符)。您也可以忘记best_fit长度检查,因为只有一个适合。

    代码仅删除比较运算符周围的空格。为了保持一致性,您可能希望删除输入开头和结尾的所有空格;然后,可以通过长度为left的返回right0变量检测无效输入 - 即,它们仅包含0字符串终止符。你仍然需要free那些零长度的字符串。

    为了好玩,您可以将"GT","LT","GE","LE"添加到分隔符,并查看它对字符串的处理方式,例如A GT BALLEQUALFAULTY<MATCH