我想编写一个C程序,该程序可以解决用户的简单数学问题,并使用不同的过程来解决每个部分,然后将值发送回父过程。该程序不应注意操作顺序。例如,如果我有问题:
3 + 4 / 7 + 4 * 2
我希望我的程序输出以下内容:
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()
方法来帮助我解析输入。这是我到目前为止所拥有的:
#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()
。预先谢谢大家。
捕获了最终数据点的“ robustified”附加项可能类似于以下内容(有意使用整数数学,如果需要,请更改为浮点数:)]]
您已经分配了#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 */ }
([note:
malloc
,甚至没有直接分配,如果line = NULL;
和n = 0;
getline
会自己分配足够的空间,所以请不要忘记[ C0]释放已分配的内存(是的,这是在退出时发生的,但是希望您编写的程序中使用free(line);
的程序要多于getline
,所以现在要养成良好的习惯...)上面使用main()
说明符将"%n"
消耗的字符数放入sscanf
变量中,然后将其用于更新nchars
中的offset
。
示例使用/输出
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()
和v1, v2
之后,才需要进行以下更改:先进行oper
进程,然后在子级中然后在父级fork()
中处理switch()
语句,直到子级退出之前退出并获取下一组值。如我的评论所示,wait()
中的示例为该过程提供了一个很好的概述。
根据您的评论,您在man 2 wait
调用成功后将fork()
设置在正确的位置。您要做的就是将调用添加到sscanf
,并进行确认和确定哪个是子代和父代。然后将现有的计算移到子进程中,并添加对fork()
的调用以添加到您的输出中。在父进程中,将您的getpid()
放置在位,然后在孩子完成操作后退出。
您可以实施以下更改以进行上述更改:
wait()
完整的示例只是添加了所需的头文件,而其余的代码则保持不变。例如:
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 */ }
示例使用/输出
例如,在每次进行单独计算之前,使用相同的输入运行上述操作将与子PID产生相同的输出
#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 */ }
试一下,如果您还有其他问题,请告诉我。
这不能完全回答问题,但是是一个有趣的小玩具。这不能处理最终数据点,并且无疑需要进行鲁棒化(“ robustification”一词吗?应该是!)。作为读者的练习,重构代码以处理最终输出,并处理非整数值。