我正在尝试从stdin中读取用于堆栈数据结构的命令,有效的命令是“ push [number]”和“ pop”,这是我的代码:
while(getline(&input, &len, stdin) > 0){
while ((n = sscanf(input,"%64s%d%n",cmd,&num,&offset)) > 0){
if (n == 1){
if (!strcmp("pop",cmd)){
pop(&head);
} else if (!strcmp("push",cmd)){
//Doing something
} else if (isNumeric(cmd) && need_num){
push(&head, num);
} else{
//error
}
}
else if (n == 2){
if (!strcmp("push",cmd)){
push(&head, num);
} else {
//error
}
}
else {
//error
}
input += offset;
}
}
该程序当然有很多缺陷,因为我对带循环的sscanf并不熟悉。第一个问题是,如果我在一行中读取了一系列命令,例如:
push 1 push 2 pop push 3
这实际上会导致错误,因为在push之后有数字,但在pop之后没有数字,因此,这行代码对于“ pop”命令是错误的:
input += offset;
但是我不知道该如何解决。 另一个问题是,如果我假设将“ push [number]”命令分为两行,则可以接受:
push 5 pop push
4
除了确定行是否以push结尾以及以下行以数字开头之外,我不知道有没有其他简便的方法:
else if (!strcmp("push",cmd)){
//Doing something
} else if (isNumeric(cmd) && need_num){
push(&head, num);
}
任何帮助将不胜感激!
答案 0 :(得分:2)
您的使用中没有明显的错误,但是有许多细微的错误导致您遇到问题。
您面临的主要问题是在转换字符串和整数之后仅获得一个偏移量。对于"pop"
,在您到达格式字符串中的%d
之前,%n
之前发生匹配失败 导致n
保持未设置状态(保留最后一个设置值-在这种情况下,导致offset
的增量太大)
相反,您需要在格式字符串中使用两个此类检查,例如:
while ((rtn = sscanf (input, "%63s %n%d %n",
cmd, &off1, &num, &off2)) > 0) {
这样,如果读取"pop"
,则在off1
中具有适当的偏移量;如果读取"push num"
,则在off2
中具有适当的偏移量。 (每个%n
之前的附加空格是可选的(但建议)。同时使用%s
和%d
时,会消耗前导空格-但最好养成对其进行处理的习惯,因为%[...]
或%c
不消耗领先的空白。
在一个简短的示例中将其放在一起,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCMD 64 /* max characters for command */
int main (void) {
char *buf = NULL; /* buffer for getline */
size_t n = 0; /* alloc size (0 getline decides) */
ssize_t nchr = 0; /* getline returns (no. of chars read */
while ((nchr = getline (&buf, &n, stdin)) > 0) { /* read each line */
char cmd[MAXCMD] = "", /* buffer for command */
*input = buf; /* pointer to advance */
int num = 0, /* number to push */
off1 = 0, /* offset if single conversion */
off2 = 0, /* offset if double conversion */
rtn = 0; /* sscanf return */
while ((rtn = sscanf (input, "%63s %n%d %n",
cmd, &off1, &num, &off2)) > 0) {
switch (rtn) { /* switch on sscanf return */
case 1: /* handle "pop" case */
if (strcmp (cmd, "pop") == 0) {
printf ("pop\n");
input += off1; /* set offset based on off1 */
}
else
fprintf (stderr, "error: invalid single cmd '%s'.\n",
cmd);
break;
case 2: /* handle "push num" case */
if (strcmp (cmd, "push") == 0) {
printf ("push %d\n", num);
input += off2; /* set offset based on off2 */
}
else
fprintf (stderr, "error: invalid single cmd '%s'.\n",
cmd);
break;
default:
fprintf (stderr, "error: invalid input.\n");
break;
}
}
}
free (buf); /* free memory allocated by getline */
return 0;
}
(注意:我使用了switch()
语句,但您可以随意使用if, else if, else
)
使用/输出示例
验证案例:
$ echo "pop pop push 1 push 2 pop push 3 pop" | ./bin/sscanfpushpop
pop
pop
push 1
push 2
pop
push 3
pop
$ echo "push 5 pop push 6 push 7 pop push 8" | ./bin/sscanfpushpop
push 5
pop
push 6
push 7
pop
push 8
仔细检查一下,如果还有其他问题,请告诉我。
答案 1 :(得分:0)
如果大小恒定,则可以在" "
或char **
中用char tab[][]
作为分隔符来分隔行。
然后,您将检查tab[i]
是否为数字,然后根据需要使用它,或者如果命令(tab[i+1])
后跟数字,则该命令将为«push»,否则为«pop»»