2016-11-15 24 views
1

我想分割一個字符串到標記來創建一個參數參數的數組。我目前的執行情況如下(path是通向用戶的可執行文件正在被讀取的可選參數):將字符串解析爲C中的標記 - 發生了什麼問題?

// ARG_MAX as defined in limits.h 
int execute(char *exe) { 
    printf("args to %s: ", exe); 

    char *args = malloc(ARG_MAX); 
    scanf("%s", args); 

    char *argv[ARG_MAX]; 

    int i = 0; 
    argv[i++] = exe; 

    while ((argv[i] = strsep(&args, " \t")) != NULL) { 
     i++; 
    } 

    free(args); 
    execv(exe, argv); 
    return 0; 
} 

什麼困惑我是從我的strsep理解爲預期這應該是工作,並且它在某種程度上在測試時準確地將tokens[0]分配爲pathtokens[1]爲什麼tokens_s直到第一個空格字符爲止。

但是,如果在輸入另一個參數後出現空格,則不會將其分配到tokens[2]等等中以用於後續參數。

當我使用strsep時,我似乎無法發現它是我做錯了什麼,而不會導致所需的功能?

輸入: exe = "/usr/bin/ps" args = "-e -l"

輸出: exec ps -e

+0

'的scanf( 「%S」,參數);'不保存''\ t''也不空格放入'args'。使用'fgets()'。建議張貼您使用的輸入。 – chux

+0

已添加輸入。已嘗試使用'fgets()',但在提示我在命令行輸入參數的地方,它只是繼續而不提示? – transiti0nary

+0

由於這篇文章缺少完整的可編譯代碼,它只是讓它比需要幫助更難。添加'fgets()'可能是一個問題,因爲其他代碼仍在使用'scanf()'。強烈建議發佈一個完整的最小代碼來顯示問題。 – chux

回答

3

多個錯誤:

  • 您必須閱讀fgets()參數讀取多個字。

  • 您必須使用strsep()的臨時變量,以便您可以將原始指針從malloc()返回到free(),或者只需使用本地數組。

這裏是一個修正版本:

#include <errno.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <limits.h> 

// ARG_MAX as defined in limits.h 
int execute(char *exe) { 
    char args[ARG_MAX + 1]; 

    printf("args to %s: ", exe); 
    fflush(stdout); 
    if (fgets(args, sizeof args, stdin)) { 
     char *argv[ARG_MAX/2]; 
     char *p; 

     int i = 0; 
     argv[i++] = exe; 

     p = args; 
     args[strcspn(args, "\n")] = '\0'; // strip the newline if present 
     while ((argv[i] = strsep(&p, " \t")) != NULL) { 
      i++; 
     } 

     printf("argv: "); 
     for (i = 0; argv[i]; i++) 
      printf(" '%s'", argv[i]); 
     printf("\n"); 

     execv(exe, argv); 
     printf("exec failed: %s\n", strerror(errno)); 
    } else { 
     printf("cannot read input\n"); 
    } 
    return 0; 
} 

int main(int argc, char *argv[]) { 
    char *exe = "printf"; 
    if (argc > 1) 
     exe = argv[1]; 
    return execute(exe); 
} 

注:如果成功

  • execv不會返回到您的程序。

  • strsep不會摺疊分隔符序列,如果您有多餘的空格,您的方法將創建額外的參數。

編輯:如果輸入從stdin讀取之前你運行execute,如果用電話進行到scanf()這樣的輸入,有可能是在stdin緩衝掛起換行,fgets()會讀它作爲一個空行。如果是這樣的情況下,首先調用printf()之前沖洗掛起的輸入:

int c; 
while ((c = getchar()) != EOF && c != '\n') { 
    continue; 
} 
+0

謝謝,它有助於如何正確實施,但''參數%s「,exe永遠不會被打印到控制檯,而是程序執行時沒有參數與此代碼? 這是我一直試圖使用'fgets()'和'getline()'的問題。 在我上面的原始代碼中,它仍然會打印提示符並執行,但只識別第一個參數 – transiti0nary

+0

@ transiti0nary:如果添加'fflush(stdout);',是否打印提示符?你確定你可以從標準輸入中讀取嗎?我更新了我的答案,使失敗更加明確。 – chqrlie

+0

是的,提示現在打印,但它仍然不停止輸入,只是運行沒有參數的exec – transiti0nary