使用strtok()将字符串分成3部分

时间:2014-03-05 05:15:32

标签: c string segmentation-fault strtok

以下代码行给出了分段错误。寄存器是:inputPtr = 00 PRNT 02(来自stdin的正确输入)fgets后,inputPtr = 00后第一个strtok(),inputPtr =(null)后第二个strtok()

if / else with return 3;是一个错误检查。

我理解的问题是对strtok()的第二次调用不是在PRNT中读取,所以我得到了段错误发生的原因。我真的很想能够阅读PRNT。 一点点帮助会很棒!谢谢!

  fgets(input, 15, stdin);
    /*Tokenize instr00 into "00"(instructionCounter) "INST"(operationCode) and "OP"(operand)*/
    if(atoi(strtok(inputPtr, " ")) >= 0 && atoi(strtok(inputPtr, " ")) <= 99)
    {
        *instructionCounter = atoi(strtok(inputPtr, " "));
    }
    else
    {
        return 3;
    }
    inputPtr = strtok(NULL, " ");

2 个答案:

答案 0 :(得分:1)

strtok的使用方式与您使用的方式不同。以下是C++ Reference的一些文档:

  

在第一次调用时,函数需要一个C字符串作为str的参数,其第一个字符用作扫描标记的起始位置。 在后续调用中,函数需要一个空指针 ,并在最后一个标记结束后立即使用该位置作为扫描的新起始位置。

试试这个:

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

int main()
{
   // fgets(input, 15, stdin);

   char input[20]; // = "00 PRNT 02";
   char* firstToken = NULL;
   char* secondToken = NULL;
   char* thirdToken = NULL;
   int instructionCounter = 0;

   strcpy(input, "00 PRNT 02");
   firstToken = strtok(input, " ");
   secondToken = strtok(NULL, " ");
   thirdToken = strtok(NULL, " ");
   instructionCounter = atoi(firstToken);

   fprintf(stdout, "First token: %s\n", firstToken);
   fprintf(stdout, "Second token: %s\n", secondToken);
   fprintf(stdout, "Third token: %s\n", thirdToken);
   fprintf(stdout, "Instruction Counter: %d\n", instructionCounter);

   return 0;
}

答案 1 :(得分:1)

让我们进行以下测试。

fgets(inputPtr, 15, stdin);

现在inputPtr的值为"00 PRNT 02"现在使用strtok获取“00”

char *p = strtok(inputStr," ");

现在printf("%s",p)提供"00"作为输出。

  

strtok是否为“00”分配新内存并将地址返回给p?   答案是。它只返回指向第一个字符的指针,并将其内部指针移动到下一个标记的开头。因此,下次调用strtok(NULL," ")时,它将从该内部指针开始。

因此p指向inputPtr的第一个字符。但printf打印字符串,直到遇到空字符'\0'。因此"00"后跟p后跟空字符。但由于p指向inputStr,所以inputStr也是如此。

因此,在第一个strtok之后,系统将" "之后的初始"00"(空格)替换为空字符。

您可以使用以下命令序列进行检查。

char *p = strtok(inputStr," ");
printf("%s",p); //output is "00"
printf("%s",inputStr); // output is "00" 

因此,当您第二次执行p = strtok(inputStr," ");时,您只会对字符串"00"进行标记,而不是"00 PRNT 02",因此您不会打印PRNT。不要再打电话了。修改后的代码如下。

fgets(inputPtr, 15, stdin);

int a = atoi(strtok(inputPtr, " "));
if(a >= 0 && a <= 99)
{
     *instructionCounter = a;
}
else
{
    return 3;
}
inputPtr = strtok(NULL, " ");