如何使用C中的char *循环字符?

时间:2016-01-22 22:06:34

标签: c stack calculator

我试图在C中创建一个计算器。我在我的eval函数中的(char * String)参数是正确的,但我并不感兴趣。我真的明白为什么或如何正确使用它。我的eval函数将以后缀表示法输入数学表达式。所以这是我的代码到目前为止,基本上我试图接受一个字符串,将所有数字推入一个字符串堆栈然后如果找到一个运算符,弹出两个'字符串'关闭字符串堆栈,将这些字符串转换为整数(这是我不确定如何做的另一件事),进行计算,将结果推送到int堆栈。在搜索完所有输入之后,遍历int堆栈并添加所有的int。这是我的代码:(忽略包括)/ *

int eval(char* String);   //implicit declarations
int bourneLongPush(int);
char* bournePop(void);
int bournePush(char *string);
int bourneLongPop(void);
int bourneGetLongStackSize(void);

int eval(char* String)
{
    int result = 0;
    int index = 0;
    int arg1;
    int arg2;
    char* endptr;

    while(String[index] != '\0'){                      //while our     String pointer is not equal to null,
        if(strtoimax(String, &endptr, 10) == NULL){    //if the character isn't a number,
            switch(String[index]){                     //switch on the operator
            case "+":  
                arg2 = bournePop();
                arg1 = bournePop();//*** how do I change char*'s to ints?
                bourneLongPush(arg2+arg1);
                break;
            case "-":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2-arg1);
                break;
            case "/":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2/arg1);
                break;
            case "*":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2*arg1);
                break;
            case ">":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2>>arg1);
                break;
            case "<":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2<<arg1);
                break;
            case "^":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(pow(arg2, arg1));
                break;
            case "|":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2|arg1);
                break;
            case "&":
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2&arg1);
                break;
            case "%":   
                arg2 = bournePop();
                arg1 = bournePop();
                bourneLongPush(arg2%arg1);
                break;
            default:
                break;
        }
        else{                                //a number was found
        int check = bournePush(String[index]);//push the number into string stack
            if(check == 1)
            {
                //error in push due to size
            }
        }
    index++;
    }
}
//Our input was read in as null so no more input needs to be read
    for(int j = 0; j<(int)bourneGetLongStackSize; j++)
    {
        int num = bourneLongPop();
        result += num;
    }
    return result;
}

2 个答案:

答案 0 :(得分:1)

所以,我建议不要将所有字符都推入堆栈然后将它们转换为整数并应用运算符,为什么我们不将它们转换为整数然后将它们推入堆栈然后应用运算符。

因此,循环中的else条件看起来像这样::

int num = 0;
while() {
    if(the character isn't a number) { //I do not exactly understand the condition you used here, but I hope you have got it figured
        bournePush(num);
        num = 0;
        switch(String[index]) {
        ...
        ...
        //remains same
        }
    }
    else {
        convertToNum(num, string[index]);
    }
}

在这里,我使用num存储当前字符串中的数字值,因此,如果我在字符串中遇到123,我将int 123存储在num中使用convertToNum函数,所以当我点击运算符时,我只需将堆栈中的完整num推入并重新初始化为0,这样我就可以用它来存储下一个数字。 / p>

这就是convertToNum看起来像::

void convertToNum(int &num, char digit) {
    int numDigit = digit - '0';
    num = num*10 + numDigit;
}

那么这将回答你关于如何将字符转换为整数的问题。在这里,我通过引用传递num,以便在converToNum中看到我在main中所做的任何更改。然后在numDigit中,我从char中减去0 digit,这将从char 0中减去char digit的ASCII值,并为我们提供值由该字符表示的整数。然后我用10做一个简单的乘法并加上下一个数字,只是简单的数学。

此外,这极大地简化了bournePopborneLongPop函数,因为现在你的堆栈只是整数,所以你不需要分离函数,现在你只需要弹出一个值堆栈并将其与switch中的运算符一起使用。

我希望这有帮助!

编辑::

我假设你的postfix字符串之间有空格来表示单独的数字,所以你可能实际上有一个像这样的字符串::

  

123 456 +

所以,上面的代码实际上会失败,因为在456之后它会遇到空间,它会进入if条件并将456推入堆栈然后它会命中+它会将0推入堆叠,然后在+上应用0 and 456这是错误的,因此我们将bournePush num只有当我们遇到空间时才会堆叠所以你的最终代码应该是这样的::

int num = 0;
while() {
    if(the character isn't a number) { //I do not exactly understand the condition you used here, but I hope you have got it figured
        if(String[index] == ' ') {
            bournePush(num);
            num = 0;
        } else {
            switch(String[index]) {
            ...
            ...
            //remains same
            }
        }
    }
    else {
        convertToNum(num, string[index]);
    }
}

此外,我并不认为您的switch会有效,因为当您撰写switch(String[index])时,您在撰写{{1}时为switch定义了char你相信,你将case条件定义为一个字符串,它会产生编译错误。因此,您的所有case "+"都应该像case一样进行更改,这样就可以了。

此外,检查字符是否为数字的更简单方法是::

case '+'

此检查int checkNum(char a) { if(a >= '0' && a <= '9') return 0; return 1; } 是否在a0之间,并返回9(false)和0(true),否则,只是建议!

答案 1 :(得分:1)

1)if(strtoimax(String, &endptr, 10) == NULL){不是一个很好的测试,看看转换是否有效。

intmax_t value = strtoimax(String, &endptr, 10);
if (endptr != String) {
  // endptr now points to the next part of the string to parse
  ConversionWorked(value);
} else
  ConversionFailed();
}

代码可以清除errno以检测溢出

errno = 0;
intmax_t = value = strtoimax(String, &endptr, 10);
if (endptr != String) {
  if (errno) ConversionOverflowed(value)
  else ConversionWorked(value);
} else
  ConversionFailed();
}

2)错误switch()用法

switch(String[index]) {
  // case "+": 
  case '+': // String[index] is a `char`, not a string

3)可能还有其他问题,例如bournePush() - 但需要查看未解决的代码才能解决..