如何在 C 中使用 char* 循环遍历字符?

How do I loop through characters with char*'s in C?

我正在尝试用 C 语言创建一个计算器。我确信我的 eval 函数中的 (char* String) 参数是正确的,但我没有真正理解为什么或如何正确使用它。我的 eval 函数将以后缀表示法给出数学表达式的输入。到目前为止,这是我的代码,本质上我是在尝试接收一个字符串,将所有数字压入字符串堆栈,然后如果找到运算符,则从字符串堆栈中弹出两个 'strings',将这些字符串转换为整数(这是我不确定如何做的另一件事),进行计算,将结果推入 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] != '[=10=]'){                      //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;
}

所以,我建议与其将所有字符压入堆栈,然后将它们转换为整数并应用运算符,不如在将它们压入堆栈之前将它们转换为整数,然后应用运算符。

因此,循环中的 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 123num使用 convertToNum 函数,所以当我点击一个运算符时,我只需将完整的 num 压入堆栈并将 re-initialize 压入 0 以便我可以使用它来存储下一个号码。

这就是 convertToNum 的样子 ::

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

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

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

中的运算符一起使用

希望对您有所帮助!

编辑::

我假设你的后缀字符串之间有 spaces 来表示单独的数字,所以你实际上可能有这样的字符串 ::

123 456 +

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

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]) 时,你已经为 char 定义了 switch 当你写 case "+" 我相信你将 case 条件定义为一个会产生编译错误的字符串。所以,你所有的case都应该改成这样case '+',这样就可以了。

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

int checkNum(char a) {
    if(a >= '0' && a <= '9')
        return 0;
    return 1;
}

这会检查 a 是否在 09 和 returns 之间 0(false) 和 1(true) 否则, 只是建议!

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() - 但需要查看未发布的代码才能解决..