简体   繁体   English

多个命令行参数-替换单词

[英]Multiple Command-Line Arguments - Replace Words

I've a program which takes any number of words from the command-line arguments and replaces them with the word 'CENSORED'. 我有一个程序可以从命令行参数中提取任意数量的单词,并将其替换为“ CENSORED”一词。 I finally have the program working for the first argument passed in, and I am having trouble getting the program to censor all arguments, outputted in just a single string. 我终于让程序可以处理传入的第一个参数,而且我很难让程序检查仅在单个字符串中输出的所有参数。 The program rather functions individually on a given argument and does not take them all into account. 该程序宁可根据给定参数单独运行,也不会考虑所有因素。 How would I modify this? 我将如何修改呢?

How does one use/manipulate multiple command-line arguments collectively ? 一个人如何集体使用/操纵多个命令行参数?

My code follows. 我的代码如下。

#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.

Two issues, you are not guaranteeing a null-terminated str and second, you are not iterating over the words on the command line to censor each. 有两个问题,您不能保证以null结尾的str ,第二个问题是,您不能在命令行上的单词上进行迭代以检查每个单词。 Try the following in main after your getchar() loop: 在您的getchar()循环之后,在main中尝试以下操作:

/* 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 ) );
}

Note: that will place each of the CENSORED words on a separate line. 注意:这会将每个CENSORED单词放在单独的行上。 As noted in the comments, move puts (or preferably printf ) outside the loop to keep on a single line. 如注释中所述,将puts (或最好是printf )移到循环外以保持一行。


Edit 编辑

I apologize. 我道歉。 You have more issues than stated above. 您遇到的问题比上述更多。 Attempting to check the fix, it became apparent that you would continue to have difficulty parsing the words depending on the order the bad words were entered on the command line. 尝试检查此修复程序时,很显然,根据在命令行上输入bad单词的顺序,您仍然难以解析单词。

While it is possible to do the pointer arithmetic to copy/expand/contract the original string regardless of the order the words appear on the command line, it is far easier to simply separate the words provided into an array, and then compare each of the bad words against each word in the original string. 尽管可以执行指针算术来复制/扩展/压缩原始字符串,而不管单词在命令行上出现的顺序如何,但将提供的单词简单地分成一个数组,然后比较每个单词要容易得多。反对原始字符串中每个单词的坏单词。

This can be accomplished relatively easily with strtok or strsep . 这可以通过strtokstrsep相对容易地实现。 I put together a quick example showing this approach. 我整理了一个简单的示例来说明这种方法。 ( note: make a copy of the string before passing to strtok , as it will alter the original). 请注意:在传递给strtok之前,请先复制字符串,因为这会更改原始字符串)。 I believe this is what you were attempting to do, but you were stumbling on not having the ability to compare each word (thus your use of strstr to test for a match). 我相信这是您正在尝试做的事情,但是您因无法比较每个单词而绊绊(因此您使用strstr来测试匹配项)。

Look over the example and let me know if you have further questions. 查看示例,让我知道是否还有其他问题。 Note: I replaced your hardcoded 4096 with a SMAX define and provided a word max WMAX for words entered on the command line. 注意:我用SMAX定义替换了您的硬编码4096 ,并为在命令行上输入的单词提供了单词max WMAX Also always initialize your strings/buffers . 还请务必初始化您的字符串/缓冲区 It will enable you to always be able to easily find the last char in the buffer and ensure the buffer is always null-terminated. 这将使您始终能够轻松找到缓冲区中的最后一个字符,并确保缓冲区始终为空终止。

#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;
}

use/output 使用/输出

./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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM