2009-01-28 88 views
3

我面臨需要拉出ANSI C中格式爲「blah.bleh.bloh」的字符串中的信息。通常我會使用strok ()來完成這個任務,但由於我通過strtok得到了這個字符串,並且strtok不是線程安全的,所以我不能使用這個選項。錯誤解析C中的字符串「左操作數必須爲l值」

我寫了一個函數來手動解析字符串。這裏是一個snippit:

for(charIndex=0; charIndex < (char)strlen(theString); charIndex++) 
{ 
    if(theString[charIndex] == '.') 
    { 
     theString[charIndex] = '\0'; 
     osi_string_copy_n(Info[currentInfoIndex], 1024, theString, charIndex + 1); 
     currentInfoIndex++; 
     theString = &theString[charIndex + 1]; 
    } 
    charIndex++; 
} 

正如你所看到的,我試圖找到'。'的第一個匹配項。並記下角色的索引。然後我轉換'。'爲空字符並將第一個字符串複製到數組。

然後,我想改變指針開始發現分隔符的地方,基本上給了我一個新的更短的字符串。

不幸的是,我上線得到一個錯誤:

theString = &theString[charIndex + 1]; 

的錯誤是:

error C2106: '=' : left operand must be l-value 

爲什麼我不能移動指針這樣的嗎?我的方法有缺陷嗎?也許有人有更好的想法來解析這個字符串。

編輯:在迴應的意見,爲theString的聲明是:

char theString[1024] = {0}; 

此外,我保證theString絕不會超過1024個字符。

+0

讓我們知道`theString`是如何聲明的。 – 2009-01-28 23:53:00

+0

您還應該查看一些其他字符串函數,如strspn和strcspn。 – MSN 2009-01-29 00:09:08

+0

無關,但爲什麼「(char)strlen(theString)」?你是否希望這個函數不能處理超過128個字符的字符串? – 2009-01-29 00:30:17

回答

8

在假設您將String定義爲數組的情況下,嘗試將其定義爲指針。當你將一個char變量聲明爲一個數組時,你不能以後改變它的地址。

我假設你有類似

char theString[100]; 

最簡單的辦法就是不理會這一宣言,並添加另一個聲明:

char *str = theString; 

,然後用str無處不在,你現在使用theString

0

變量「theString」必須是一個指針而不是數組類型。

-1

如果您嘗試指定文字,則可能會發生該錯誤。在你的情況下,如果theString已被#define d作爲預處理器宏而不是變量,則可能發生這種情況。

4

您可以使用strtok_r,它在大多數平臺上都可用並且是可重入的。這意味着它不保持內部狀態,並且可以毫無困難地從嵌套循環中調用它。

2

只有一個真正的C方式,使用指針,緊密循環和神祕命令:-)。

下面的getNext()函數將允許您按順序返回所有組件,然後是空標記。您需要提供足夠大的緩衝區來存儲組件。我還包括我的測試程序,以便您可以檢查它(如果您願意,可以添加更多的單元測試用例)。

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

char *getNext (char *pStr, char *pComp) { 
    /* Special for '.' at string end. */ 
    if ((*pStr == '.') && (*(pStr+1) == '\0')) { 
     *pComp = '\0'; 
     return pStr + 1; 
    } 

    /* Check if no components left. */ 
    if (*pStr == '\0') 
     return NULL; 

    /* Transfer component one character at a time. */ 
    while ((*pStr != '\0') && (*pStr != '.')) 
     *pComp++ = *pStr++; 
    *pComp = '\0'; 

    /* Skip '.' at end, if there, but not at end of string. */ 
    if ((*pStr == '.') && (*(pStr+1) != '\0')) 
     pStr++; 

    // Return location of next component. 
    return pStr; 
} 

int main (int argCount, char *argVal[]) { 
    int argNum; 
    int compNum; 
    char *newStr; 
    char *strPtr; 

    if (argCount < 2) { 
     printf ("Usage: components <string to componentize>...\n"); 
     return 1; 
    } 
    for (argNum = 1; argNum < argCount; argNum++) { 
     if ((newStr = malloc (strlen (argVal[1]) + 1)) == NULL) { 
      printf ("Out of memory for '%s'.", argVal[argNum]); 
     } else { 
      printf ("Input string is '%s'.\n", argVal[argNum]); 
      compNum = 0; 
      strPtr = getNext (argVal[argNum],newStr); 
      while (strPtr != NULL) { 
       printf (" Component [%3d] is '%s'.\n", ++compNum, newStr); 
       strPtr = getNext (strPtr,newStr); 
      } 
      free (newStr); 
     } 
    } 

    return 0; 
} 

下面是輸出:

[fury]> components your.test.string .dot.at.start at.end. .both. no_dots '' 
Input string is 'your.test.string'. 
    Component [ 1] is 'your'. 
    Component [ 2] is 'test'. 
    Component [ 3] is 'string'. 
Input string is '.dot.at.start'. 
    Component [ 1] is ''. 
    Component [ 2] is 'dot'. 
    Component [ 3] is 'at'. 
    Component [ 4] is 'start'. 
Input string is 'at.end.'. 
    Component [ 1] is 'at'. 
    Component [ 2] is 'end'. 
    Component [ 3] is ''. 
Input string is '.both.'. 
    Component [ 1] is ''. 
    Component [ 2] is 'both'. 
    Component [ 3] is ''. 
Input string is 'no_dots'. 
    Component [ 1] is 'no_dots'. 
Input string is ''. 
0

theString = &theString[charIndex + 1];應擺在首位從來沒有存在過。即使該行不會出錯並正常運行,theString[charIndex]也不會成爲您期望的下一個相鄰字符,因爲theString已被移動。

我的建議,幾乎最少的代碼改變:

for(charIndex=0; charIndex < strlen(theString); charIndex++) 
{ 
    if(theString[charIndex] == '.') 
    { 
     theString[charIndex] = '\0'; 
     osi_string_copy_n(Info[currentInfoIndex], 1024, theString + subStrStart, charIndex + 1 - subStrStart); 
     currentInfoIndex++; 
     subStrStart = charIndex + 1; 
    } 
    charIndex++; 
} 

我不知道什麼是您的osi_string_copy_n做的,所以這條線就是從原始代碼的猜測。但是,如果您將子字符串複製到另一個地方,並且在函數參數中指定了子字符串長度,那麼應該不需要將子字符串的末尾爲空?

編輯:
我發現你的代碼有兩個charIndex++。是theString雙字節字符串?如果是的話,也許更恰當使用wchar_t

0

如果你有一個非古libc,你有strtok_r,這是strtok重入變種。

char *saveptr; 
char *str; 
for (str = strtok_r(theString, ".", &saveptr); 
     str; 
     str = strtok_r(NULL, ".", &saveptr) 
    ) 
{ 
    printf("got: '%s'\n", str); 
} 

這保證不會影響任何國家strtok保持周圍,或任何其他國家呼叫strtok_r保持(假設他們不同意你的saveptr)。

相關問題