Как я могу проверить первый символ в строке C? Пытался использовать strtok, но не удалось

Я пишу программу на C, которая читает файл, указанный в качестве входных данных. Я должен создать калькулятор, каждая строка файла составлена ​​так:

*2
+6
-8
+33
.......

Я пытался использовать strtok для отделения операции от числа. Моя проблема в том, что strtok ведет себя не так, как должен. Почему моя программа всегда вводит все ifs?

typedef struct{
    long result;
    long number;
    char done;
}shm_data;

void create_operation(char* buffer,shm_data* data){

    char* add,*sottr,* molt;
    long number=0;

    if (((add=strtok(buffer,"+"))!=NULL))
    {
        printf("add: %s\n",add);
    }
     
    if (((sottr=strtok(buffer,"-"))!=NULL))
    {
        printf("sottr: %s\n",sottr);
    }
    
    if (((molt=strtok(buffer,"*"))!=NULL))
    {
        printf("molt: %s\n",molt);
    }

}

void child_mng(shm_data* data,int sem_id,char* path){
    
    FILE* r_stream;
    char tmp[DIM];

    if ((r_stream=fopen(path,"r"))==NULL)
    {
        perror("fopen");
        exit(1);
    }

    while(fgets(tmp,DIM,r_stream))
    {
        if (tmp[strlen(tmp)-1]=='\n')
            tmp[strlen(tmp)-1]='\0';

        printf("read file: %s\n",tmp);
        create_operation(tmp,data);

    }

    exit(0);

}

э.

Предположим, что файл содержит только одну строку:

+80

Это мой вывод:

./calculator list.txt 
read file: +80
add: 80
sottr: +80
molt: +80

но вывод должен быть таким:

./calculator list.txt 
read file: +80
add: 80

почему это происходит? Могу ли я сделать это по-другому?

«Моя проблема в том, что strtok ведет себя не так, как должен». По вашим собственным словам, что именно, по вашему мнению, он должен делать вместо этого и почему? Пожалуйста, будьте подробны. Кроме того, подумайте о том, чтобы прочитать документацию, чтобы убедиться, что вы правильно поняли.

Karl Knechtel 03.04.2023 10:18

Отвечает ли это на ваш вопрос? Как strtok() разбивает строку на токены в C?

Karl Knechtel 03.04.2023 10:20

Функция strtok здесь не очень подходит. Я бы лично проанализировал здесь вручную, просматривая строку, пока не получу цифровой символ. Затем скопируйте все до цифры в отдельную строку (которую я затем «обрезаю», удаляя начальные и конечные пробелы). Используйте strcmp в строке оператора в цепочке if ... else if ... и используйте strtol, чтобы получить числовое значение. Не забывайте о проверке ошибок и проверке ввода.

Some programmer dude 03.04.2023 10:24

99,9% strtok ведет себя так, как должен, просто не так, как вы думаете. Используйте отладчик.

gnasher729 03.04.2023 10:29

как сравнить только первый символ? я пробовал так (strcmp(buffer[0],"+")==0), но получаю ошибку

Valentino Fabris Valenti 03.04.2023 11:04

@ValentinoFabrisValenti if (buffer[0] == '+') сравнил бы только первый символ. Другой вариант — создать карту оператора. Пример

Ted Lyngmo 03.04.2023 11:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если формат гарантированно всегда будет как <op><number>, где

  • <op> это '+', '-', '*' или '/'; И
  • <number> — допустимое целое число; И
  • Между <op> и <number> нет пробела; И
  • <op> — первый символ в строке

тогда простое switch (buffer[0]) будет работать нормально, и использование &buffer[1] в качестве строки для числа будет работать.

Например:

const char *number = &buffer[1];
switch (buffer[0])
{
case '+':
    printf("Add %s\n", number);
    break;
// Etc. for '-', '*' and '/'

default:
    printf("Invalid operator\n");
    break;
}

Если вам нужно целочисленное значение, используйте, например. strtol чтобы преобразовать его:

long number = strtol(&buffer[1], NULL, 10);
printf("The number is %ld\n", number);

Обратите внимание, что это не сработает, если не гарантируется соответствие ввода правилам, изложенным в списке выше. Также обратите внимание, что вам действительно нужно добавить проверку ввода и проверку ошибок, чтобы защититься от ввода, который не соответствует правилам.

Я согласен, что strtok не подходит для этой задачи.

Вы можете использовать sscanf здесь. Строка формата sscanf может содержать буквенные символы; sscanf затем проверит, совпадают ли они, и выполнит остальную часть своей работы, если они совпадают (и сообщит об ошибке, если они не совпадают).

int number;

if (sscanf(buffer, "+%d", &number) == 1)
    printf("Let's add\n");
else if (sscanf(buffer, "-%d", &number) == 1)
    printf("Let's subtract\n");
else if (sscanf(buffer, "*%d", &number) == 1)
    printf("Let's multiply\n");
else
    printf("Error!\n");
printf("The number we are going to manipulate is: %d\n", number);

Другие вопросы по теме