Я пишу программу на 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() разбивает строку на токены в C?
Функция strtok
здесь не очень подходит. Я бы лично проанализировал здесь вручную, просматривая строку, пока не получу цифровой символ. Затем скопируйте все до цифры в отдельную строку (которую я затем «обрезаю», удаляя начальные и конечные пробелы). Используйте strcmp
в строке оператора в цепочке if ... else if ...
и используйте strtol
, чтобы получить числовое значение. Не забывайте о проверке ошибок и проверке ввода.
99,9% strtok ведет себя так, как должен, просто не так, как вы думаете. Используйте отладчик.
как сравнить только первый символ? я пробовал так (strcmp(buffer[0],"+")==0), но получаю ошибку
@ValentinoFabrisValenti if (buffer[0] == '+')
сравнил бы только первый символ. Другой вариант — создать карту оператора. Пример
Если формат гарантированно всегда будет как <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);
«Моя проблема в том, что strtok ведет себя не так, как должен». По вашим собственным словам, что именно, по вашему мнению, он должен делать вместо этого и почему? Пожалуйста, будьте подробны. Кроме того, подумайте о том, чтобы прочитать документацию, чтобы убедиться, что вы правильно поняли.