兩個問題,你不能保證一個空值終止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
單詞的順序,您將繼續難以解析單詞。
儘管可以執行指針運算來複制/展開/收縮原始字符串,而不管命令行中出現的單詞的順序如何,但將單詞提供到數組中的操作要簡單得多,然後比較每個不好的單詞與原始字符串中的每個單詞。
這可以用strtok
或strsep
相對容易地完成。我列舉了一個顯示這種方法的簡單例子。 (注意:在傳遞到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.
的'j'參數是多餘的。 – emlai 2015-03-18 21:43:46
你有兩種選擇:A)在調用'puts'前調用'main'中的'replace_str'多次,或者B)將'argc'和'argv'全部傳遞給'replace_str'。 – user3386109 2015-03-18 21:54:59
對getchar()的調用不會輸入命令行參數。但這似乎是代碼試圖做的事情。 – user3629249 2015-03-18 22:21:44