Remove a word from a sentence (string)

时间:2018-02-03 11:01:53

标签: c

I am in the stage of preparing myself for exams, and the thing that I m least proud of are my skills with strings. What I need to do is remove a word from a sentence, without using <string.h> library at all. This is what I've got so far. It keeps showing me that certain variables are not declared, such as start and end.

#include <stdio.h>

/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
    int counter = 0;
    while (*s++) {
        counter++;
        s--;
    return counter;
}

/* Function to remove a word from a sentence */
char *remove_word(const char *s1, const char *s2) {
    int counter2 = 0;
    /* We must remember where the string started */
    const char *toReturn = s1;
    /* Trigger for removing the word */
    int found = 1;
    /* First we need to find the word we wish to remove [Don't want to
      use string.h library for anything associated with the task */
    while (*s1 != '\0') {
        const char *p = s1;
        const char *q = s2;
        if (*p == *q) 
           const char *start = p;
        while (*p++ == *q++) {
            counter2++;
            if (*q != '\0' && counter2 < count(s2))
                found = 0;
            else {
                const char *end = q;
            }
        }
        /* Rewriting the end of a sentence to the beginning of the found word */
        if (found) {
            while (*start++ = *end++)
               ;
        }
        s1++;
    }
    return toReturn;
}

void insert(char niz[], int size) {
    char character = getchar();
    if (character == '\n')
        character = getchar();
    int i = 0;
    while (i < size - 1 && character != '\n') {
        array[i] = character;
        i++;
        character = getchar();
    }
    array[i] = '\0';
}

int main() {
    char stringFirst[100];
    char stringSecond[20];

    printf("Type your text here: [NOT MORE THAN 100 CHARACTERS]\n");
    insert(stringFirst, 100);
    printf("\nInsert the word you wish to remove from your text.");
    insert(stringSecond, 20);
    printf("\nAfter removing the word, the text looks like this now: %s", stringFirst);

    return 0;
}

4 个答案:

答案 0 :(得分:1)

您的代码格式错误,我强烈建议您编译: gcc -ansi -Wall -pedantic -Werror -D_DEBUG -g(或类似)

  • 首先在功能块的开头声明变量,它们只在声明它们的块中知道。

  • 您的计数功能有问题,错过了关闭&#39;}&#39; (它没有编译) 应该像

    size_t Strlen(const char *s)
    {
        size_t size = 0;
        for (; *s != '\n'; ++s, ++size)
        {}
        return size;
    }
    
  • 实现memmove比使用char

  • 复制char要高效得多

答案 1 :(得分:0)

您的startend指针是在一个块中定义的,这使得它们的范围受限于该块。因此,它们对代码的其他部分不可见,如果您尝试在其范围之外引用它们,编译器将抱怨并抛出错误。您应该在功能块的开头声明它们。

尽管如此,请考虑以下方法从字符串中删除单词:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int delete_word(char *buf,
    const char *word);


int main(void)
{
    const char word_to_delete[] = "boy";

    fputs("Enter string: ", stdout);

    char buf[256];
    fgets(buf, sizeof(buf), stdin);

    if (delete_word(buf, word_to_delete)) 
    {
        printf("Word %s deleted from buf: ", word_to_delete);
        puts(buf);
    }
    else 
    {
        printf("Word %s not found in buf: ", word_to_delete);
        puts(buf);
    }

    system("PAUSE");
    return 0;
}


int chDelimit(int ch)
{
    return
        (ch == '\n' || ch == '\t') ||
        (ch >= ' ' && ch <= '/') ||
        (ch >= ':' && ch <= '@') ||
        (ch >= '[' && ch <= '`') ||
        (ch >= '{' && ch <= '~') ||
        (ch == '\0');
}

char *find_pattern(char *buf,
    const char *pattern)
{
    size_t n = 0;
    while (*buf)
    {
        while (buf[n] && pattern[n])
        {
            if (buf[n] != pattern[n])
            {
                break;
            }
            n++;
        }
        if (!pattern[n])
        {
            return buf;
        }
        else if (!*buf)
        {
            return NULL;
        }
        n = 0;
        buf++;
    }
    return NULL;
}

char *find_word(char *buf,
    const char *word)
{
    char *ptr;
    size_t wlen;

    wlen = strlen(word);
    ptr = find_pattern(buf, word);

    if (!ptr)
    {
        return NULL;
    }
    else if (ptr == buf)
    {
        if (chDelimit(buf[wlen]))
        {
            return ptr;
        }
    }
    else
    {
        if (chDelimit(ptr[-1]) &&
            chDelimit(ptr[wlen]))
        {
            return ptr;
        }
    }

    ptr += wlen;
    ptr = find_pattern(ptr, word);
    while (ptr)
    {
        if (chDelimit(ptr[-1]) &&
            chDelimit(ptr[wlen]))
        {
            return ptr;
        }
        ptr += wlen;
        ptr = find_pattern(ptr, word);
    }
    return NULL;
}

