编写一个忽略操作顺序的C程序? [英] Writing a C program that ignores the order of operations?

查看:87
本文介绍了编写一个忽略操作顺序的C程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个C程序,该程序可以解决用户的简单数学问题,并使用不同的过程来解决每个部分,然后将值发送回父过程.该程序不应注意操作顺序.例如,如果我有问题:

I want to write a C program that takes a simple math problem from the user and use different processes to solve each part, and then send the value back to the parent process. This program should not pay attention to the order of operations. For instance, if I have the problem:

3 + 4 / 7 + 4 * 2

我希望我的程序输出以下内容:

I want my program to output the following:

Enter problem: 3 + 4 / 7 + 4 * 2
PID 20419 calculated 3+4 as 7
PID 20420 calculated 7/7 as 1
PID 20421 calculated 1+4 as 5
PID 20422 calculated 5*2 as 10
Final result: 10

我在解析输入的方程式时遇到一些麻烦.我正在考虑在C中使用getline()方法来帮助我解析输入.这是我到目前为止的内容:

I am having a bit of trouble parsing the equation I am entering. I am thinking of using the getline() method in C to help me parse input. This is what I have so far:

#include <stdio.h>

#define MAX_LINE_LENGTH 200

int main()
{
    printf("Enter equation: ");
    //getline(&buffer, &size, stdin)
    //&buffer is the address of the first character
    //&size is the address of the variable that holds the size of the input buffer
    //stdin is the input file handle
    size_t n = MAX_LINE_LENGTH;

    //Line becomes a pointer to 200 bytes of memory for you to use
    char *line = malloc(n)
    while ((getline(&line, &n, stdin)) {
        //Parse numbers and operators here
    }

    return 0;
}

有人对如何解析我将从标准输入中输入的数字和运算符有任何建议吗?一旦我读完一个数字,一个运算符和一个数字,我想使用fork().谢谢大家.

Does anyone have any suggestions on how to parse the numbers and operators that I will enter from the standard input? Once I think I read in a number, operator, and a number, I would like to use fork(). Thank you all in advance.

推荐答案

确实捕获了最终数据点的"robustified" 添加的一小部分可能类似于以下内容(使用整数数学运算,如有需要,请更改为浮点数):

A slight bit of a "robustified" addition that does grab the final data point could be something like the following (use of integer math intentional, change to floating-point if desired):

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

#define MAX_LINE_LENGTH 200

int main()
{
    size_t  n = MAX_LINE_LENGTH,
            offset = 0;
    int oper = 0, v1 = INT_MIN;
    char *line = malloc(n);

    if (!line) {    /* validate every allocation */
        perror ("malloc-line");
        return 1;
    }

    printf("Enter equation: ");
    if (getline (&line, &n, stdin) == -1) { /* validate every input */
        fputs ("stream error or user canceled.\n", stderr);
        return 1;
    }

    for (; line[offset];) {     /* loop while not end of line */
        int nchar = 0, v2;
        if (sscanf (line + offset, "%d%n", &v2, &nchar) == 1) { /* read int? */
            if (v1 == INT_MIN)  /* if v1 not set, set v1 to value */
                v1 = v2;
            else {              /* otherwise its v2 */
                int vsave = v1;
                switch (oper) { /* switch on operator, save result in v1 */
                    case '+':   v1 += v2; break;
                    case '-':   v1 -= v2; break;
                    case '*':   v1 *= v2; break;
                    case '/':   v1 /= v2; break;
                    default:    fputs ("error: invalid operator.\n", stderr);
                                break;
                }
                /* output results of calculation */
                printf ("calculated %d%c%d as %d\n", vsave, oper, v2, v1);
            }
            offset += nchar;    /* update offset with nchars read */
        }
        else {  /* read of int failed, must be oper or end */
            size_t used = strcspn (&line[offset], "+-*/");  /* chars to oper */
            offset += used;     /* update offset */
            if (line[offset] == '\n' || line[offset] == 0)  /* end of line? */
                break;
            oper = line[offset++];  /* set oper advance to next char */
        }
    }

    free (line);    /* don't forget to free line */
}

(注意:),您已经分配了malloc,甚至没有直接分配,如果line = NULL;n = 0; getline将自己分配足够的空间,那么不要别忘了free(line);释放已分配的内存(是的,这是在退出时发生的,但是希望您编写的程序在main()中使用getline,所以现在就养成良好的习惯...)

(note: you have allocated with malloc, and even absent the direct allocation, if line = NULL; and n = 0; getline will allocate sufficient space on its own, so don't forget to free(line); to free the memory you have allocated. (yes, here that happens on exit, but hopefully you will write programs that use getline in more than main(), so build good habits now...)

使用上面的"%n"修饰符会将sscanf消耗的字符数放入nchars变量中,然后用于在line中更新offset.

The use of the "%n" specifier above places the number of characters consumed by sscanf in that read in the nchars variable that is then used to update your offset in line.

使用/输出示例

$ ./bin/calculate
Enter equation: 3 + 4 / 7 + 4 * 2
calculated 3+4 as 7
calculated 7/7 as 1
calculated 1+4 as 5
calculated 5*2 as 10


fork()处理计算


fork() To Handle Calculations

从本质上讲,在拥有v1, v2oper之后,唯一需要进行的更改是对fork()进程进行处理,然后在子级中处理switch()语句,然后在父级wait()中处理该语句,直到子级退出在退出并获取下一组值之前.如我的评论所示,man 2 wait中的示例很好地概述了该过程.

Essentially, the only changes needed after you have your v1, v2 and oper is to fork() the process and then handle the switch() statement in the child and then in the parent wait() until the child exits before exiting and grabbing your next set of values. As indicated in my comment, the example in man 2 wait provides a good outline of the process.

根据您的评论,您成功在sscanf调用之后将fork()设置在正确的位置.您要做的就是将调用添加到fork(),并进行验证和确定哪个是子代和父代.然后将现有的计算移到子进程中,并添加对getpid()的调用以添加到您的输出中.在父进程中,定位您的wait(),然后在孩子完成后退出.

Based on your comment, you were setting fork() up in the correct location after the sscanf call succeeds. There all you are doing is adding the call to fork() and the validations and determination of which is the child and parent. Then move the existing calculation into the child process, and add a call to getpid() to add to your output. In the parent process, site up your wait() and then exit after your child is done.

您可以执行以下更改以进行上述更改:

You can implement the following making the changes above:

        if (sscanf (line + offset, "%d%n", &v2, &nchar) == 1) { /* read int? */
            if (v1 == INT_MIN)  /* if v1 not set, set v1 to value */
                v1 = v2;
            else {      /* otherwise its v2 */
                int status;
                pid_t w, pid = fork();  /* fork to compute values */
                if (pid == -1) {        /* validate fork succeeded */
                    perror ("fork");
                    return 1;
                }
                if (pid == 0) {         /* if pid == 0 in child process */
                    int vsave = v1;
                    switch (oper) { /* switch on operator, save result in v1 */
                        case '+':   v1 += v2; break;
                        case '-':   v1 -= v2; break;
                        case '*':   v1 *= v2; break;
                        case '/':   v1 /= v2; break;
                        default:    fputs ("error: invalid oper.\n", stderr);
                                    break;
                    }   /* output child PID with results of calculation */
                    printf ("PID %ld calculated %d%c%d as %d\n", 
                            (long)getpid(), vsave, oper, v2, v1);
                }
                else {      /* in the parent process */
                    do {    /* wait on child PID */
                        w = waitpid(pid, &status, WUNTRACED | WCONTINUED);
                        if (w == -1) {      /* validate waitpid return */
                            perror("waitpid");
                            exit (EXIT_FAILURE);
                        }
                    } while (!WIFEXITED(status) && !WIFSIGNALED(status));
                    exit (EXIT_SUCCESS);    /* child exited, exit parent */
                }
            }
            offset += nchar;    /* update offset with nchars read */
        }

完整的示例仅添加所需的头文件,而其余代码保持不变.例如:

The full example simply adds the needed header files with the remainder of the code unchanged. For example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <sys/wait.h>
#include <unistd.h>

int main (void)
{
    size_t  n = 0,
            offset = 0;
    int oper = 0, v1 = INT_MIN;
    char *line = NULL;

    printf("Enter equation: ");
    if (getline (&line, &n, stdin) == -1) { /* validate every input */
        fputs ("stream error or user canceled.\n", stderr);
        return 1;
    }

    for (; line[offset];) {     /* loop while not end of line */
        int nchar = 0, v2;
        if (sscanf (line + offset, "%d%n", &v2, &nchar) == 1) { /* read int? */
            if (v1 == INT_MIN)  /* if v1 not set, set v1 to value */
                v1 = v2;
            else {      /* otherwise its v2 */
                int status;
                pid_t w, pid = fork();  /* fork to compute values */
                if (pid == -1) {        /* validate fork succeeded */
                    perror ("fork");
                    return 1;
                }
                if (pid == 0) {         /* if pid == 0 in child process */
                    int vsave = v1;
                    switch (oper) { /* switch on operator, save result in v1 */
                        case '+':   v1 += v2; break;
                        case '-':   v1 -= v2; break;
                        case '*':   v1 *= v2; break;
                        case '/':   v1 /= v2; break;
                        default:    fputs ("error: invalid oper.\n", stderr);
                                    break;
                    }   /* output child PID with results of calculation */
                    printf ("PID %ld calculated %d%c%d as %d\n", 
                            (long)getpid(), vsave, oper, v2, v1);
                }
                else {      /* in the parent process */
                    do {    /* wait on child PID */
                        w = waitpid(pid, &status, WUNTRACED | WCONTINUED);
                        if (w == -1) {      /* validate waitpid return */
                            perror("waitpid");
                            exit (EXIT_FAILURE);
                        }
                    } while (!WIFEXITED(status) && !WIFSIGNALED(status));
                    exit (EXIT_SUCCESS);    /* child exited, exit parent */
                }
            }
            offset += nchar;    /* update offset with nchars read */
        }
        else {  /* read of int failed, must be oper or end */
            size_t used = strcspn (&line[offset], "+-*/");  /* chars to oper */
            offset += used;     /* update offset */
            if (line[offset] == '\n' || line[offset] == 0)  /* end of line? */
                break;
            oper = line[offset++];  /* set oper advance to next char */
        }
    }

    free (line);    /* don't forget to free line */
}

使用/输出示例

以相同的输入运行上述内容将在每次单独计算之前使用子PID产生相同的输出,例如

Running the above with the same input will produce the same output with the child PID before each individual calculation, e.g.

$ ./bin/calculate_fork
Enter equation: 3 + 4 / 7 + 4 * 2
PID 18746 calculated 3+4 as 7
PID 18747 calculated 7/7 as 1
PID 18748 calculated 1+4 as 5
PID 18749 calculated 5*2 as 10

试试看,如果您还有其他问题,请告诉我.

Give it a go and let me know if you have further questions.

这篇关于编写一个忽略操作顺序的C程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