How can I make a function to remove two letters in C?

I am trying to make a function that removes double letters from a string. The function should only remove double letters next to each other, not in the whole string. for example, "aabbaa" becomes "aba" (not "ab"). I'm new to programming and don't fully understand pointers etc. And I need some help. Below I am so far. This doesn't work at all and I have no idea what to return since I try to return the string [] it has an error:

char doubleletter( char *string[] ) {
char surname[25];
int i;
for((i = 1) ; string[i] != '\0' ; i++) {

    if (string[i] == string[(i-1)]) {   //Supposed to compare the ith letter in array with one before
        string[i] = '\0' ;              //Supposed to swap duplicate chars with null
    }


}
surname[25] = string;

return surname ;

      

+3


source to share


5 answers


Try the following. This is simple and professional looking code. :)

#include <stdio.h>

char * unique( char *s ) 
{
    for ( char *p = s, *q = s; *q++; )
    {
        if ( *p != *q ) *++p = *q;
    }

    return s;
}


int main(void) 
{
    char s[] = "aabbaa";

    puts( unique( s ) );

    return 0;
}

      

Output signal

aba

      

Also, the function can be rewritten as follows to avoid unnecessary copying.



char * unique( char *s ) 
{
    for ( char *p = s, *q = s; *q++; )
    {
        if ( *p != *q )
        {
            ( void )( ( ++p != q ) && ( *p = *q ) );
        }
    }

    return s;
}

      

or

char * unique( char *s ) 
{
    for ( char *p = s, *q = s; *q++; )
    {
        if ( *p != *q && ++p != q ) *p = *q;
    }

    return s;
}

      

The latest implementation seems to be the best. :)

+2


source


First of all, remove those parent outlines aroung i = 1

in for loop (why did you put them there?) Second , if you put \0

in the middle of the line, the line will just be shorter. \0

terminates an array (string) in C, so if you have:
ababaabababa


and you replace the second "a" in the pair with \0

:
ababa\0baba


efficiently to the compiler it will be like you are just slicing that string:
ababa

The third mistake here is probably that you are passing a two-dimensional array: char *string[]

This is equivalent to passing char **string

and it is essential that you are passing an array of strings while you only want to pass a string (which means a pointer, which means an array: char *string

or ofc char string[]

)



Next: you make an internal assumption that the past line will be less than 24 characters (+ \0

), but you don't check it anywhere.

I think that the easiest way (although maybe not the smartest) to remove duplicate characters is to copy the passed string to another one for the loop, omitting the repeated characters.

+2


source


One example: it does not modify the input line and does not return a new dynamically allocated row. I think:

char *new_string_without_dups(const char *input_str, size_t len)
{
    int i = 1;
    int j = 0;
    char tmpstr[len+1] = {0};

    for (; i < len; i++) {
        if (input_str[i] == input_str[i-1]) {
            continue;
        }
        tmpstr[j] = input_str[i];
        j++;
     }

     return strdup(tmpstr);
}

      

Remember to free the returned string after use.

Note that there are several ways to adapt / improve this. One thing is that it requires a C99 std due to the fact that the size of the array is not known at compile time. Other things like you can get rid of the argument len

if you guarantee a terminated string \0

as input. I'll leave this as an exercise.

+2


source


Your idea in the code is correct, but you are making two major mistakes:

  • You return char []

    from a function with char

    as the return type. char []

    , char *

    and char

    are three different types, although in this case char []

    they char *

    will behave the same. However, you need to return char *

    from your function to be able to return a string.

  • You automatically reclaim the memory. In other languages ​​where memory counts, this is fine. In C, this causes undefined behavior. You cannot use automatic memory from a function outside of that function itself. The memory is considered empty after the function exits and will be reused, i.e. your value will be overwritten. You have to either pass a buffer or hold the result, or do dynamic allocation within the function with malloc()

    . Which one you make is a matter of style. You can also reuse the input buffer, but writing a function like this is not desirable anyway when you need to store the input, and it will make it impossible to pass const char*

    to the function, meaning you cannot do something like this:

const char *str = "abbc"; ... doubleletter(str,...);

If I had to write a function, I would call it something like this:

int doubleletter (const char *in, size_t inlen, char *out, size_t outlen){
    int i;
    int j = 0;
    if (!inlen) return 0;
    if (!outlen) return -1;
    out [j++] = in[0];
    for (i = 1; i < inlen; ++i){
        if (in[i - 1] != in[i]){
            if (j > outlen - 1) return -1;
            out[j++] = in[i];
        }
    }
    out[j] = '\0';
    return j - 1;
}

int main(void) {
    const char *str1 = "aabbaa";
    char out[25];
    int ret = doubleletter(str1, strlen(str1), out, sizeof(out)/sizeof(out[0]));
    printf("Result: %s", out);
    return 0;
}

      

+2


source


I would recommend using 2 indices to change the line in place:

void remove_doubles(char *str)
{

    // if string is 1 or 0 length do nothing.
    if(strlen(str)<=1)return; 

    int i=0;   //index (new string)
    int j=1;   //index (original string)


    // loop until end of string
    while(str[j]!=0)
    {
        // as soon as we find a different letter,
        // copy it to our new string and increase the index.
        if(str[i]!=str[j])
        {
            i++;
            str[i]=str[j];
        }

        // increase index on original/old string
        j++;
    }

    // mark new end of string
    str[i+1]='\0';

}

      

+1


source







All Articles