c - 通过函数传递字符串会剪切前几个字符

标签 c stdin

我必须编写一个代码,以中缀表示法接收表达式,并输出正确的答案。

示例输入如下:

3
2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
1.8752 ^ 3.7947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
3.8120 / 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795

第一个输入是一个整数,表示后面有多少个表达式。

为了解决这个问题,我创建了一个函数 result(),它接受包含表达式的字符串。该函数有效,但仅适用于循环的第一次迭代。

从这个错误中,我怀疑我获取输入的方式有问题,因此我在主函数中放置了一条 print 语句,以查看是否从 STDIN 获得了正确的输入:

int main(void) {
    int num; //get num of expressions
    scanf("%d", &num);
    getchar(); //get newline
    char exp[MAX];
    //gets the whole string of input
    for(int a = 0; a < num; a++) {
        fgets(exp, MAX, stdin);
        exp[strlen(exp)-1] = 0;
        printf("STDIN: %s\n", exp);
        //double ans = result(exp);
        memset(exp, 0, MAX);
        //printf("%0.4lf\n\n", ans);
    }
}

这是我的输出:

STDIN: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
STDIN: 1.8752 ^ 3.7947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
STDIN: 3.8120 / 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795

因此,从这里我知道 STDIN 确实获得了正确的输入。接下来,在结果函数中,我放置了一条打印语句,用于检查输入到函数中的字符串的值。现在,如果我取消注释 main 中调用函数结果的行,并放入相同的输入,我会得到不同的输出。

STDIN: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
FUNCTION: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121

STDIN: 947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
FUNCTION: 947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631

STDIN:  5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795
FUNCTION:  5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795

为什么会发生这种情况?即使我删除函数中的 print 语句,也会发生此错误。只要我调用函数 result()

就会发生这种情况

调用该函数时来自 STDIN 的输入:

STDIN: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
STDIN: 947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
STDIN:  5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795

我怀疑它与空格有关,但我无法弄清楚该错误会发生在哪里?我已经处理好了换行符了吗?

<小时/>

完整代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define MAX 100000

struct Stack {
    int data[MAX];
    int top;
};
typedef struct Stack Stack;

double numbers[MAX]; //stack for numbers
int numTop;

void Initialize(Stack *S) {
    S->top = -1;
    memset(S->data, 0, MAX);
}

void initNumbers() {
    numTop = -1;
    memset(numbers, 0, MAX);
}

char peek(Stack *S) {
    return S->data[S->top];
}

void push(Stack *S, char c) {
    S->top++;
    S->data[S->top] = c;
}

char pop(Stack *S) {
    char value = S->data[S->top];
    S->top--;
    return value;
}

int isEmpty(Stack *S) {
    if(S->top == -1) {
        return 1; //empty
    } else {
        return 0;
    }
}

int isDigit(char c) {
    if(c >= '0' && c <= '9' || c == '.') {
        return 1;
    } else {
        return 0;
    }
}

int isOperation(char c) {
    if(c == '+' || c == '-' || c == '*' || c == '/' || c == '^') {
        return 1;
    } else {
        return 0;
    }
}

double ConvertTodouble(char exp[], int a, int size) {
    char temp[MAX];
    memset(temp, 0, MAX);
    for(int i = 0; i < size; i++) {
        temp[i] = exp[a];
        a++;
    }
    return atof(temp);
}

void pushNum(double num) { //for num array
    numTop++;
    numbers[numTop] = num;
}

double popNum() {
    double result = numbers[numTop];
    numTop--;
    return result;
}

double evaluate(double a, double b, char op) {
    if(op == '+') {
        return a + b;
    } else if(op == '-') {
        return a - b;
    } else if(op == '*') {
        return a * b;
    } else if(op == '/') {
        return a / b;
    } else if(op == '^') {
        return pow(a, b);
    }
}

int weight(char c) {
    switch(c) {
        case '+':
        case '-': return 1;
                  break;
        case '*': 
        case '/': return 2;
                  break;
        case '^': return 3;
                  break;
    }
}

//if isp > icp, pop (returns 1)
//this returns 1 if isp > icp (left associative)
//returns 1, we pop
int higherPrecedence(char instack, char incoming) { 
    int isp = weight(instack);
    int icp = weight(incoming);

    if((isp == icp) && instack == '^') {
        return 0;
    } else if((isp == icp) && instack != '^') {
        return 1;
    }

    if(isp > icp) {
        return 1;
    } else {
        return 0;
    }
}

double result(char exp[]) {
    Stack S; //stack for operations (+,-,*,/,^)
    double ans = 0;
    Initialize(&S);
    initNumbers();
    int len = strlen(exp);
    int flag = 0;
    for(int i = 0; i < len; i++) {
        if(exp[i] == ' ') {
            getchar();
        } else if(isDigit(exp[i])) {
            //gets number from char array and converts to double
            flag = i; //flag determines how many spaces to move pointer later
            for(int a = i; a < len; a++) {
                if(exp[a] == ' ') {
                    break;
                } else {
                    flag++;
                }
            }
            int size = flag - i;
            double number = ConvertTodouble(exp, i, size);
            pushNum(number);
            i = flag - 1; //update the index so we won't repeat operation
        } else if (exp[i] == '(') {
            push(&S, '(');
        } else if(isOperation(exp[i])) {
            while(!isEmpty(&S) && peek(&S) != '(' && higherPrecedence(peek(&S), exp[i])) {
                char op = pop(&S);
                double b = popNum();
                double a = popNum();
                ans = evaluate(a,b,op);
                pushNum(ans);
            } 
            push(&S, exp[i]);

        } else if(exp[i] == ')') {
            while(!isEmpty(&S) && peek(&S) != '(') {
                char op = pop(&S);
                double b = popNum();
                double a = popNum();
                ans = evaluate(a,b,op);
                pushNum(ans);
            }
            char throw = pop(&S); //this gets the '('
        }
    }
    while(!isEmpty(&S)) {
        char op = pop(&S);
        double b = popNum();
        double a = popNum();
        ans = evaluate(a,b,op);
        pushNum(ans);

        if(numTop == 0) {
            break;
        }
    }
    return ans;
}

int main(void) {
    int num; //get num of expressions
    scanf("%d", &num);
    getchar(); //get newline
    char exp[MAX];
    //gets the whole string of input
    for(int a = 0; a < num; a++) {
        printf("Before: %s\n", exp);
        fgets(exp, MAX, stdin);
        exp[strlen(exp)-1] = 0;
        printf("STDIN: %s\n", exp);
        double ans = result(exp);
        memset(exp, 0, MAX);
        //printf("%0.4lf\n\n", ans);
    }
}

最佳答案

好吧,我想我发现了这个错误。

你可以在这里看到发生了什么

1.8752 ^ 3.7947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
            ^
            |
           you got it from here.

12 个字符丢失。

检查上一行

2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
      x x      x x      x x      x x      x x      x x

有 12 个空格。

这就是导致错误的原因。

for(int i = 0; i < len; i++) {
        if(exp[i] == ' ') {
            getchar();

更改代码的逻辑。希望这会有所帮助。

关于c - 通过函数传递字符串会剪切前几个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47846831/

相关文章:

c - GTK 计时器 - 如何在框架内制作计时器

c - 如果 execlp 不包含 NULL 会怎样?

TCL - 将 STDIN 提供给执行程序

c - 如何初始化数组?

c - C中的字母数组末尾有一个额外的 '@'

c++ - 二进制操作数无效 ^

c - 在 C 中停止 getline

io - 使用 Scanf + input + enter 从 stdin 获得双重输入,如何刷新?

sockets - 套接字编程: why are the behaviors of recv() and read() not the same?

C in 2048,移动问题