2016-07-30 110 views
-2

我有這個由幾個分隔符之一分割字符串?

A > B,或A < B,或A==B

使用strtok我會破壞數據,我的目標是獲得某種結構的,我可以檢查:

  1. 我有什麼樣的分隔符
  2. 可以訪問它的兩邊(A和B)。

這樣:

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 : 
     {} 
    } 


} 
+0

爲什麼不用strtok? – mik1904

+1

@ mik1904它不會使用「==」,它不是一個字符。 – Curnelious

+0

由於可能有也可能沒有空白分隔符(或者看起來像),僅*指針*是不夠的。您需要一個'result'結構體,其中至少包含一個指向每個標記開頭及其長度的指針,或者,也可以將每個標記複製到一個新字符串中。代碼可以非常簡單;到目前爲止,你有什麼? – usr2564301

回答

1

這裏是一個廣義的過程:

  1. 對於一個給定,使用strstr檢查每個如果它出現在輸入字符串。作爲獎勵,我下面的代碼允許「雙」條目,如<<>;它會檢查所有並儘可能使用最長的。
  2. 確定要使用的最佳分隔符後,您將有一個指針開始。那麼你可以將
  3. ..將其左側的所有內容複製到left變量中;
  4. ..將分隔符本身複製到delim變量(爲了一致性);和
  5. ..將所有分隔符右側的所有內容複製到right變量中。

第4點與其他兩個變量是「一致的」。你也可以創建一個枚舉(LESS,EQUALS,MORE,NOT_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長度檢查,因爲只能有一個適合。

該代碼僅在比較運算符周圍刪除空白。爲了保持一致性,您可能需要刪除輸入開始和結束處的所有空白;那麼通過返回leftright變量檢測到無效輸入,其長度爲0 - 即它們只包含0字符串終止符。您仍然需要free那些零長度的字符串。

爲了好玩,你可以添加"GT","LT","GE","LE"的分隔符,看看它是如何做的字符串,如A GT BALLEQUALFAULTY<MATCH

+0

非常感謝,我會接受。你能看到我的編輯,讓我知道你的意見嗎? (這是一個壞的解決方案?) – Curnelious

+0

@Curnelious:假設它的工作原理(是否將''left'和'right'聲明在你的for循環中?),那麼按照我的標準完全可以。當然,它可以寫得不那麼冗長,也可能在風格上更好。如果它能夠做到這一點,始終如一,準確無誤,這「足夠好」。通過這些練習,您可以增強對C技能的信心。 – usr2564301

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; 
} 

這絕不是做的最好方法,它只是表明你可以使用它。另外,我對此並沒有多少考慮,我編寫了代碼向您展示一個可能的解決方案。其實我並不喜歡它,我也不會用它

+0

哇,這看起來很聰明! :) – Curnelious

+0

你爲什麼不使用它? – Curnelious

+1

因爲它不可靠。我不能立即想到一個明顯失敗的案例。但我不能相信'sscanf()'。雖然如我所說,簡單的情況將起作用。 –