如何从char数组中删除特定的单词?

时间:2016-11-13 09:33:10

标签: c

所以我的任务是从char数组删除这些以相同字母开头和结尾的单词。此时我的程序崩溃了。 这是我的功能:

void RemoveSame(char * start) {
  int i, j, first, last, k;
  for (i = 1; i < LINE_LENGTH; i++) {
    if ( * (start + i) != ' ') {
      first = * (start + i);
      for (j = i; j < LINE_LENGTH; j++) {
        if ( * (start + i + j + 1) == ' ') {
          last = * (start + i + j);
        } else {
          break;
        }
      }

    }
    for (; i != j; i++) {
      k = j - i; 
      * (start + k) = "\0";
    }
  }
}

这是我的完整代码http://pasted.co/22566eb6

4 个答案:

答案 0 :(得分:1)

正如其他人所说:

* (start + i)更改为start[i]可提高可读性

"\0"应该是'\0'或者只是0 - 在c中,双引号用于表示字符串,而字符串实际上是内存地址。

数组索引从0开始

还要记住,源代码中明确写入的字符串(例如:“abcba this is a string”)是常量字符串(const char *),必须复制到其他位置才能修改它们。

void RemoveSame(char * start) {
    int i, j, k;

    for (i = 0; start[i];) { // advance while haven't reached the string's end
        if (start[i] != ' ') {
            for (j = i + 1; ; ++j) {
                if (start[j] == ' ' || !start[j]) { // advance until I find a word
                    if (start[i] == start[j - 1]) {
                        for (k = i; (start[k] = start[k + j - i]); ++k); // delete word
                    }
                    else {
                        i = j;
                    }
                    break;
                }
            }
        }
        else {
            ++i;
        }
    }
}

答案 1 :(得分:1)

对于初学者来说,代码格式太差,很难理解它的作用。

目前尚不清楚为什么外环从1开始。 内环

  for (j = i; j < LINE_LENGTH; j++) {
    if ( * (start + i + j + 1) == ' ') {
      last = * (start + i + j);
    } else {
      break;
    }
  }

没有任何意义。

此循环

for (; i != j; i++) {
  k = j - i; 
  * (start + k) = "\0";
}

也没有意义,而且在此声明中

  * (start + k) = "\0";

您正尝试为char类型的对象分配值char *的值。编译器应在此处发出诊断消息。

还不清楚为什么不使用标准C函数。

该功能可以按照以下方式查看,如本演示程序中所示

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

#define N   100

char * remove_words( char *s )
{
    size_t n = strlen( s );

    char *t = s;

    while ( *t )
    {
        while ( isblank( ( unsigned char )*t ) ) ++t;

        char *last = t;

        if ( *last++ )
        {
            while ( *last && !isblank( ( unsigned char )*last ) ) ++last;

            if ( t[0] == last[-1] ) memmove( t, last, n - ( last -t ) + 1 );
            else t = last;
        }
    }

    return s;
}

int main( void ) 
{
    while ( 1 )
    {
        char s[N];

        printf( "Input a sentence: (Enter - exit): " );

        if ( fgets( s, sizeof( s ), stdin ) == NULL || s[0] == '\n' ) break;

        s[ strcspn( s, "\n") ] = '\0';

        puts( s );

        puts( remove_words( s ) );

        printf( "\n" );     
    }       

    return 0;
}

它的输出可能看起来像

Input a sentence: (Enter - exit): ab aba abc abcbca dd d
ab aba abc abcbca dd d
ab  abc   

Input a sentence: (Enter - exit): 

另一种方法是删除必须删除的单词后面的空格。它比第一种方法更有效。

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

#define N   100

char * remove_words( char *s )
{
    char *destination = s;

    //  for starters skip leading blands
    while ( isblank( ( unsigned char )*destination ) ) ++destination;

    char *source = destination;

    while ( *source )
    {
        char *last = source;

        if ( *last++ )
        {
            while ( *last && !isblank( ( unsigned char )*last ) ) ++last;

            char *blank_tail = last;

            while ( isblank( ( unsigned char )*blank_tail ) ) ++blank_tail;

            if ( source[0] != last[-1] )
            {
                //  copy valid word to the destination
                if ( destination != source )
                {
                    memmove( destination, source, blank_tail - source );
                }
                destination += blank_tail - source;
            }

            source = blank_tail;
        }
    }

    *destination = '\0';

    return s;
}

int main( void ) 
{
    while ( 1 )
    {
        char s[N];

        printf( "Input a sentence: (Enter - exit): " );

        if ( fgets( s, sizeof( s ), stdin ) == NULL || s[0] == '\n' ) break;

        s[ strcspn( s, "\n") ] = '\0';

        puts( s );

        puts( remove_words( s ) );

        printf( "\n" );     
    }       

    return 0;
}

程序输出可能与abobe显示的方式相同

Input a sentence: (Enter - exit): ab aba abc abcbca dd d
ab aba abc abcbca dd d
ab abc 

Input a sentence: (Enter - exit): 

答案 2 :(得分:0)

像这样:

#include <stdio.h>
#include <ctype.h>

char *RemoveSame(char *str) {
    char *from, *to, *p;
    from = to = str;
    while(*from){
        if(isspace((unsigned char)*from)){//pre spaces copy before processing a word
            *to++ = *from++;
            continue;
        }
        p = from;//top of word
        while(*p && !isspace((unsigned char)*p))
            ++p;
        if(*from == p[-1])//top == end
            from = p;//skip
        else {
            while(*from && !isspace((unsigned char)*from))
                *to++ = *from++;//copy
        }
    }
    *to = 0;
    return str;
}

int main(void) {
    char sentence[] = "madam adam madam ada adam eve";
    printf("'%s'\n", RemoveSame(sentence));

}

答案 3 :(得分:0)

您的函数RemoveSame()有多个问题:

  • i应从0

  • 开始
  • j应从1开始。您使用start[i + j + 1]

  • 访问字符串太远了
  • 你应该停在'\0'

  • 您永远不会复制您希望保留的字词

  • 将字符串的其余部分设置为0似乎没必要,但无论如何你应该使用空字符'\0'而不是空字符串"\0"

以下是更正后的版本:

void RemoveSame(char *str) {
    int i, j, to = 0;
    for (i = 0; str[i] != '\0';) {
        if (str[i] == ' ') {
            str[to++] = str[i++];
            continue;
        }
        for (j = 1; str[i + j] != '\0'; j++) {
            if (str[i + j] == ' ')
                break;
        }
        if (str[i] == str[i + j - 1]) {
            /* skip the word */
            i += j;
            continue;
        }
        for (; j > 0; j--) {
            str[to++] = str[i++];
        }
    }
    str[to] = '\0';  /* set the null terminator */
}

注意:

  • str是字符串比start更明确的名称。

  • 使用数组表示法str[i]*(str + i)更具可读性。

  • 删除的单词之前或之后的空格也应该被移除。

您的代码中还有其他问题:

  • scanf("%s", &readerName);不正确,请改用scanf("%s", readerName);

  • 以这种方式分配lineline = calloc(FILE_NAME_LENGTH, FILE_NAME_LENGTH * sizeof(char))不正确,请使用自动数组:char line[LINE_LENGTH];

  • while (!feof(reader))总是错的。请改用while (fgets(line, LINE_LENGTH, reader))

  • WriteLine()应停在第一个'\0'

  • 您应该使用'\0'作为空字符,而不是NULL

  • *(start + i) != NULL