2015-03-18 89 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.