Hello, i have trouble with creating funkction that will remove white spaces if they are more than 1 in a row

i have created this function so far

void VymazBiele()
{
int c;
    while ( (c = getchar() ) != EOF )
    {
        if (isspace(c))
        {
          putchar(' ');
          while ( (c = getchar() ) != EOF && isspace(c))
          {}
          }
          if (c != EOF)
          {
        putchar(c);
          }
    }
}

but i also need remove white spaces at the stard of the line and at the end of the line and this function cant do this
i figured out that i can replace the first and last white spaces with something like this

if isspace(c)
{
putchar('\0')
}

but i dont know how to " ask " on the first char, i can use only standard function like getchar, putchar... and i need to create condtion that will look like this
" putchar('\0') untill you find the first alphabetic character and then use function created above "

can someone help ?

Recommended Answers

All 28 Replies

use a flag for that as follows

#define FALSE 0
#define TRUE 1

void VymazBiele()
{
int c;
    int start= TRUE;
    while ( (c = getchar() ) != EOF )
    {
        if (isspace(c))
        {
          if(start==FALSE)
                 putchar(' ');
          while ( (c = getchar() ) != EOF && isspace(c))
          {}
          }
          if (c != EOF)
          {
                putchar(c);
                start = FALSE;
          }
    }
}

hups double post

thanx you very much, but there is still one mistake
there CANT be any WHITE SPACE at the beginning of the line and at the END of the line

i used this test data sa input

skuska			skuska 		

  skuska  test 				skuska		

      test  

    
	
	  tessst   			k		
      kjkj  
  lkjkj

and the output is

skuska skuska skuska test skuska test tessst k kjkj lkjkj

you probably cant see it, but when u try to quote my post, you will see that there is one SPACE after the last word in the output and there can not be, so how to fix that ?

and plz, can u explain me, why using your code was more successful than mine ? what did that #define TRUE, #define FALSE do excactly /, and using this in the code, i relly want to understand it

and plz, can u explain me, why using your code was more successful than mine ? what did that #define TRUE, #define FALSE do excactly /, and using this in the code, i relly want to understand it

read more on macros in C

read more on macros in C

ok, i understand now, that it will not do putchar(' ') because the START has true value, so it will ignore all the white spaces until the first letter :)

but how to manage, that the output won't end with one space as it ends in this case.. i cant figure out how to replace last white space with \0, any ideas ?

ok, i understand now, that it will not do putchar(' ') because the START has true value, so it will ignore all the white spaces until the first letter :)

but how to manage, that the output won't end with one space as it ends in this case.. i cant figure out how to replace last white space with \0, any ideas ?

use one more flag for that as

#define FALSE 0
#define TRUE 1

void VymazBiele()
{
int c;
    int start= TRUE;
    int spacePrinted=FALSE;
    while ( (c = getchar() ) != EOF )
    {
        if (isspace(c))
        {
          spacePrinted = FALSE;
          while ( (c = getchar() ) != EOF && isspace(c))
          {}
        }
          if (c != EOF)
          {
                if(start==FALSE && spacePrinted==FALSE)
                {
                       putchar(' ');
                       spacePrinted = TRUE;
                }
                putchar(c);
                start = FALSE;
          }
    }
}

There has to be some kind of mistake with this flag

input:

kjkkk	kjkj		jj

output

k jkkk kjkj jj

now it does not add the one space after the last letter, but it add space after the first letter..hmm ?

The code as is should work right the first time. If you are reading multiple lines it will start putting leading spaces in because start is not reset for the next one.

The code as is should work right the first time. If you are reading multiple lines it will start putting leading spaces in because start is not reset for the next one.

well but i will read multiple lines, so how to make this code right ?

well but i will read multiple lines, so how to make this code right ?

set the start flag to TRUE when u get a newline ('\n') character.

well but i will read multiple lines, so how to make this code right ?

Perhaps another approach?

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

void clean_spaces(void);
int main(void)
{
    clean_spaces();
    return 0;
}

/*
 * clean_spaces will leave only the first space found and it ignores extra
 * instances
 */
void clean_spaces(void)
{
    int c;

    do {
        c = getchar(); /* reads a char from stdin */
        /*
         * checks if the char read is a space. Displays the firts of it.
         * will disregard any consecutive space. Newlines should be excluded.
         */
        if (isspace(c) && c != '\n') {
            /* if expression works as a flag that space is in */
            putchar(c);
            /*
             * we know that previously we read a space, is the next one
             * another?
             */
            while (isspace((c = getchar()))); /* ; */
        }
        /* last char read is not discarded */
        putchar(c);

    } while (c != EOF);
}

