简体   繁体   English

如何让计算器计算输入中带空格的表达式?

[英]How to make the calculator count the expression with spaces in the input?

I tried to make calculator supporting brackets, but I have no idea how to deal if the user's input includes expression with spaces, for example: input: (2 + 3) * 2 i got: 2 If it's normally get (2+3)*2, it counts 10 .我试图让计算器支持括号,但我不知道如果用户输入包含带空格的表达式如何处理,例如:输入: (2 + 3)* 2我得到: 2如果它通常得到(2 + 3) *2,它计数10 My code:我的代码:

#include <stdio.h> 
#define MAX_SIZE 1024 
  
int insert_operand(int *operand, int * top_num, int num) /* data is pushed into the data stack*/
{
     (*top_num) ++;
     operand[*top_num] = num; /*save data*/
      
     return 0; /*Exit normally*/
}
  
int insert_oper (char * oper , int *top_oper , char ch) 
{
     (*top_oper)++;
     oper[*top_oper] = ch; /*save operator*/
  
     return 0; /*Exit normally*/
}
  
int compare(char *oper , int *top_oper , char ch) /* compare the priority of the operating server*/
{
     
     if((oper[*top_oper] == '-' || oper[*top_oper] == '+') /*Determine whether the current priority is higher than the priority of the operator at the top of the stack*/
             && (ch == '*' || ch == '/'))
     {
         return 0;
     }
  
     else if(*top_oper == -1 || ch == '('
             || (oper[*top_oper] == '(' && ch != ')')) /*Determine whether the operator stack is empty; whether the top operator is '('*/
     {
         return 0;
     }
  
     else if (oper[*top_oper] =='(' && ch == ')')
     {
         (*top_oper)--;
         return 1; 
     }
  
     else
     {
         return -1; /*Operate the operator*/
     }
  
}
  
int deal_date(int *operand ,char *oper ,int *top_num, int *top_oper) /*perform data operation*/
{
     int num_1 = operand[*top_num]; /*Take out two data from the data stack*/
     int num_2 = operand[*top_num - 1];
  
     int value = 0;
  
     if(oper[*top_oper] == '+') 
     {
         value = num_1 + num_2;
     }
  
     else if(oper[*top_oper] == '-') 
     {
         value = num_2 - num_1;
     }
  
     else if(oper[*top_oper] == '*') 
     {
         value = num_2 * num_1;
     }
  
     else if(oper[*top_oper] == '/') 
     {
         value = num_2 / num_1;
     }
  
     (*top_num) --; /*Move the top of the data stack down one bit*/
     operand[*top_num] = value; /*Push the obtained value into the data stack*/
     (*top_oper) --; /*Move the top of the operator stack down one bit*/
  
  
}
  
