[英]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()
desti
了buf
范圍。
現有代碼最簡單的更改是使用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.