-1

Possible Duplicate:
How do I replace multiple spaces with a single space in C?

I have a string in c that can contain two consecutive spaces. I want to remove two consecutive spaces with one space. How can I do that? Help please.

Community
  • 1
  • 1
James
  • 13,891
  • 26
  • 68
  • 93

5 Answers5

2

If it is the case that there is a single occurrence of two consecutive spaces in the string then a possibility would be to use strstr() and memmove():

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

int main()
{
    char s[] = "a string with two  spaces";
    char* two_spaces_ptr = strstr(s, "  ");
    printf("[%s]\n", s);
    if (two_spaces_ptr)
    {
        memmove(two_spaces_ptr + 1,
                two_spaces_ptr + 2,
                strlen(two_spaces_ptr + 2) + 1); /* +1 to copy the NULL. */

    }
    printf("[%s]\n", s);

    return 0;
}

Output:

[a string with two  spaces]
[a string with two spaces]

The C standard for memmove() states:

The memmove function copies n characters from the object pointed to by s2 into the object pointed to by s1. Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1.

EDIT:

Updated answer to use memmove(), instead of strcpy() that resulted in undefined behaviour.

hmjd
  • 120,187
  • 20
  • 207
  • 252
0

You can use strchr function to search for a space in a string and then follow it up with a logic to replace all the spaces following it. You need to repeat this for another patch of spaces till the string ends.

Jay
  • 24,173
  • 25
  • 93
  • 141
0

You can write over your own string:

char *ys = YOUR_STRING;
char *n = ys;
while (*ys)
{
  *n = *ys;
  if (*ys == ' ')
    while (*ys == ' ')
      ys++;
  else
    ys++;
  n++;
}

Or you can create a new string:

char *ys = YOUR_STRING;
char *n = malloc(sizeof(*n) * strlen(ys));
int i = 0;

while (*ys)
{
  n[i++] = *ys;
  if (*ys == ' ')
    while (*ys == ' ')
      ys++;
  else
    ys++;
}
// use n
Eregrith
  • 4,263
  • 18
  • 39
  • No, you don't necessarily need to create a new one, even though it can improve readability and make the code more generic. – Lundin Mar 22 '12 at 09:08
-1
for (unsigned char *p = YOUR_STRING, *q = p; ((*q = *p));) {
        if (*q++ == ' ') {
                while (*++p == ' ');
        } else {
                p++;
        }
}

Less obscure alternative:

unsigned char *p = YOUR_STRING;
unsigned char *q;
/* zap to the first occurrence */
while (*p && *p++ != ' ');
/* copy from here */
q = --p;
while ((*q = *p)) {
        if (*q++ == ' ') {
                while (*++p == ' ');
        } else {
                p++;
        }
}
hroptatyr
  • 4,702
  • 1
  • 35
  • 38
  • 1
    You don't replace anything, at least put a `//use *p char here` comment after your `if/else`. Anyway this does not work as `q` will pass on the spaces after the first one and cause your `while` to increment `p` at least once even if `*p` is not a space, you will have a difference between `*q` and `*p`. – Eregrith Mar 22 '12 at 08:50
  • huh? `p` and `q` are just temporary pointers, `YOUR_STRING` is modified by side-effect – hroptatyr Mar 22 '12 at 08:53
  • no... it's not modified by a side effect, you are not assigning anything you are just incrementing your _pointers_ here. If you want to remove spaces you have to allocate a new string and copy only one space, moving on top of others – Eregrith Mar 22 '12 at 08:58
  • @Eregrith: And yes of course there's a difference between `q` and `p`, `p` traverses the string while `q` builds up the string with only a single space – hroptatyr Mar 22 '12 at 09:00
  • @Eregrith, well try the code and see the magic :) – hroptatyr Mar 22 '12 at 09:01
  • the assignment is in the condition part of the `for`-loop – hroptatyr Mar 22 '12 at 09:02
  • 1
    This is a horribly obscure way to solve this trivial task, if it even does what you claim it does. – Lundin Mar 22 '12 at 09:03
  • Ok I see where i was wrong. Why on earth did you put the assignment `*q = *p` __IN THE FOR'S CONDITION ZONE__ ????? – Eregrith Mar 22 '12 at 09:04
  • @Lundin: well I disagree, I think it's beautiful because all pointers only increment and so the whole operation can be done using just 2 registers – hroptatyr Mar 22 '12 at 09:07
  • 1
    complete abuse of the for loop. the progression zone is empty, the condition does 2 things... copy from p to q and test if copied value was different of \0... you win the obscurity test hands down – UmNyobe Mar 22 '12 at 09:11
  • Not that it matters, but I chose the `for` loop to introduce `q` and `p` only. Nobody would have objected the corresponding `while ((*q = *p))` form. – hroptatyr Mar 22 '12 at 09:16
  • 2
    @hroptatyr It is ugly as can be and premature optimization. Look at hmjd's code in comparison. An optimized compiler would inline the strstr and strcpy calls, resulting in pretty much identical code. Well, not exactly identical as his code is generic, while this code is not. In the end, readability is far more valuable than performance in 99.9% of all programs. – Lundin Mar 22 '12 at 09:20
  • 1
    As a curiousity, this little code alone yielded 15 violations of the MISRA-C coding standard when executed in a static code analyser (LDRA Testbed). – Lundin Mar 22 '12 at 09:24
  • @Lundin: Except that hmjd's solution didn't work. See my less obscure variant. – hroptatyr Mar 22 '12 at 10:14
-1

If you're sure there can be only two spaces consecutive at max, you can do something like:

int main ()
{
    char *str="This  is a  wonderful world. Let's  have a   good  time here.";
    int len=strlen(str);
    char *result = (char*)malloc(len);
    int j=0;
    for(int i=0;i<len;i++) {
        if(str[i]==' ' && str[i-1]==' ') {
            i++;
        }
        result[j++]=str[i];
    }
    result[j]='\0';
    printf("%s\n", result);
  return 0;
}
Manu Manjunath
  • 6,201
  • 3
  • 32
  • 31
  • 2
    -1 for teaching to typecast the result of malloc. Please remove the typecast. Read [this](http://c-faq.com/malloc/mallocnocast.html) and [this](http://stackoverflow.com/questions/1565496/specifically-whats-dangerous-about-casting-the-result-of-malloc). – Lundin Mar 22 '12 at 09:09
  • -1 for buggy code example, evidently untested. – Paul R Mar 22 '12 at 09:43
  • @Eregrith Fixed. Lundin, Thanks. So far, I was always told to put the typecast. :-). Paul, Fixed. – Manu Manjunath Mar 22 '12 at 11:05
  • There are still serious bugs in the code, e.g. look at what happens if the first character in the string is a space. – Paul R Mar 22 '12 at 12:33