int main()
{
     int operand[MAX_SIZE] = {0}; /*data stack, initialize*/
     int top_num = -1;
  
     char oper[MAX_SIZE] = {0}; /*operator stack, initialize*/
     int top_oper = -1;
  
     char *str = (char *) malloc (sizeof(char) * 100); /*get expression (without =)*/
     scanf("%s", str);
  
     char* temp;
     char dest[MAX_SIZE];
     int num = 0;
  
     int i = 0;
     while(*str != '\0')
     {
         temp = dest;
  
         while(*str >= '0' && *str <= '9') /*judging whether it is data*/
         {
             *temp = *str;
             str++;
             temp++;
         } /*Encounter a symbol to exit*/
  
         if(*str != '(' && *(temp - 1) != '\0') /*Determine whether the symbol is '('*/
         {
             *temp = '\0';
  
             num = atoi(dest); /*convert string to number*/
             insert_operand(operand, &top_num,num); /*Push data into the data stack*/
         }
  
          while(1)
          {
              i = compare(oper,&top_oper,*str); /*judgment operator priority*/
  
             if(i == 0)
             {
                 insert_oper(oper,&top_oper,*str); /*press operator*/
                 break;
             }
  
             else if(i == 1) /*judging whether the expression in brackets ends*/
             {
                 str++;
             }
  
             else if(i == -1) /* data processing */
             {
                 deal_date(operand,oper,&top_num,&top_oper);
             }
  
          }
  `
         str ++; /* point to the next character of the expression */
     }
  `
     printf("%d\n",operand[0]); /*output result*/
  
     return 0; 

I tried to count the equation even if there is a space in it.我试着算方程式,即使里面有空格。 Can someone please help?有人可以帮忙吗?

Solving the problem by removing spaces:通过删除空格解决问题:

So if you're working with equation as string you can simply remove spaces with function like this (there will be probably better way or function in library string.h but this was first guess):因此,如果您将方程作为字符串使用,您可以像这样简单地使用 function 删除空格(可能会有更好的方法或库string.h中的 function 但这是第一个猜测):

char* DeleteSpaces( char* stringWithSpaces, size_t lengthOfString)
    {
    char* stringWithoutSpaces = (char*)calloc(lengthOfString + 1, sizeof(char));
    if( !stringWithoutSpaces )
        return NULL;

    for( unsigned int x = 0, y = 0; x <= lengthOfString; x++, y++ )
        {
        if( stringWithSpaces[x] == ' ' ) // if the character is space
            {
            while( stringWithSpaces[x] == ' ' && x < lengthOfString ) // skip all the spaces OR go away before you hit '\0'
                x++;

            stringWithoutSpaces[y] = stringWithSpaces[x]; // then copy next character into new string
            }
        else  // if there's no space just copy the character
            stringWithoutSpaces[y] = stringWithSpaces[x];
        }

    return stringWithoutSpaces;
    }

This will basically remove all spaces from your received equation.这基本上会从您收到的等式中删除所有空格。 If you really need the smallest possible memory requirement you can use realloc() at the end of the function for more optimal memory usage.如果你真的需要尽可能小的 memory 要求,你可以在 function 的末尾使用realloc()以获得更优化的 memory 用法。

Here's simple example of how to use the function so you can test it:以下是如何使用 function 的简单示例,您可以对其进行测试:

int main()
{
    char firstString[] = "H        e l l o w o r l d\0";
    char* secondString;

    secondString = DeleteSpaces( firstString, strlen(firstString) );
    if( !secondString )
        return -1;

    printf( "%s", secondString );
    free( secondString );
    return 0;
}

Don't forget to use free(SecondString) .不要忘记使用free(SecondString) I hope I helped you atleast a little:)我希望我至少能帮到你一点点:)

As with the previous answer, I added in a function to remove any spaces from the entered formula in order to process the requested calculation.与之前的答案一样,我添加了 function 以从输入的公式中删除所有空格,以便处理请求的计算。 Also, coupled with that, I revised the "scanf" input to read in all of the entered characters which looked to be another symptom you were facing.此外,除此之外,我修改了“scanf”输入以读取所有输入的字符,这看起来是您面临的另一个症状。 With that, following is a refactored version of your program with the additional space compression function.因此,以下是您的程序的重构版本,具有额外的空间压缩 function。

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

#define MAX_SIZE 1024

int insert_operand(int *operand, int * top_num, int num) /* data is pushed into the data stack*/
{
     (*top_num) ++;
     operand[*top_num] = num; /*save data*/

     return 0; /*Exit normally*/
}

int insert_oper (char * oper , int *top_oper , char ch)
{
     (*top_oper)++;
     oper[*top_oper] = ch; /*save operator*/

     return 0; /*Exit normally*/
}

int compare(char *oper , int *top_oper , char ch) /* compare the priority of the operating server*/
{

     if((oper[*top_oper] == '-' || oper[*top_oper] == '+') /*Determine whether the current priority is higher than the priority of the operator at the top of the stack*/
             && (ch == '*' || ch == '/'))
     {
         return 0;
     }

     else if(*top_oper == -1 || ch == '('
             || (oper[*top_oper] == '(' && ch != ')')) /*Determine whether the operator stack is empty; whether the top operator is '('*/
     {
         return 0;
     }

     else if (oper[*top_oper] =='(' && ch == ')')
     {
         (*top_oper)--;
         return 1;
     }

     else
     {
         return -1; /*Operate the operator*/
     }

}

int deal_date(int *operand ,char *oper ,int *top_num, int *top_oper) /*perform data operation*/
{
     int num_1 = operand[*top_num]; /*Take out two data from the data stack*/
     int num_2 = operand[*top_num - 1];

     int value = 0;

     if(oper[*top_oper] == '+')
     {
         value = num_1 + num_2;
     }

     else if(oper[*top_oper] == '-')
     {
         value = num_2 - num_1;
     }

     else if(oper[*top_oper] == '*')
     {
         value = num_2 * num_1;
     }

     else if(oper[*top_oper] == '/')
     {
         value = num_2 / num_1;
     }

     (*top_num) --; /*Move the top of the data stack down one bit*/
     operand[*top_num] = value; /*Push the obtained value into the data stack*/
     (*top_oper) --; /*Move the top of the operator stack down one bit*/

    return value;
}

void compress(char *stx)    /* The additional function */
{
    char work[101];
    int i = strlen(stx);

    strcpy(work, stx);

    for (int j = 0; j < i; j++)
    {
        stx[j] = 0;
    }

    i = 0;

    for (int j = 0; j < (int)strlen(work); j++)
    {
        if (work[j] != ' ')
        {
            stx[i] = work[j];
            i++;
        }
    }
}

int main()
{
     int operand[MAX_SIZE] = {0}; /*data stack, initialize*/
     int top_num = -1;

     char oper[MAX_SIZE] = {0}; /*operator stack, initialize*/
     int top_oper = -1;

     char *str = (char *) malloc (sizeof(char) * 100); /*get expression (without =)*/
     //scanf("%s", str);
     scanf("%[^\n]", str);  /* Refined the scanf call to receive all characters prior to the newline/return character */

     compress(str);         /* Added this function to remove spaces */

     char* temp;
     char dest[MAX_SIZE];
     int num = 0;

     int i = 0;
     while(*str != '\0')
     {
         temp = dest;

         while(*str >= '0' && *str <= '9') /*judging whether it is data*/
         {
             *temp = *str;
             str++;
             temp++;
         } /*Encounter a symbol to exit*/

         if(*str != '(' && *(temp - 1) != '\0') /*Determine whether the symbol is '('*/
         {
             *temp = '\0';

             num = atoi(dest); /*convert string to number*/
             insert_operand(operand, &top_num,num); /*Push data into the data stack*/
         }

          while(1)
          {
              i = compare(oper,&top_oper,*str); /*judgment operator priority*/

             if(i == 0)
             {
                 insert_oper(oper,&top_oper,*str); /*press operator*/
                 break;
             }

             else if(i == 1) /*judging whether the expression in brackets ends*/
             {
                 str++;
             }

             else if(i == -1) /* data processing */
             {
                 deal_date(operand,oper,&top_num,&top_oper);
             }

          }

         str ++; /* point to the next character of the expression */
     }

     printf("%d\n",operand[0]); /*output result*/

     return 0;

}

Testing out your sample formula with some additional spacing to ensure the compression function was working properly, following was the terminal output.使用一些额外的间距测试您的示例公式,以确保压缩 function 正常工作,以下是终端 output。

@Vera:~/C_Programs/Console/Calculate/bin/Release$ ./Calculate 
(2 + 3) * 2
10

Give that a try and see if it meets the spirit of your project.试一试,看看它是否符合您项目的精神。

As pointed out in the comments and other answers, the solution may be to simply "compact" the spaces out of the string before trying to analyse the string's content.正如评论和其他答案中所指出的,解决方案可能是在尝试分析字符串的内容之前简单地“压缩”字符串中的空格。

This doesn't require a lot of code:这不需要很多代码:

#include <stdio.h>

char *stripSP( char *src ) {
    for( char *d = src, *s = src; ( *d = *s ) != '\0'; s++ )
        d += *d != ' ';
    return src;
}

int main( void ) {
    char *s[] = { "Hello", "H e   l l  ooo", "(2 + 5) * 3" };
    for( int i = 0; i < 3; i++ ) {
        printf( "From '%s'  ", s[i] );
        printf( "'%s'\n", stripSP( s[i] ) );
    }
    return 0;
}
From 'Hello'  'Hello'
From 'H e   l l  ooo'  'Hellooo'
From '(2 + 5) * 3'  '(2+5)*3'

Even more compact would be to use array indexing :更紧凑的是使用数组索引

char *stripSP( char s[] ) {
    for( int f=0, t=0; (s[t] = s[f++]) != '\0'; t += s[t] != ' ' ) {}
    return s;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM