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 ;
source to share
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. :)
source to share
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.
source to share
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.
source to share
Your idea in the code is correct, but you are making two major mistakes:
-
You return
char []
from a function withchar
as the return type.char []
,char *
andchar
are three different types, although in this casechar []
theychar *
will behave the same. However, you need to returnchar *
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 passconst 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;
}
source to share
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';
}
source to share