8

The question asked here is very similar to what I am having a problem with. The difference is that I must pass an argument to a function that removes the spaces and returns the resulting string/char array. I got the code working to remove the spaces but for some reason I am left with trailing characters left over from the original array. I even tried strncpy but I was having lots of errors.

Here is what I have so far:

#include <stdio.h>
#include <string.h>
#define STRINGMAX 1000                                                      /*Maximium input size is 1000 characters*/

char* deblank(char* input)                                                  /* deblank accepts a char[] argument and returns a char[] */
{
    char *output=input;
    for (int i = 0, j = 0; i<strlen(input); i++,j++)                        /* Evaluate each character in the input */
    {
        if (input[i]!=' ')                                                  /* If the character is not a space */
            output[j]=input[i];                                             /* Copy that character to the output char[] */
        else
            j--;                                                            /* If it is a space then do not increment the output index (j), the next non-space will be entered at the current index */
    }
    return output;                                                          /* Return output char[]. Should have no spaces*/
}
int main(void) {
    char input[STRINGMAX];
    char terminate[] = "END\n";                                             /* Sentinal value to exit program */

    printf("STRING DE-BLANKER\n");
    printf("Please enter a string up to 1000 characters.\n> ");
    fgets(input, STRINGMAX, stdin);                                         /* Read up to 1000 characters from stdin */

    while (strcmp(input, terminate) != 0)                                   /* Check for que to exit! */
    {
        input[strlen(input) - 1] = '\0';
        printf("You typed: \"%s\"\n",input);                                /* Prints the original input */
        printf("Your new string is: %s\n", deblank(input));                 /* Prints the output from deblank(input) should have no spaces... DE-BLANKED!!! */

        printf("Please enter a string up to 1000 characters.\n> ");
        fgets(input, STRINGMAX, stdin);                                     /* Read up to another 1000 characters from stdin... will continue until 'END' is entered*/
    }
}
Community
  • 1
  • 1
John R
  • 350
  • 2
  • 5
  • 19
  • Possible duplicate of [How to remove all spaces and tabs from a given string in C language?](http://stackoverflow.com/questions/1514660/how-to-remove-all-spaces-and-tabs-from-a-given-string-in-c-language) – Jim Fell Oct 29 '15 at 17:40

6 Answers6

15

After removing the white spaces from the input you have not terminated it with nul-terminator (\0) because the new length is less than or equal to the original string.

Just nul-terminate it at the of end your for loop:

char* deblank(char* input)                                         
{
    int i,j;
    char *output=input;
    for (i = 0, j = 0; i<strlen(input); i++,j++)          
    {
        if (input[i]!=' ')                           
            output[j]=input[i];                     
        else
            j--;                                     
    }
    output[j]=0;
    return output;
}
P.P
  • 117,907
  • 20
  • 175
  • 238
  • Worked nicely for me! Thanks. Had to move j declaration out of the for loop in order to give it function scope visibility. – John R Oct 26 '12 at 12:40
  • May want to consider removing all whitespace based on [this](https://stackoverflow.com/a/30033598/7032856). – Nae Nov 22 '20 at 21:45
13

You're not terminating the output, and since it might have shrunk, you're leaving the old tail in there.

Also, I would suggest that the treatment of j, which is always incremented in the loop and then has to be manually decremented if the current character is not copied, to be somewhat sub-optimal. It's not very clear, and it's doing pointless work (incrementing j) which even has to be undone when it's not desired. Quite confusing.

It's easier written as:

char * deblank(char *str)
{
  char *out = str, *put = str;

  for(; *str != '\0'; ++str)
  {
    if(*str != ' ')
      *put++ = *str;
  }
  *put = '\0';

  return out;
}
unwind
  • 391,730
  • 64
  • 469
  • 606
  • I would have preferred your answer but I only have an infant's understanding of pointers. The book I am reading for my class does not explain things so well for absolute beginners like myself and I honestly couldnt explain what is going on to my instructor. I can kinda piece together what you did if I stare at your code long enough but I really don't have a fundamental concept of how your code works. For example, how does incrementing "++" work with char arrays? I thought that could only be used for numerical datatypes. Thanks for your input anyway though! – John R Oct 26 '12 at 12:56
  • @JohnR *This* solution should be the accepted one. I hope you are now as comfortable with C pointers as to understand why. – Wolf Aug 12 '21 at 10:38
  • @unwind (just a tiny question) Would you, spontaneously, have a better name in mind than `deblank`? – Wolf Aug 12 '21 at 11:02
1

If you need to filter more than one character at a time, you might find something like:

char *FilterChars(char *String,char *Filter){
  int a=0,i=0;
  char *Filtered=(char *)malloc(strlen(String)*sizeof(char));
  for(a=0;String[a];a++)
    if(!strchr(Filter,String[a]))
      Filtered[i++]=String[a];
  Filtered[i]=0;
  return Filtered;
}

Useful; just provide a list of characters in *Filter you wish to strip out. For example "\t\n ", for tabs, newlines and spaces.

Owl
  • 1,446
  • 14
  • 20
0

As others mentioned, same string is used for both source and destination, and a end of string is not maintained.

You could do in the following way also.

char* deblank(char* input)                                                  /* deblank accepts a char[] argument and returns a char[] */
{
    char *output;
    output = malloc(strlen(input)+1);

     int i=0, j=0;
    for (i = 0, j = 0; i<strlen(input); i++,j++)                        /* Evaluate each character in the input */
    {
        if (input[i]!=' ')                                                  /* If the character is not a space */
            output[j]=input[i];                                             /* Copy that character to the output char[] */
        else
            j--;                                                            /* If it is a space then do not increment the output index (j), the next non-space will be entered at the current index */
    }

    output[j] ='\0';
    return output;                                                          /* Return output char[]. Should have no spaces*/
}
Whoami
  • 13,930
  • 19
  • 84
  • 140
0

You have to return the string after adding the null(\0) terminator after the for loop block

char* deblank(char* input)                                                  
{
char *output=input;
for (int i = 0, j = 0; i<strlen(input); i++,j++)                        
{
    if (input[i]!=' ')                                                  
        output[j]=input[i];                                             
    else`enter code here`
        j--;                                                            
}
output[j]='\0';
return output;                                                          
}
Fingolfin
  • 5,363
  • 6
  • 45
  • 66
Sankar Mani
  • 168
  • 3
0

This code works with time complexity of O(n).

char str[]={"my name    is Om"};
int c=0,j=0;
while(str[c]!='\0'){
    if(str[c]!=' '){
        str[j++]=str[c];
    }
    c++;
}
str[j]='\0';
printf("%s",str);