2016-08-21 32 views
0

用C編寫這個程序。使用兩個堆棧實現隊列(CTCI中的問題3.5)。通過推送和彈出對scanf的不同期望

我想讓用戶輸入「push {integer}」或「pop」。我正在使用scanf("%s %d", op, &data);

但是,這會導致程序中的行爲不一致,其中用戶輸入「push {integer}」正常工作,但用戶輸入「pop」會導致程序執行延遲。似乎scanf("%s %d", op, &data);等待一些輸入到&數據,但我希望它只接受「流行」沒有任何數據。

代碼:

#include "stdio.h" 
#include "stdlib.h" 
#include "../Chapter-2/linkedlist.h" 
#include "string.h" 

int main(int argc, char *argv[]) 
{ 
    char op[10]; 
    int data; 
    struct node *pushStack = NULL; 
    struct node *popStack = NULL; 

    printf("Usage: \"push\" some_int ||OR|| \"pop\"\n"); 
    while(1) 
    { 
     scanf("%s %d", op, &data); 
     if(strncmp(op, "push", 4) == 0) 
     { 
      if(pushStack == NULL) 
      { 
       if(popStack != NULL) //we were popping from the "queue" so we need to switch to pushing mode 
       { 
        while(popStack != NULL) //transfer all from popstack to pushstack 
        { 
         push(&pushStack, pop(&popStack)); 
        } 
       } 
      } 
      push(&pushStack, data); 
     } else if(strncmp(op, "pop", 3) == 0) 
     { 
      if(popStack == NULL) 
      { 
       if(pushStack != NULL) //we were pushing to "queue" so we need to switch to pop mode 
       { 
        while(pushStack != NULL) // transfer all from pushStack to popStack 
        { 
         push(&popStack, pop(&pushStack)); 
        } 
       } 
      } 
      if(popStack == NULL) //could still be null if there was nothing to transfer from pushstack 
       printf("Queue is empty. You have nothing to pop.\n"); 
      else 
       printf("Popped queue: %d\n", pop(&popStack)); 
     } else { 
      printf("Invalid usage.\n"); 
      printf("Usage: \"push\" some_int ||OR|| \"pop\"\n"); 
     } 
    } 
    return 0; 
} 
+3

我建議你用'fgets'獲取輸入。然後應用'sscanf'並檢查返回值(轉換字段的數量,在所有**情況下的*必需*測試)。如果收到「pop」,沒有第二個參數,你可以更容易地轉儲輸入字符串,而不是忽略不滿意的'scanf'格式字段,它們是持久的。與'scanf'不同,字符串函數'sscanf'不等待更多信息。 –

+2

另外:標準庫頭文件應該包含在'while #include <#include 中,while'(1!= scanf(「%9s」,op))''while''include #include <#include> stdio.h'' –

回答

2

你可以嘗試將scanf成兩個呼叫取決於命令拆分。喜歡的東西:

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

int main(int argc, char *argv[]) 
{ 
    char op[10]; 
    int data; 
    int t = 3; 
    int res; 

    printf("Usage: \"push\" some_int ||OR|| \"pop\"\n"); 
    while(t) 
    { 
     res = scanf("%9s", op); // Read the command 
     if (res == EOF) exit(1); 

     if(strncmp(op, "push", 4) == 0) 
     { 
      do 
      { 
       res = scanf("%d", &data); // Read data only when command is push 
       if (res == EOF) exit(1); 
       if (res != 1) 
        while ((res = getchar()) != '\n' && res != EOF); // Flush stdin 
      } while (res != 1); 

      printf("%s %d\n", op, data); 
     } 
     else if(strncmp(op, "pop", 3) == 0) 
     { 
      printf("%s\n", op); 
     } 
     else 
     { 
      printf("Invalid usage.\n"); 
      printf("Usage: \"push\" some_int ||OR|| \"pop\"\n"); 
     } 
     --t; 
    } 
    return 0; 
} 

輸入

push 7 
pop 
push 42 

輸出

Usage: "push" some_int ||OR|| "pop" 
push 7 
pop 
push 42 

BTW:

經常檢查scanf函數

決不返回值做的scanf(%s的....

作爲替代scanf你可以使用fgets。例如:

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

int main(int argc, char *argv[]) 
{ 
    char op[10]; 
    int data; 
    int t = 3; 

    printf("Usage: \"push\" some_int ||OR|| \"pop\"\n"); 
    while(t) 
    { 
     if (fgets(op, 10, stdin) == NULL) exit(1); 

     if(sscanf(op, "push %d", &data) == 1) 
     { 
      printf("push %d\n", data); 
     } 
     else if(strncmp(op, "pop", 3) == 0) 
     { 
      printf("pop\n"); 
     } 
     else 
     { 
      printf("Invalid usage.\n"); 
      printf("Usage: \"push\" some_int ||OR|| \"pop\"\n"); 
     } 
     --t; 
    } 
    return 0; 
} 
+0

'看起來像一個潛在的無限循環,如果stdin被關閉。 'while'有什麼用處? – chux

+1

@chux - well ...'while'的使用是爲了確保'op'在使用之前被初始化。但是這並不需要format'%9s'(但是格式爲'%d')。另外缺少的EOF檢查使代碼有點草率。感謝您指出了這一點。我試圖改進代碼。 – 4386427