Close but not quite right Aia.

This will leave a leading space and a trailing space before the line feed.

You can fix yours OSiRiSsk. Just check for the EOL and reset the flags.

Close but not quite right Aia.

This will leave a leading space and a trailing space before the line feed.

You can fix yours OSiRiSsk. Just check for the EOL and reset the flags.

im not behind my pc, so i cant code it right now, but it will go somelike this ?
if ( c = EOL)
{
spacePrinted = TRUE;
}

or another flag ? and where should i check for eol in the code ?

Close but not quite right Aia.

This will leave a leading space and a trailing space before the line feed.

You can fix yours OSiRiSsk. Just check for the EOL and reset the flags.

Funny, I thought that was part of the requirement.

Funny, I thought that was part of the requirement.

requirements are
"all white spaces longer than ONE SIGN have to be replace with JUST one white space, and before the first and behind the last letter there cant be ANY white space"

im not behind my pc, so i cant code it right now, but it will go somelike this ?
if ( c = EOL)
{
spacePrinted = TRUE;
}

or another flag ? and where should i check for eol in the code ?

Make it so it's just like the first time so reset both of em ...

#define EOL '\n'

... 

if(c == EOL)
{
   putchar(c);
   start= TRUE;
   spacePrinted=FALSE;
}

And EOL is considered a space so check for it while skipping spaces.


EDIT: I was refraining from clouding the issue with more code but, here's a single loop solution ...

void TrimSpace()
{
   bool bTrailing = false;
   bool bSpace    = false;

   for(;;) // ever
   {
      int c = getchar();
      switch(c)
      {
         // Terminators
         case EOF:
            return;
         case EOL:
            putchar(c);
            bSpace = bTrailing = false;
            break;
         // white space
         case ' ':
         case '\t':
            if(bTrailing)
            {
               bSpace = true;
            }
            break;
         // printables
         default:
            if(bSpace)
            {
               putchar(' ');
               bSpace = false;
            }
            putchar(c);
            bTrailing = true;
            break;

      }
   }
}

Here is a thread from a month or so ago of me working through the same problem.
http://www.daniweb.com/forums/thread226007.html
The solution is listed and works

In case you don't care to take a look:

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

#define MAXLINE 1000

/* This program will remove all trailing white space from an input file.
   Using a loop containing several if statements to check for the ASCII
      value of any white space generating characters; the program will
         individually access each character until it reaches the EOF.    */

int read(int index)
{
  if (index < MAXLINE - 1)
      return index + 1;
        else
            return 0;
}

int main(void)
{
        char S[MAXLINE];
        int head, tail, White_Space, Return_Value, c;
        Return_Value = White_Space = head = tail = 0;

        while ((c = getchar()) != EOF)
        {
                if (c == '\n')
                {
                head = tail = 0;
                if (White_Space)
                putchar('\n');
                White_Space = 0;
                }
                else if (c == ' ' || c == '\t')
                {
                        if (read(head) == tail)
                        {
                        putchar(S[tail]);
                        tail = read(tail);
                        White_Space = 1;
                        Return_Value = EXIT_FAILURE;
                        }
                S[head] = c;
                head = read(head);
                }

                else
                {
                while (head != tail)
                        {
                        putchar(S[tail]);
                        tail = read(tail);
                        }
                        putchar(c);
                        White_Space = 1;
                }
        }
        return Return_Value;
}

That will leave leading spaces as well.
Besides the fact it is way more complicated than needed.

That will leave leading spaces as well.
Besides the fact it is way more complicated than needed.

and that code has limit 1000 char for input, i need function for unlimited input

following is the complete program for your purpose

#define FALSE 0
#define TRUE 1

void VymazBiele()
{
    int c;
    int start= TRUE;
    int spacePrinted=FALSE;
    while ( (c = getchar() ) != EOF )
    {
        if (isspace(c))
        {
          spacePrinted = FALSE;
          while ( (c = getchar() ) != EOF && isspace(c))
          {}
        }
          if (c != EOF)
          {
                if(start==FALSE && spacePrinted==FALSE)
                {
                       putchar(' ');
                       spacePrinted = TRUE;
                }
                putchar(c);
                if(c == '\n')
                     start = TRUE;
                else
                     start = FALSE;
          }
    }
}

things like this u should try on your own.

Make it so it's just like the first time so reset both of em ...

#define EOL '\n'

... 

if(c == EOL)
{
   putchar(c);
   start= TRUE;
   spacePrinted=FALSE;
}

And EOL is considered a space so check for it while skipping spaces.


EDIT: I was refraining from clouding the issue with more code but, here's a single loop solution ...

void TrimSpace()
{
   bool bTrailing = false;
   bool bSpace    = false;

   for(;;) // ever
   {
      int c = getchar();
      switch(c)
      {
         // Terminators
         case EOF:
            return;
         case EOL:
            putchar(c);
            bSpace = bTrailing = false;
            break;
         // white space
         case ' ':
         case '\t':
            if(bTrailing)
            {
               bSpace = true;
            }
            break;
         // printables
         default:
            if(bSpace)
            {
               putchar(' ');
               bSpace = false;
            }
            putchar(c);
            bTrailing = true;
            break;

      }
   }
}

it seems i cant change the code using macro, it always add one space after first letter,whether i reset it or not, i am probably doing something wrong.. but i kinda like that way using macro, so it would be cool if it works :S
and this second way you made, using loop, i cant compile, it gives be bunch of errors, dont know whats wrong

//home/osiris/Desktop/projekt 1/projekt 1/projekt1.c||In function ‘VymazBiele’:|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|62|error: ‘bool’ undeclared (first use in this function)|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|62|error: (Each undeclared identifier is reported only once|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|62|error: for each function it appears in.)|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|62|error: expected ‘;’ before ‘bTrailing’|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|63|error: expected ‘;’ before ‘bSpace’|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|75|error: ‘bSpace’ undeclared (first use in this function)|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|75|error: ‘bTrailing’ undeclared (first use in this function)|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|75|error: ‘false’ undeclared (first use in this function)|
/home/osiris/Desktop/projekt 1/projekt 1/projekt1.c|82|error: ‘true’ undeclared (first use in this function)|
||=== Build finished: 9 errors, 0 warnings ===|

following is the complete program for your purpose

#define FALSE 0
#define TRUE 1

void VymazBiele()
{
    int c;
    int start= TRUE;
    int spacePrinted=FALSE;
    while ( (c = getchar() ) != EOF )
    {
        if (isspace(c))
        {
          spacePrinted = FALSE;
          while ( (c = getchar() ) != EOF && isspace(c))
          {}
        }
          if (c != EOF)
          {
                if(start==FALSE && spacePrinted==FALSE)
                {
                       putchar(' ');
                       spacePrinted = TRUE;
                }
                putchar(c);
                if(c == '\n')
                     start = TRUE;
                else
                     start = FALSE;
          }
    }
}

things like this u should try on your own.

this still add one space after the first letter :S
input

kjkkk	kjkj		jj

output

k jkkk kjkj jj

its a bit strange

this still add one space after the first letter :S
input

kjkkk	kjkj		jj

output

k jkkk kjkj jj

its a bit strange

hi, i figured it out. See below

int spacePrinted=FALSE;

change the above line to

int spacePrinted=TRUE;

It will not print the space now.....................

hi, i figured it out. See below

int spacePrinted=FALSE;

change the above line to

int spacePrinted=TRUE;

It will not print the space now.....................

here are the samples of input i have used and the outputs that the program generated

first input

test	test    test

first output

test test test

everything is allright, so far

second input

test		test

second output

t est test

there is a horizontal tabulator before the word "test" in the second output, and as you can see it puts a space after the first letter...

ok ok.
make the following change
(refer to line #19)

if(start==FALSE && spacePrinted==FALSE)                
{
                       putchar(' ');
                       spacePrinted = TRUE;
}

change the above codes to

if(start==FALSE && spacePrinted==FALSE)                
{
                       putchar(' ');
}
spacePrinted = TRUE;

thanx you very much, it is finally working as i wanted ! !!!
espacially big thanx go to dkalita & SVR

Glad it is working. One thing to check though ...
isspace(c) will be true for EOL so you will skip some line endings.
Sorry about the example not building. I've been doing c++ too long.
To compile it change the bool to int and the small true/false to caps and use the defines you have for those.

Just a note on flags ...
The name of your flags should reflect the condition (and polarity) you want to test.
In the case of the spacePrinted, you really want to know if you 'need' to print a space. So the test might be better stated as ...

if(SpaceNeeded)
{
    putchar(' ');
}

Then when it's time to set this flag it is clearer how to proceed ...

if(isspace(c))
{
   if(!start)
   {
       spaceNeeded = TRUE;
   }
}

Now the 'start' condition is suspect because we have to use !
So what we are asking here is 'is this space leading or trailing' because we only want trailing spaces. And in this case we want the 'true' condition to test so ...

if(isspace(c))
{
   if(isTrailing)
   {
       spaceNeeded = TRUE;
   }
}

or more concisely ...

if(isspace(c))
{
    spaceNeeded = isTrailing;
}

Put it all together ...

#define FALSE 0
#define TRUE 1
#define EOL '\n'

void VymazBiele()
{
    int c;
    int isTrailing  = FALSE;
    int spaceNeeded = FALSE;

    while ( (c = getchar() ) != EOF )
    {
        if (isspace(c) && c!= EOL)
        {
          spaceNeeded = isTrailing;
          while ( (c = getchar() ) != EOL && isspace(c)) {}
        }

        if (c != EOF)
        {
            if(spaceNeeded)
            {
                putchar(' ');
                spaceNeeded = FALSE;
            }
            putchar(c);

            if((c == EOL)
               isTrailing = FALSE;
            else
               isTrailing = TRUE;
        }
    }
}

Note: you don't have to check for EOF in inner loop because isspace(EOF) returns false.

Hello, is me again, im trying to improve my program with another function
it should print as many senteces on one line in the output, as user will enter as the parameter in the command line


sentenece is characterized with sign '.'
if you have sentences wchich ends with '...' then consider the last dot as an end of the sentence
but if you have '. . . ' (three dots with spaces after each one) then consider this as three different sentences

so i have this code, - i tried altered code that you suggested me in this topic
at first, ive just tried to do the basic thing, that it should count dots in the input
and if the number of dots equal the parameter then it should put new line

void ParameterSPL(int argc, char *argv[]) //spl means sentences per line
{
    unsigned long int counter = 0;
    unsigned long int pom; 
    int c;
    int start= TRUE;
    int spaceNeeded=TRUE;

    pom = SpracujParameter(argc, argv);
// in variable pom there is a number of sentences wich should be print on one 
// line in the output, in function SpracujParameter i used strotoul conversion
                                                                    

      while ( (c = getchar() ) != EOF )
    {

        if (isspace(c))
        {
          spaceNeeded = FALSE;
          while ( (c = getchar() ) != EOF && isspace(c))
          {}
        }
        if (c == '.') // if there is an dot in the input
        {
          counter++; // then increase the variable counter
          }
          if (c != EOF)
          {
                if (start == FALSE && spaceNeeded == FALSE)
                {
                       putchar(' ');
                }
                       spaceNeeded = TRUE;
                putchar(c);
                if (counter == pom) // 
                {
                  putchar('\n'); // put new line
                  counter = 0; // reset the counter
                  }
                if(c == '\n')
                     start = TRUE;
                else
                     start = FALSE;
          }
    }
  }

so and the problem is here, i will demonstrate it on the input and outputs i have been testing

i entered number 3 as parameter

input

Tak teda vsetci vieme. Ze sa nemam dobre. Vsetko su sracky. Veronika na mna kasle.
Nechapem preco to robi. vy hej ?. ja teda nie. ved ma lubi. aspon tak vravi. hm. cele je to divne. chcem ju pri sebe.
a nie v pici daleko. preco za mnou nemoze dojst. preco za mnou nemoze dojst ked vravi ze ma lubi.

output

Tak teda vsetci vieme. Ze sa nemam dobre. Vsetko su sracky.
 Veronika na mna kasle. Nechapem preco to robi. vy hej ?.
 ja teda nie. ved ma lubi. aspon tak vravi.
 hm. cele je to divne. chcem ju pri sebe.
 a nie v pici daleko. preco za mnou nemoze dojst. preco za mnou nemoze dojst ked vravi ze ma lubi.

so as you can see, there is a white space in front of each new sentence, and there should not.... and how to code, that '...' will be recognized as one sentence ended with three dots, and '. . . ' will be recognized as three different sentences, i guess i can make this somehow with using macros, could i ?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.