为什么我的removeString函数不能删除字符?

时间:2016-07-25 18:07:17

标签: c arrays string

我正在书中练习,除了printfscanf之外,我不允许使用任何库函数。

我写了一个接受字符串的程序。然后,您可以输入要从字符串中删除的字符数。然后选择执行哪个索引。

我的尝试是在我的函数结束时遍历我想要保留的字符,然后用我想要丢失的函数替换它们。

由于某种原因,它正好相反。

如果我输入字符串:"the wrong son" 然后选择删除6个字符并从数组的第4个索引开始,

我应该得到:"the son"

相反,我得到"the wro"

我现在已经对这个打了4个小时了。

你能告诉我我哪里出错吗?

#include <stdio.h>

void removeString(char source[], int start, int count);
int stringLength(const char string[]);

    int main(void)
    {
        int start, count;
        char source[20]; 

        printf("What's your string?\n");
        scanf("%[^\n]s", source);

        printf("How many characters do you want to remove?\n");
        scanf("%i", &count);

        // Choose which index to start deletion from
        printf("Where are we starting from?\n");
        scanf("%i", &start);

        // Call function to remove characters from string
        removeString(source, start, count);

        // print out result, stored in source
        printf("Here's the result: %s\n", source);

        return 0;
    }

    void removeString(char source[], int start, int count)
    {
        int i, j;

        // Find length of string
        int length = stringLength(source);


        //loop through the last few characters that we DO want to keep until we hit the end of the string 
        for(i = (start+count); i <= length; i++)
        {
            //loop backwards through the string, from the first of the ones we want to keep, stop at the 'start' of the index
            for(j = (start+count)-1; j <= start; j--)
            {
                // assign 'i' which is the last few characters we want to keep and put them in the place of the characters we want to delete
                source[j] = source[i];
            }
        }

        // assign a null character to end the string once we've finished modifying
        source[count + 1] = '\0';
    }

    int stringLength(const char string[])
    {
        int count =0;

        while(string[count] != '\0')
            count++;

        return count;
    }

4 个答案:

答案 0 :(得分:3)

你只需要一个for循环来实现这一点。假设我们可以成功地避免在字符串的末尾运行,你可以编写如下内容:

for(i = start; i < start + count && i < length; i++) {
   source[i] = source[i+count];
}

然后你只需要在正确的位置设置一个空字符。但是,这不算数。也许在长度计数1(或考虑开始+计数),因为你正在删除&#34;计数&#34;字符。

答案 1 :(得分:1)

您需要修改循环 -

for(i=start, j=(start+count) ; j<=length; i++, j++){
    source[i]=source[j];    
}
// assign a null character to end the string once we've finished modifying

source[strlen(source)-1]='\0';   // include string.h for strlen()

这个循环基本上做的是,从starti)位置初始化,并在索引{{1}处复制索引start+countj)的值}。最后将i附加到数组中。

同样关于'\0'不正确,因为它会将其附加到错误的位置。

答案 2 :(得分:1)

考虑使用fgets读取输入,使用sscanf来解析整数。检查sscanf(或scanf)的返回以查看是否存在问题。在removeString中,可以使用一对指针来遍历字符串。

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

void removeString(char source[], int start, int count);
int stringLength(const char string[]);

int main(void)
{
    int start, count;
    int result = 0;
    char source[120];
    char input[120];

    printf("What's your string?\n");
    if ( ( fgets( source, sizeof ( source), stdin)) == NULL) {
        printf ( "could not get input\n");
        return 1;
    }
    source[strcspn ( source, "\n")] = '\0';//remove newline

    do {
        printf("How many characters do you want to remove?\n");
        if ( ( fgets( input, sizeof ( input), stdin)) == NULL) {
            printf ( "could not get input\n");
            return 1;
        }
        result = sscanf(input, "%d", &count);
    } while ( result != 1);//loop on bad input

    do {
        printf("Where are we starting from?\n");
        if ( ( fgets( input, sizeof ( input), stdin)) == NULL) {
            printf ( "could not get input\n");
            return 1;
        }
        result = sscanf(input, "%d", &start);
    } while ( result != 1);//loop on bad input

    removeString(source, start, count);

    printf("Here's the result: %s\n", source);
    return 0;
}

void removeString(char source[], int start, int count)
{
    char *to = NULL, *from =NULL;

    int length = stringLength(source);

    if ( start > length) {//very short source
        return;
    }

    if ( start + count > length) {//source still too short
        source[start] = '\0';//truncate at start
        return;
    }
    to = &source[start];
    from = &source[start + count];

    while(*from)//loop until '\0'
    {
        *to = *from;
        to++;
        from++;
    }
    //set '\0'
    *to = *from;
}

int stringLength(const char string[])
{
    int count =0;
    while(string[count] != '\0')
        count++;
    return count;
}

答案 3 :(得分:0)

  

你能告诉我我哪里出错吗?

在索引中。

我会尝试让您了解出错的地方,而不是发布简单的解决方案。

for(i = (start+count); i <= length; i++)

在这里,对于输入错误的儿子&#39;,length将等于13.因此,您正在索引source[13]不是一个越界访问,因为你已经将数组静态初始化为20个单元格,但它仍然超过输入字符串的长度1。

因此请将其更改为i < length

现在这个循环:

for(j = (start+count)-1; j <= start; j--) 

它表示从9开始(对于示例输入)并减少j直到它小于或等于4,没有意义,你打算写:

j >= start

现在抓一张纸,写下你的输入和指示,请:

start = 4
count = 6
length = 13

       start    start+count
         |           |
         V           V
|t|h|e| |w|r|o|n|g| |s|o|n|
 0 1 2 3 4 5 6 7 8 9 101112

立即运行您的算法。

你正在获得第i个角色并覆盖所有第j个角色,这就是为什么你最终得到了nnn&#39;在应用我的修复后,对吧?

所以你要做的就是直到start再加上你已经覆盖过的东西,并且再次覆盖!

结果,改变这个:

j >= start

j >= start + i - (start + count);

你应该得到这个输出:

C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
What's your string?
the wrong son
How many characters do you want to remove?
6
Where are we starting from?
4
Here's the result: the son

如果情况并非如此,请告诉我发布整个固定代码。

修改

  

我附加了&#39; \ 0&#39;错了吗?

不,这是正确的(至少在此答案中提出的所有修正案之后)。我们来看看这段代码:

printf("source = %s\n", source);
printf("count = %d\n", count);
printf("source[count] = %c\n", source[count]);
printf("source[count + 1] = %c\n", source[count + 1]);
source[count + 1] = '\0';

给出:

source = the sonnnnson
count = 6
source[count] = n
source[count + 1] = n

所以count + 1等于7,这是第二个&#39; n&#39;在字符串中,这正是我们想要放置空终止符的地方。