Consider:
#include <stdio.h>
#include <ctype.h>
int main()
{
const char* input = "Hey ,how are you today ?" ;
const char* chp = input ;
// While not end of input...
while( *chp != '\0' )
{
// Print all regular characters (not space or punctuation)
if( !(isspace( *chp ) || ispunct( *chp )) )
{
putchar( *chp ) ;
chp++ ;
}
// Print all punctuation followed by a space (except at end)
else if( ispunct( *chp ) )
{
putchar( *chp ) ;
chp++ ;
if( *chp != '\0' && !isspace( *chp ) )
{
putchar( ' ' ) ;
}
}
// Is space...
else if( isspace( *chp ) )
{
// Skip all space
while( *chp != '\0' && isspace( *chp ) )
{
chp++ ;
}
// If not end, and not punctuation...
if( *chp != '\0' && !ispunct( *chp ) )
{
// ...insert single space
putchar( ' ' ) ;
}
}
}
return 0;
}
However it is likely that you need to refine your rules more carefully. Perhaps not all punctuation should be treated the same? For example for :
const char* input = "She said \"Hello\"" ;
The output is:
She said" Hello"
which is unlikely to be intended. For that not only would you need to include an exception rule for '"'
, you'd need to account for opening and closing quotes and apply the rule accordingly. An exercise for the reader - I suggest you post a new question if you remain stuck with that.
It gets really complicated if you have a string such as :
She said, "Hey, how are, you today?"
Because then you have ?
and "
together, for ?
you want a rule: "space after punctuation unless next character is also punctuation". But if the ?
and "
are separated by space you have to eliminate that first before making the decision. To be honest, I gave up trying to figure out all the permutations. I would suggest that if you want to do that you perform the transform in multiple passes applying one rule at a time, for example:
- Reduce all multiple spaces to 1 space
- Insert space after punctuation if no space is present, and it is not an opening quote (
'
or "
).
- Remove space between punctuation
- Insert space before opening quote if no space is present.
By having simpler rules (executed in separate functions) and multiple passes, it will be much easier to get right at the expense of efficiency. You can also then easily re-order the application of the rules to get the intended result. For example here rule 4 must be applied after rule 3.