如何修复';strtok销毁原始字符串';在c中

如何修复';strtok销毁原始字符串';在c中,c,string,strtok,C,String,Strtok,我正在为汇编程序编写一个编译器,我需要对从文件中获取的文本进行解析,而不需要对原始字符串进行任何更改。我用于将字符串复制到缓冲区的函数是strcpy,用于剪切字符串的函数是strtok,用于剪切缓冲区。 一切都很完美,但在使用函数addressingConstantIndex后尝试剪切原始字符串时,我得到了null 我试图将缓冲区的类型更改为字符指针,但实际上没有起作用。我想主要的问题在于我将原始字符串复制到缓冲区的方式 int main(){ char desti[MAXCHAR];

我正在为汇编程序编写一个编译器,我需要对从文件中获取的文本进行解析,而不需要对原始字符串进行任何更改。我用于将字符串复制到缓冲区的函数是
strcpy
,用于剪切字符串的函数是
strtok
,用于剪切缓冲区。 一切都很完美,但在使用函数
addressingConstantIndex
后尝试剪切原始字符串时,我得到了
null

我试图将缓冲区的类型更改为字符指针,但实际上没有起作用。我想主要的问题在于我将原始字符串复制到缓冲区的方式

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 : (null) 


不同之处在于结果的最后一行。

问题在于
strtok()
维护一个指向当前字符串位置的静态指针。因此,在
addressingConstantIndex()
中,您开始处理本地
buf
,这样当您返回
main()
时,它不再解析
desti
,而是从
addressingConstantIndex()
解析现在超出范围的
buf

对现有代码最简单的更改是在Windows上使用
strtok\u r()
(或
strtok\u s()
):

然后在
寻址Constantindex()中类似地:


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\u r
解决方案可能更符合您的需要,但如果您需要保留原始字符串,请复制字符串并在副本上使用
strtok()
,或者不要使用
strtok()
。还要注意,不能同时使用
strtok()
分析两个不同的字符串。基本上,
strtok();这是许多次错误的函数之一。请尝试
strspn()
strcspn()
。我需要对我得到的字符串的每个部分进行验证。您的平台是否有
strtok\r
char* context = 0 ;
token = strtok_r( desti, " ", &context ) ;
printf("\nthe Token in Main is : %s \n", token);
token = strtok_r( NULL, ",", &context ) ;
...
char* context = 0 ;
token = strtok_r(buf, "[", &context);
...
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;
}