user2387766
user2387766

Reputation:

How do I get rid of the spaces in the string?

I'm trying to write a function to remove the spaces in a string, I know that my problem is that even after moving the next character into where the space would be, I'm still copying that character in its original place (I'm repeating a character twice). I'm not too sure how to get rid of that repeating character. (i.e. I have "Hello world.", but my function gives me "Hellowworld.")

void deblank(char str1[], char str2[])
{
   int i, x;

   for (i = 0; str1[i] != '\0'; i++)
   {
      if (str1[i] == ' ')
      {
         x = i + 1;
         str2[i] = str1[x];
      }

      else
      {
         str2[i] = str1[i];
      }
   }

   str2[i] = '\0';
}

Upvotes: 0

Views: 242

Answers (7)

Ahmed Masud
Ahmed Masud

Reputation: 22374

Okay this is just to give an alternate approach to the accepted answer, and is primarily to help you approach solving problems in a more generic way.

#include <stdio.h>
/** 
 * char *remove_needles(char *dest, const char *haystack, const char *needles);
 * 
 * puts in dest, all characters from haystack, that are not found in needles
 */

char *remove_needles(char *dest, const char *haystack, const char *needles) 
{
    const char *hp;   /* this pointer will run through the haystack and is used to sort
                       * needles and hay 
                       */
    char *dp;         /* this pointer will point to the last character in dest */
    const char *np;   /* runs through the needles with the current  */

    dp = dest;         /* to begin with the tail is the head :-) */

    for (hp = haystack; hp != NULL && *hp != '\0'; hp++ ) {

        for (np = needles; *np != '\0'; np++ ) {  
           if ( *hp == *np ) { /* is the current char at hp a needle? */
              break; /* yep: let's break out of this loop it's a needle */
           }
        }

        if ( *np == '\0' ) { 
                           /* *np will only be '\0' if we ran through all the needles but 
                            * the character at the pointer hp was not a needle
                            */
           *dp = *hp;      /* so it's hay and we save it at the tail of dest */
           dp++;           /* and move the tail along */
        }
    }

    return dest;           /* we are all done and we return the result */
}


int main() 
{
      char src[] = "Hello World\n\tare you watching this?";
      char dest[256]; /* this should have at least sizeof(src) space */
      char white_spaces[] = " \t"; /* these are our needles, notice the space before \t */

      remove_needles(dest, src, white_spaces);

      printf("src: `%s'\ndest:`%s'\n", src, dest);
      return 0;
}

Exercises to consider

  1. Can you extend this to a split function that put substrings from haystack into an array? Start out by limiting yourself to 10 substrings, declare char dest[128][10]; and try it out.

  2. How can you avoid declaring dest like this? We know that total memory dest can take up is not bigger than haystack, is it possible to keep yourself squeezed close to around that amount without manually calculating it?

Upvotes: 1

Oscar Tang
Oscar Tang

Reputation: 201

This should works.

void deblank(char str1[], char str2[])
{
   int i, j;

   for (i = 0, j = 0; str1[i] != '\0'; i++, j++)
   {
      if (str1[i] == ' ')
      {
         i++;
         str2[j] = str1[i];
      }

      else
      {
         str2[j] = str1[i];
      }
   }

   str2[j] = '\0';
}

Upvotes: 0

chux
chux

Reputation: 153348

[edit] re-write to use only 1 string parameter.

void deblank(char str[]) {
   size_t x = 0;
   for (size_t i = 0; str[i]; i++) {
      if (str[i] != ' ') {
         str[x++] = str[i];
      }
   }
   str[x] = '\0';
}

Upvotes: 1

Jerry Coffin
Jerry Coffin

Reputation: 490098

Right now, you have only one index, i.

You really want two indices, call them i and j. i will be your index into your source string. j will be your index into your destination string.

You'll start by walking through the source string about like you are now, incrementing i at each iteration. When you have a non-space character in the source, you'll copy it to the destination, and increment your destination index.

When you have a space in the source, you won't copy it to the destination or increment the destination index.

Typically this will look something like:

size_t j = 0;

for (i=0; input[i]; i++)
    if (input[i] != ' ')
        output[j++] = input[i];
output[j] = '\0';

And yes, I'd use something like input and output or source and dest instead of str1 and str2. The latter gives no indication of which you're copying from/to.

I'd also advise using isspace from <ctype.h> instead of comparing directly to the space character, unless you really only want to eliminate the space character, but retain other white space (tabs, carriage returns, new lines, vertical tabs, etc.)

Upvotes: 1

Nobilis
Nobilis

Reputation: 7448

A smarter way would be to have a second counter that is used to keep track of the current position in the output array. You only copy to the output if the current character in the input is not space.

#include <stdio.h>

void deblank(char str1[], char str2[])
{
   int i, j = 0; /* j points initially to the first element of str2, we only increment it if i doesn't point to space */

   for (i = 0; str1[i] != '\0'; i++)
   {
      if (str1[i] != ' ') /* i doesn't point to a space char */
      {
         str2[j] = str1[i]; /* add the current char to str2, for the first iteration this is at position str2[0] */
         j++; /* increment j++, so that the next time we encounter a non-space char, it is put in the next posisition */
      }
   }

   str2[i] = '\0';
}

int main()
{
    char input[20] = "Hey lo, World!";
    char output[20] = "";

    deblank(input, output);

    printf("%s - %s\n", input, output);

    return 0;
}

Prints:

 $ ./a.out 
 Hey lo, World! - Heylo,World!

Upvotes: 0

vinod
vinod

Reputation: 132

code what ur written won't work when multiple spaces are there in between words.


int i, x=0;

   for (i = 0; str1[i] != '\0'; i++)
   {
      if ((str1[i] == ' ')||(str[i] == '\t'))
      {
         continue;
      }

      else
      {
         str2[x] = str1[i];
          x++;
      }
   }

   str2[x] = '\0';

Upvotes: 0

Mark Stevens
Mark Stevens

Reputation: 2366

You are just shifting the 1 character and leaving the rest - filling the ' ' with a 'w'.

Moving left to right, you need to shift ALL characters to the left every time you encounter a blank. That's the idea anyway.

It would be easier - and a little faster - to have 2 strings: a source and a destination.

Like so:

char src[128] = "hello world and then some!";
char dest[128];

int destIndex = 0;
for (int i = 0; i < strlen(src); ++i)
{
    if (src[i] != ' ')
        dest[destIndex++] = src[i];
}
dest[destIndex] = 0;  // make sure the new string is terminated

That way you don't have to shift anything - just move the non-blank chars to the new string and you're left with a new string with all of the spaces removed.

Upvotes: 0

Related Questions