Используйте strtok(), чтобы разбить строку на 3 части

Следующие строки кода дают мне ошибку сегментации. Регистры: inputPtr = 00 PRNT 02 (правильный ввод со стандартного ввода) после fgets, inputPtr = 00 после первого strtok() и inputPtr = (null) после второго strtok()

if/else с возвратом 3; это проверка ошибок.

Насколько я понимаю, проблема заключается в том, что второй вызов strtok() не читается в PRNT, поэтому я понимаю, почему происходит segfault. Я просто очень хотел бы иметь возможность читать в 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, " ");

person airvector222    schedule 05.03.2014    source источник


Ответы (2)


Проведем следующие тесты.

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, " ");
person Shashwat Kumar    schedule 05.03.2014

strtok предназначен для использования не так, как вы используете. Вот некоторая документация из Справочник по C++:

При первом вызове функция ожидает строку 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;
}
person R Sahu    schedule 05.03.2014