[英]C program to remove all occurrences of a WORD in string
我的代码的 output 不正确。 比如我输入“joy is joyful”,然后想去掉“joy”这个词,output应该是“isjoyful”,而output与输入相同。
这是完整的代码:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void print(char string[100]);
main()
{
char string[100], remove[100];
int stringLen, removeLen, i, j, k, l, count, location, sLen, ij, counter = 0;
printf("Enter any string: ");
gets(string);
printf("Enter word to remove: ");
gets(remove);
printf("\nString before removing '%s': ", remove);
print(string);
stringLen = strlen(string);
sLen = stringLen;
removeLen = strlen(remove);
for(i=0; i<stringLen; i++)
{
count = 0;
for(j=0; j<removeLen; j++)
{
if(string[i+j] == remove[j])
{
count++;
location = i;
ij = i+j;
}
}
if(count == removeLen)
{
if(string[ij+1] == '\0' && string[ij+1] == ' ' && string[ij+1] == '\n')
{
counter = count;
}
else
{
counter = count - 1;
}
}
if(counter == removeLen)
{
for(l=0; l<count; l++)
{
for(k=location; k<sLen; k++)
{
string[k] = string[k+1];
}
sLen--;
}
}
}
printf("\n\nString after removing '%s':", remove);
print(string);
getch();
return 0;
}
void print(char string[100])
{
printf("\n%s", string);
}
我尝试制作这部分:
if(count == removeLen)
{
if(string[ij+1] == '\0' && string[ij+1] == ' ' && string[ij+1] == '\n')
{
counter = count;
}
else
{
counter = count - 1;
}
}
为此,它奏效了:
if(count == removeLen)
{
if(string[ij+1] != '\0' && string[ij+1] != ' ' && string[ij+1] != '\n')
{
counter = count - 1;
}
else
{
counter = count;
}
}
原版好像有什么问题?
对于 pf all, never, ever, EVER,使用gets()
。 它很容易被从 C11 开始的 C 库中删除的缓冲区溢出利用。 有关更多讨论,请参阅: 为什么 gets() 如此危险,永远不应该使用!
在您的单词替换中,您不必担心在您删除的单词之前或之后删除前导或尾随空格,并且仅当它不是较大单词中的 ZE83AED3DDF4667DEC0DAAAACB2BB3BE0BZ 或后跟标点符号的单词时才删除该单词。 (这很好——但在隔离删除词时,您通常需要考虑剩下的内容)
您可以简化您尝试做的事情,并将完整的算法简化为对字符串中字符的单个循环。 您只需保留三个索引(或计数器,如果您想这样想的话)。 您需要一个read-index ,即要读取的下一个字符。 您需要一个write-index ,即要写入的字符串中的下一个位置。 最后,您需要删除 substring 中要删除的字符的删除索引。
在这里,您只需使用您的读取索引遍历字符串中的字符。 您的读取和写入索引开始相同。 如果某个字母与您的 remove substring 中的第一个字母匹配,则增加您的 remove-index 并再次循环。 如果字符序列与您删除的 substring 中的所有字符匹配,则在下一次迭代中,您的 substring 索引将位于其nul 终止字符。
现在您可以测试字符串中读取索引下的下一个字符是否为空格(使用isspace()
宏)或测试您是否位于原始字符串的末尾。 如果任一情况为真,您只需从写入索引中减去 substring 长度并继续 - 有效地从原始字符串中删除 substring。 不需要多循环,您实际上是在使用 substring 索引跟踪您所在位置(状态)的原始字符的每个字符。
以这种方式接近它的一个简短示例可能如下所示。 function remove_substr()
,读取str
中的字符并删除其中每个孤立的substr
出现,就地更新原始str
:
int remove_substr (char *str, const char *substr)
{
if (!strstr (str, substr)) /* if substr not found in str */
return 0; /* return 0 - nothing replaced */
size_t sslen = strlen (substr), /* length of substr */
i = 0, j = 0, n = 0; /* read, write, substr indexes */
do { /* loop over str (including '\0') */
if (!substr[n]) { /* substr found (at substr '\0') */
/* if at end of str or whitespace */
if (!str[i] || isspace((unsigned char)str[i]))
j -= sslen; /* subtract sslen from write index */
n = 0; /* reset substr index */
}
str[j++] = str[i]; /* copy from read to write index */
if (str[i] == substr[n]) /* if char matches substr */
n++; /* increment substr counter */
} while (str[i++]); /* exit after '\0' processed */
return 1; /* return replacements made */
}
为返回类型选择了一个简单类型int
以指示0
未发生删除,或1
指示从str
中删除了substr
的出现。
调用 function 的简短示例可能是:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXC 1024
/* insert function here */
int main (void) {
char str[MAXC] = "", /* storage for string */
substr[MAXC] = ""; /* storage for substring */
fputs ("enter string: ", stdout); /* prompt for string */
if (!fgets (str, sizeof str, stdin)) /* read/validate input */
return 1;
str[strcspn(str, "\n")] = 0; /* overwrite '\n' with '\0' */
fputs ("enter substr: ", stdout); /* ditto for substr */
if (!fgets (substr, sizeof substr, stdin))
return 1;
substr[strcspn(substr, "\n")] = 0;
if (remove_substr (str, substr)) /* remove all substr in str */
printf ("\nresult: '%s'\n", str); /* output updated str if removals */
else
puts ("\nno replacements made"); /* otherwise output no replacements */
}
只需运行程序,系统将提示您输入字符串和 substring 以删除。 目前使用的每个字符串都限制为MAXC
( 1024
个字符),请根据您的需要进行调整——但不要吝啬缓冲区大小。
示例使用/输出
$ ./bin/str_rm_substr
enter string: joy is joyful
enter substr: joy
result: ' is joyful'
一个更复杂的例子:
$ ./bin/str_rm_substr
enter string: joy is joyful, joy is full of joy
enter substr: joy
result: ' is joyful, is full of '
有很多方法可以像这样编写 function。 您可以使用strtok()
的组合来标记原始字符串的副本,检查每个标记是否与要删除的substr
匹配。 您可以使用多个循环来细化字符串以向前扫描以查找substr
中的第一个字母,然后循环以查看它是否匹配。 您还可以使用strspn()
和strcspn()
的组合来执行相同的英寸蠕虫技术,让那些 function 为您处理循环。 可能有 1/2 打左右的有效方法。
看看事情,如果你有问题,请告诉我。
这里
if(string[ij+1] == '\0' && string[ij+1] == ' '
您测试一个字符是否既是nul又是空格。
那永远不会是真的。 换句话说,整个 if 语句是无用的,因为它总是采用错误的路径。
在这种情况下,问题在于if(string[ij+1] == '\0' && string[ij+1] == ' ' && string[ij+1] == '\n')
并且计数器减少。 所以在减少之后你永远不会进入这个代码:
if(counter == removeLen)
{
for(l=0; l<count; l++)
{
for(k=location; k<sLen; k++)
{
string[k] = string[k+1];
}
sLen--;
}
}
所以删除这段代码:
if(count == removeLen)
{
if(string[ij+1] == '\0' && string[ij+1] == ' ' && string[ij+1] == '\n')
{
counter = count;
}
else
{
counter = count - 1;
}
}
这将是工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.