2015-03-18 91 views
0

我有一個程序,它從命令行參數中取出任意數量的單詞,並用單詞'CENSORED'替換它們。我終於讓程序爲傳入的第一個參數工作,並且我無法讓程序檢查所有參數,只輸出一個字符串。該程序相對於給定的參數單獨運行,並沒有將它們全部考慮在內。我將如何修改?多個命令行參數 - 替換字

如何統一使用/操作多個命令行參數?

我的代碼如下。

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

char *replace_str(char *str, char *orig, char *rep, int j, int argc) 
{ 
    static char buffer[4096]; 
    char *p; 

    for (j = 1; j <= argc; j++) 
    { 

     if(!(p = strstr(str, orig))) // Check if 'orig' is not in 'str' 
     { 
      if (j == argc) { return str; } // return str once final argument is reached 
      else    { continue; } // restart loop with next argument 
     } 

     strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' str 
     buffer[p-str] = '\0'; 

     if (j == argc)  { return buffer; } 
     else     { continue;  } 
    } 
    sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); 
} 

int main(int argc, char* argv[]) //argv: list of arguments; array of char pointers //argc: # of arguments. 
{ 
    long unsigned int c, i = 0, j = 1; 

    char str[4096]; 

    while ((c = getchar()) != EOF) 
    { 
     str[i] = c; // save input string to variable 'str' 
     i++; 
    } 
    puts(replace_str(str, argv[j], "CENSORED", j, argc)); 

    return 0; 
} 


i.e. 
$ cat Hello.txt 

Hello, I am me. 

$ ./replace Hello me < Hello.txt 

CENSORED, I am CENSORED. 
+0

的'j'參數是多餘的。 – emlai 2015-03-18 21:43:46

+0

你有兩種選擇:A)在調用'puts'前調用'main'中的'replace_str'多次,或者B)將'argc'和'argv'全部傳遞給'replace_str'。 – user3386109 2015-03-18 21:54:59

+0

對getchar()的調用不會輸入命令行參數。但這似乎是代碼試圖做的事情。 – user3629249 2015-03-18 22:21:44

回答

1

兩個問題,你不能保證一個空值終止str和第二,你是不是遍歷的話在命令行御史每個。嘗試在主下面你getchar()循環後:

/* null-terminate str */ 
str[i] = 0; 

/* you must check each command line word (i.e. argv[j]) */ 
for (j = 1; j < argc; j++) 
{ 
    puts(replace_str(str, argv[j], "CENSORED", j, argc)); 
} 

注:,將各地方的截尾的話在單獨一行。正如評論中指出的那樣,將puts(或最好是printf)移到循環外部以保持單行。


編輯

我道歉。你有更多的問題比以上陳述。試圖檢查修復程序,很明顯,根據在命令行上輸入的bad單詞的順序,您將繼續難以解析單詞。

儘管可以執行指針運算來複制/展開/收縮原始字符串,而不管命令行中出現的單詞的順序如何,但將單詞提供到數組中的操作要簡單得多,然後比較每個不好的單詞與原始字符串中的每個單詞。

這可以用strtokstrsep相對容易地完成。我列舉了一個顯示這種方法的簡單例子。 (注意:在傳遞到strtok之前製作一個字符串的副本,因爲它會改變原始字體)。我相信這就是你想要做的事情,但你卻無法比較每個單詞(因此你使用strstr來測試比賽)。

查看示例並讓我知道您是否還有其他問題。注意:我用SMAX定義替換了您的硬編碼4096,並在命令行中輸入了單詞max WMAX總是初始化您的字符串/緩衝區。它將使您始終能夠輕鬆地找到緩衝區中的最後一個字符,並確保緩衝區始終以空字符結尾。

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

#define SMAX 4096 
#define WMAX 50 

char *replace_str (char *str, char **bad, char *rep) 
{ 
    static char buffer[SMAX] = {0}; 
    char *p = buffer; 
    char *wp = NULL; 
    unsigned i = 0; 
    unsigned char censored = 0; 

    char *str2 = strdup (str);    /* make copy of string for strtok */ 
    char *savp = str2;      /* and save start address to free */ 

    if (!(wp = strtok (str2, " ")))   /* get first word in string or bail */ 
    { 
     if (savp) free (savp);   
     return str; 
    } 

    while (bad[i])       /* test against each bad word  */ 
    { 
     if (strcmp (wp, bad[i++]) == 0)  /* if matched, copy rep to buffer */ 
     { 
      memcpy (buffer, rep, strlen (rep)); 
      censored = 1; 
     } 
    } 

    if (!censored)       /* if no match, copy original word */ 
     memcpy (buffer, wp, strlen (wp)); 

    while ((wp = strtok (NULL, " ")))  /* repeat for each word in str  */ 
    { 
     i = 0; 
     censored = 0; 

     memcpy (strchr (buffer, 0), " ", 1); 
     p = strchr (buffer, 0);    /* (get address of null-term char) */ 

     while (bad[i]) 
     { 
      if (strcmp (wp, bad[i++]) == 0) 
      { 
       memcpy (p, rep, strlen (rep)); 
       censored = 1; 
      } 
     } 

     if (!censored) 
      memcpy (p, wp, strlen (wp)); 
    } 

    if (savp) free (savp);     /* free copy of strtok string  */ 
    return buffer; 
} 

int main (int argc, char** argv) 
{ 
    unsigned int i = 0; 
    char str[SMAX] = {0}; 
    char *badwords[WMAX] = {0};    /* array to hold command line words */ 

    for (i = 1; i < argc; i++)    /* save command line in array  */ 
     badwords[i-1] = strdup (argv[i]); 

    i = 0;         /* print out the censored words  */ 
    printf ("\nCensor words:"); 
    while (badwords[i]) 
     printf (" %s", badwords[i++]); 
    printf ("\n\n"); 

    printf ("Enter string: ");    /* promt to enter string to censor */ 

    if (fgets (str, SMAX-1, stdin) == NULL) 
    { 
     fprintf (stderr, "error: failed to read str from stdin\n"); 
     return 1; 
    } 

    str[strlen (str) - 1] = 0;    /* strip linefeed from input str */ 

    /* print out censored string */ 
    printf ("\ncensored str: %s\n\n", replace_str (str, badwords, "CENSORED")); 

    i = 0;         /* free all allocated memory  */ 
    while (badwords[i]) 
     free (badwords[i++]); 

    return 0; 
} 

使用/輸出

./bin/censorw bad realbad 

Censor words: bad realbad 

Enter string: It is not nice to say bad or realbad words. 

censored str: It is not nice to say CENSORED or CENSORED words.