簡體   English   中英

如何在C中修復``strtok銷毀原始字符串''

[英]How to fix 'strtok destroy original string' in c

我正在為匯編器編寫編譯器,並且需要對從文件中獲取的文本進行解析,而無需對原始String進行任何更改。 我用來復制String的函數是strcpy到緩沖區,而用來剪切String的函數是strtok來剪切緩沖區。 一切正常,但是一旦我嘗試使用函數addressingConstantIndex剪切原始的String,我就會得到null

我試圖將緩沖區的類型更改為Character的指針,但這實際上沒有用。 我想主要的問題是我將原始String復制到緩沖區的方式。

int main(){
    char desti[MAXCHAR];
    char *temp;
    char *token;
    temp = "mov LIST[5] , r4";
    strcpy(desti,temp);
    printf("\ndest is : %s\n", desti);

    token = strtok(desti," ");

    printf("\nthe Token in Main is : %s \n", token);

    token = strtok(NULL, ",");

    printf("\nthe Token in Main is : %s\n", token);

    printf("\nThe value is %d \n ",addressingConstantIndex(token));

    token = strtok(NULL, " ,");

    printf("\nthe Token in Main is : %s\n", token);
    return 0;
}



int addressingConstantIndex(char * str) {
    char buf[43];
    char *token;
    int ans;
    strcpy(buf, str);
    token = strtok(buf, "[");
    printf("The string is %s\n",str);
    if (token != NULL)
    {
        printf("the token is %s\n", token);
        token = strtok(NULL, "]");
        printf("the token is %s\n", token);
        if(isOnlyNumber(token))
        {
            token = strtok(NULL, " ");
            if (checkIfSpaces(token,0) == ERROR)
            {
                printf("ERROR: Extra characters after last bracket %s \n", str);
                ans = ERROR;
            } else
                ans = OK;
        } else {
            printf("ERROR: Unknown string - %s  - its not a macro & not a number.\n", token);
            ans = ERROR;
        }
    } else {
        printf("ERROR: %s , its not a LABEL", token);
        ans = ERROR;
    }
    return ans;
}


int isOnlyNumber(char *str) {
    int i, isNumber;
    i = 0;
    isNumber = 1;
    if (!isdigit(str[i]) && !(str[i] == '-' || str[i] == '+'))
    {
        isNumber = ERROR;
    }
    i++;
    while (i < strlen(str) && isNumber == 1)
    {
        if (!(isdigit(str[i]))) {
            if (isspace(str[i]))  
                isNumber = checkIfSpaces(str, i);
            else
                isNumber = ERROR;
        }
        i++;
    }
    return isNumber;
}


int checkIfSpaces(char *str, int index) {
    int i;
    if (str == NULL)
    {
        return OK;
    } else {
        for (i = index; i < strlen(str); i++)
        {
            if (!isspace(str[i])) return ERROR;
        }
    }
    return OK;
}




預期結果:

dest is : mov LIST[5] , r4

the Token in Main is : mov

the Token in Main is : LIST[5]
The string is LIST[5]
the token is LIST
the token is 5

The value is 1

the Token in Main is : r4

實際結果:

dest is : mov LIST[5] , r4

the Token in Main is : mov

the Token in Main is : LIST[5]
The string is LIST[5]
the token is LIST
the token is 5

The value is 1

the Token in Main is : (null) 

區別在於結果的最后一行。

問題在於strtok()維護指向當前字符串位置的單個靜態指針。 因此,在addressingConstantIndex() ,您開始處理本地buf ,以便當您返回main() ,不再解析desti而是從addressingConstantIndex() destibuf范圍。

現有代碼最簡單的更改是使用strtok_r() (或Windows上的strtok_s() ):

char* context = 0 ;
token = strtok_r( desti, " ", &context ) ;
printf("\nthe Token in Main is : %s \n", token);
token = strtok_r( NULL, ",", &context ) ;
...

然后類似地在addressingConstantIndex()

char* context = 0 ;
token = strtok_r(buf, "[", &context);
...

在每次調用時, strtok用NULL替換字符串中的分隔符。 您的代碼正在主級別上找到“ LIST [5]”令牌,這時它已將NULL替換為“”。

addressingConstantIndex ,將strtok重置為新字符串並正確解析(盡管您的函數鍵入的是void而不是int)。

再次在主要級別上,不會重置strtok ,因此它將繼續解析addressingConstantIndex使用的字符串。

要解決此問題,您需要再次重置strtok才能繼續。 但是,您不能只使用strtok(desti,",")來調用它,因為desti將先前調用中的所有分隔符都設置為NULL。

一種快速的解決方案是將令牌復制以在主級別上饋入到addressingConstantIndex中,並在完成下一級別的解析之前完成主級別。

int main(){
    char desti[MAXCHAR];
    char *temp;
    char *token;
    temp = "mov LIST[5] , r4";
    strcpy(desti,temp);
    printf("\ndest is : %s\n", desti);

    token = strtok(desti," ");
    printf("\nMnemonic : %s \n", token);

    token = strtok(NULL, ",");
    printf("\nLIst bit: %s\n", token);

    char buf[80];       //Save the token 
    strcpy(buf, token);

    token = strtok(NULL, " ,"); //Finish this level of processing
    printf("\nRegister: %s\n", token);

    //Continue at the next level with copy
    printf("\nThe value is %d \n ",addressingConstantIndex(buf)); 
    return 0;
}

盡管strtok_r解決方案可能會更好地滿足您的需求

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM