3

I want to repace multiple spaces in a string by single space, however my following code doesn't work. What's the logical mistake?

#include<stdio.h>
#include<string.h>
main()
{
char input[100];
int i,j,n,z=0;
scanf("%d",&n);
z=n;
for(i=0;i<n;i++)
scanf("%c",&input[i]);
for(i=0;i<n;i++)
{
    if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
    {
        --z;
        for(j=i;j<n;j++)
        input[j]=input[j+1];
    }
}
for(i=0;i<z;i++)
    printf("%c",input[i]);
printf("\n");
}
5
  • 1
    scanf makes some issue. Instead use gets OR scanf("%s",input). Commented May 28, 2013 at 11:00
  • wrong if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' ')) Commented May 28, 2013 at 11:01
  • @BLUEPIXY , whats wrong? Commented May 28, 2013 at 11:03
  • see sample code of my answer Commented May 28, 2013 at 11:06
  • @Navnath: please do not suggest gets(). It is impossible to easy safely and no longer (since 2011) in the C Standard. Suggest fgets() which is perfectly reasonable for reading interactive user input. Commented May 28, 2013 at 11:19

9 Answers 9

7

I would do something like this:

void replace_multi_space_with_single_space(char *str)
{
    char *dest = str;  /* Destination to copy to */

    /* While we're not at the end of the string, loop... */
    while (*str != '\0')
    {
        /* Loop while the current character is a space, AND the next
         * character is a space
         */
        while (*str == ' ' && *(str + 1) == ' ')
            str++;  /* Just skip to next character */

       /* Copy from the "source" string to the "destination" string,
        * while advancing to the next character in both
        */
       *dest++ = *str++;
    }

    /* Make sure the string is properly terminated */    
    *dest = '\0';
}

Of course, the above function requires you to properly terminate the string, which you currently do not.

What the function above does, is basically copy the string over itself. The exception is when there is a space, when multiple spaces are simply discarded.

Since the function modifies the source string, it can not be used on string literals.

Sign up to request clarification or add additional context in comments.

Comments

2

The scanf is giving you some problem: it reads the \n you give after inputting the length n. So, you will miss the last character since for loop exits. The already given answers are good enough. But if you want to follow your own logic, try this:

void main()
{
    char input[100];
    int i = 0,j,n = 0;
    while ((input[n] = getchar()) != '\n') {
        n++;
    }
    input[n] = '\0';
    while (i < n)
    {
        if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
        {
            for(j=i;j<n;j++)
            input[j]=input[j+1];
            n--;
        }
        else
        {
            i++;
        }
    }
    printf("%s\n",input);
    printf("\n");
}

1 Comment

looks to me that this solution is O(n^2). there is an O(n) solution.
2

if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))

case " 1 3" : when i == 0 accses input[i-1] Out-of-Bounds

scanf("%d",&n);

remain newline, (input[0] <-- '\n')

fix to

scanf("%d%*c",&n);

#include <stdio.h>

char* uniq_spc(char* str){
    char *from, *to;
    int spc=0;
    to=from=str;
    while(1){
        if(spc && *from == ' ' && to[-1] == ' ')
            ++from;
        else {
            spc = (*from==' ')? 1 : 0;
            *to++ = *from++;
            if(!to[-1])break;
        }
    }
    return str;
}

int main(){
    char input[]= "  abc   de  f  ";

    printf("\"%s\"\n", uniq_spc(input));//output:" abc de f "
    return 0;
}

2 Comments

+ your answer(I saw other also) are very good, but bit explanation will help OP/and others more :)
to[-1] introduced the spc flag to avoid sequence range.
1

Why make it more complicated than it needs to be? You can use strtok to check for single whitespaces and just ignore those. Then you can use strcat to concatenate the string into a full sentence and then you're done.

This is how I did it:

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

int main(void) {
    char *pch;
    char sentence[1000];
    char without[1000];

    printf("Sentence: ");
    fgets(sentence,1000, stdin);
    strtok(sentence, "\n"); // remove any newlines
    pch = strtok(sentence, " ");
    while(pch != NULL) {
      strcat(without, pch);
      strcat(without, " \0");
      pch = strtok(NULL, " ");
    }
    without[strlen(without)-1] = '\0'; // remove extra whitespace at the end
    printf("|%s|\n",without);
    return 0;
}

Comments

1
#include <stdio.h>
#include <stdlib.h>
void remove_blanks(char* s);

int main()
{
    char const s[] = {'1',' ',' ','2',' ',' ','3'};
    remove_blanks(s);
    printf("%s",s);
    return 0;
}

void remove_blanks(char* s){
    int i=0, delta=0, cnt=0;

    for (i=0;s[i];++i){
        if (s[i]==' ') cnt++;
        if (cnt>1){
            delta+=1;
            cnt=0;
        }
        s[i-delta]=s[i];
        if(delta>0) s[i]='\0';

    }
}

Comments

1

You cant try this simple code:

#include <stdio.h>

#define IN 1
#define OUT 0

int main() {
  int c, spaces, state;

  spaces = 0;
  state = OUT;  
  while ((c = getchar()) != EOF) {

      if ( c == ' ') {
           ++spaces;
           state = OUT;
       }
      else if (state == OUT) {
          state = IN;
          spaces = 0;
      }
      if (c == ' ' && spaces > 1 && state == OUT)
          c = 0;            
      putchar(c);
  }
  return 0;
}

Comments

0

You have to fix the following for loop. the limit of your for loop should be z and not n

for(j=i;j<n;j++)
input[j]=input[j+1];

by

for(j=i;j<z;j++)
input[j]=input[j+1];

BTW: the fist charachter get by your scanf() (which read charachters) is newline (\n). this newline come from the first scanf() of decimal(%d)

Comments

0
#include<stdio.h>
#include<string.h>
int main(void)
    {
        char input[1000];
        int i=0;
        gets(input); 
        for(i=0;input[i]!='\0';i++)
        {
            if(input[i]!=' ' || input[i+1]!=' ')
                printf("%c",input[i]);
        }
        return 0;
    }

Comments

0

Simplest way, using two methods from string.h library:

void strRemoveBlanks(char* _s){
    char* ptr = NULL;
    while ((ptr = strstr(_s, "  ")) != NULL)
        memmove(ptr, ptr + 1, strlen(ptr));
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.