繁体   English   中英

C 程序删除字符串中所有出现的 WORD

[英]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 以删除。 目前使用的每个字符串都限制为MAXC1024个字符),请根据您的需要进行调整——但不要吝啬缓冲区大小。

示例使用/输出

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

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