int delete_word(char *buf,
    const char *word)
{
    size_t n;
    size_t wlen;

    char *tmp;
    char *ptr;

    wlen = strlen(word);
    ptr = find_word(buf, word);

    if (!ptr) 
    {
        return 0;
    }
    else 
    {
        n = ptr - buf;
        tmp = ptr + wlen;
    }

    ptr = find_word(tmp, word);
    while (ptr)
    {
        while (tmp < ptr)
        {
            buf[n++] = *tmp++;
        }
        tmp = ptr + wlen;
        ptr = find_word(tmp, word);
    }
    strcpy(buf + n, tmp);
    return 1;
}

答案 2 :(得分:0)

我将代码重新格式化为小缩进问题,实际上缩进问题表明存在实际问题:

  • }中缺少count。它应该是:

    /* Side function to count the number of letters of the word we wish to remove */
    int count(char *s) {
        int counter = 0;
        while (*s++) {
            counter++;
        }
        return counter;
    }
    

    或更好:

    /* Side function to count the number of letters of the word we wish to remove */
    int count(const char *s) {
        const char *s0 = s;
        while (*s++) {
            continue;
        }
        return s - s0;
    }
    

    此函数计算字符串中的字节数,这是strlen的几乎完全克隆,但返回类型int而不是size_t除外。另请注意,您实际上并不使用也不需要此功能。

  • 您的函数insert无法正常处理EOF并拒绝空行。为什么不用fgets()读取一行并手动删除换行符:

    char *input(char buf[], size_t size) {
         size_t i;
         if (!fgets(buf, size, stdin))
             return NULL;
         for (i = 0; buf[i]; i++) {
             if (buf[i] == '\n') {
                 buf[i] = '\0';
                 break;
             }
        }
        return buf;
    }
    
  • 在函数remove_word中,您应该定义范围更大的startend,通常是外部while循环的正文。此外,s1应该有char *类型,而不是const char *,因为短语会在适当的位置进行修改。

  • 如果测试成功,您应该只增加pq,并且应该检查pq是否都不在其字符串的末尾

  • 最后但并非最不重要:您未在remove_word函数中致电main

完整的代码可以简化为:

#include <stdio.h>

/* Function to remove a word from a sentence */
char *remove_word(char *s1, const char *s2) {
    if (*s2 != '\0') {
        char *dst, *src, *p;
        const char *q;
        dst = src = s1;
        while (*src != '\0') {
            for (p = src, q = s2; *q != '\0' && *p == *q; p++, q++)
                continue;
            if (*q == '\0') {
                src = p;   /* the word was found, skip it */
            } else {
                *dst++ = *src++;  /* otherwise, copy this character */
            }
        }
        *dst = '\0';  /* put the null terminator if the string was shortened */
    }
    return s1;
}

char *input(char buf[], size_t size) {
     size_t i;
     if (!fgets(buf, size, stdin))
         return NULL;
     for (i = 0; buf[i]; i++) {
         if (buf[i] == '\n') {
             buf[i] = '\0';
             break;
         }
    }
    return buf;
}

int main() {
    char stringFirst[102];
    char stringSecond[22];

    printf("Type your text here, up to 100 characters:\n");
    if (!input(stringFirst, sizeof stringFirst))
        return 1;

    printf("\nInsert the word you wish to remove from your text: ");
    if (!input(stringSecond, sizeof stringSecond))
        return 1;

    printf("\nAfter removing the word, the text looks like this now: %s\n",
           remove_word(stringFirst, stringSecond));

    return 0;
}

答案 3 :(得分:-1)

如果你必须手动完成,只需循环遍历你的字符串的标记,找到第一个匹配的字符,然后你将有第二个循环循环播放所有其他匹配并重置所有字符串并跳转到第一个循环的下一个索引,如果没有匹配则继续搜索。如果我再次记得,C中的所有字符串都可以像数组一样访问,你必须弄清楚如何。不要害怕,那些原则很容易! C是一个简单的langugae,写得很长。

为了删除:将第一部分存储在一个数组中,将第二部分存储在一个数组中,为它们分配一个新空间并在那里连接它们。

谢谢,点击upvote按钮。 维塔利

编辑:使用\ 0来终止新创建的字符串。