Removing spaces from strings - c

I tried to write a function that gets a string and creates a new string but without multiple spaces (leaving only 1 space between words).
So far I wrote this, but for some reason it crashs and the debugger shows nothing.
I also don't know where do I need to put the free function...
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* upgradestring(char* oldtext);
int main()
{
char str1[] = "Chocolate Can Boost Your Workout" ;
printf("%s\n", str1);
printf("\n%s\n", upgradestring(str1));
return 0;
}
char* upgradestring(char* oldtext)
{
int i,j, count = 1;
char *newstr;
for (i = 0; oldtext[i] != '\0'; i++)
{
if (oldtext[i] != ' ')
count++;
else if (oldtext[i - 1] != ' ')
count++;
}
newstr = (char*)malloc(count * sizeof(char));
if (newstr == NULL)
exit(1);
for (i = 0, j = 0; (oldtext[i] != '\0')|| j<(count+1); i++)
{
if (oldtext[i] != ' ')
{
newstr[j] = oldtext[i];
j++;
}
else if (oldtext[i - 1] != ' ')
{
newstr[j] = oldtext[i];
j++;
}
}
return newstr;
}

You're addressing [i-1] and it's not within the range of the original array if i==0.
Here's how you could do it:
Simply copy one by one and if the char is ' ', keep skipping while it is ' ', otherwise advance by one.
static size_t newlen(char const *o)
{
size_t r=0;
while(*o){
r++;
if(*o==' ')
while(*o==' ')
o++;
else
o++;
}
return r;
}
char *upgradestring(char const *o)
{
char *r, *p;
size_t len = newlen(o);
if( 0==(r = malloc(len+1)))
return 0;
r[len]=0;
for(p=r;*o;){
*p++=*o;
if(*o==' ')
while(*o==' ')
o++;
else
o++;
}
return r;
}
int main()
{
char str1[] = "Chocolate Can Boost Your Workout" ;
char *new;
printf("%s\n", str1);
if(0 == (new = upgradestring(str1)))
return 1;
printf("%s\n", new);
free(new);
}
Failures to allocate are best signalled by return codes (you wouldn't want a library function to abort your program if it fails).
In order to be able to free the returned string, you first must capture it in a variable.

Good attempt, but let's focus on when you need to free your memory. You allocate dynamically the memory inside the function, then call the function inside a printf, which will allow the string to print, but how will you deallocate it? Use a pointer to assign the return value of your function, print it, and then free it!
Moreover, you need to allocate space for as many characters the new string has, plus one for the null terminator, since C strings require that to work smoothly with functions coming from headers, such as printf().
Furthermore, we do not cast what malloc() returns in C, read more here.
Also this:
else if (oldtext[i - 1] != ' ')
should be written as:
else if (i != 0 && oldtext[i - 1] != ' ')
to avoid accessing oldtext[-1] which is out of bounds, when i is 0.
Lastly, the condition you used when populating the new string, would be better with a logical AND, instead of an OR, since we have to stop as soon as either condition is false (we do not want to read past the null terminator of the original string, or past the size of the new string).
Putting everything together, we:
#include <stdio.h>
#include <stdlib.h>
char* upgradestring(char* oldtext)
{
int i, j, count = 0;
// compute 'count'
for(i = 0; oldtext[i]; i++)
{
if (oldtext[i] != ' ')
count++;
else if (i != 0 && oldtext[i - 1] != ' ')
count++;
}
char* newstr = malloc(count + 1); // PLUS ONE for the null terminator
if(!newstr) // check if malloc failed
{
printf("Malloc failed\n");
return 0;
}
// populate 'newstr'. We need to stop when either condition is false
for (i = 0, j = 0; (oldtext[i]) && j<(count+1); i++)
{
// Same as your code
}
// Assign the null terminator!
newstr[j] = '\0';
return newstr;
}
int main(void) {
char str1[] = "Chocolate Can Boost Your Workout" ;
// store the result of your function into 'newstr'
char* newstr = upgradestring(str1);
// print it
printf("%s\n", newstr);
// free it, since you no longer need it!
free(newstr);
return 0;
}
Output:
Chocolate Can Boost Your Workout

#include <stdio.h>
#include <stdlib.h>
char *upgradestring(char *oldtext)
{
size_t len,src,dst,spc;
char *result;
// First pass: count needed size
for (len=src=spc=0;oldtext[src]; src++){
if (oldtext[src] != ' ') spc=0; // non-space needs space
else if(spc++) continue; // skip non first space
len++;
}
result= malloc (1+len);
// Second pass: copy(K&R style)
for (dst=src=spc=0; (result[dst] = oldtext[src]) ; src++){
if (oldtext[src] != ' ') spc=0; // non-space: rest counter
else if(spc++) continue; // skip non-first space
dst++;
}
return result;
}
Simplified version: dont calculate the size in a first pass, but start with the same size as the original, and resize after the second pass. (strdup() can be replaced by strlen+malloc+memcpy)
char * strdup(char *);
char *upgradestring2(char *oldtext)
{
size_t src,dst,spc;
char *result;
result= strdup (oldtext);
// edit the copy, skipping all spaces except the first
for (dst=src=spc=0; result[src] ; src++){
if (result[src] != ' ') spc=0; // non-space:reset counter
else if(spc++) continue; // skip space,except the first
result[dst++] = result[src]; // Copy
}
result[dst] = 0;// terminate string;
// result=realloc(result, dst+1);
return result;
}

For starters neither declaration from the header <string.h> is used in your program. Thus this directive
#include <string.h>
may be removed from the program.
According to the C Standard the function main without parameters shall be declared like
int main( void )
The function with the strange name upgradestring:) does not change the argument. Hence it should be declared like
char* upgradestring( const char* oldtext);
^^^^^
Take into account that the source string can start with blanks. In this case statements like this
else if (oldtext[i - 1] != ' ')
count++;
result in undefined behavior because there is an attempt to access memory beyond the string when i is equal to 0.
The condition
(oldtext[i] != '\0')|| j<(count+1);
should be written at least like
(oldtext[i] != '\0') && j<(count+1);
^^^
though it is enough to check the index j because it can not be greater than the length of the source string.
You forgot to append the result string with the terminating zero '\0'.
Also it is not a good idea to exit the function with this statement
exit(1);
In this case you could just return a null pointer.
And the allocated memory should be freed before exiting the program.
As it has been mentioned before a source string can start with spaces and also have a redundant trailing space. I think it will be logically consistent to exclude them from the result string.
Usually the space character is considered in pair with the tab character. Moreover C has a special function isblank declared in the header <ctype.h> that checks whether a character is a space or a blank. (As far as I know the MS VS does not support this function)
Taking all this into account the function can be defined the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
char * trim_blanks( const char *s )
{
size_t n = 0;
const char *p = s;
// skip leading blanks
while ( *p == ' ' || *p == '\t' ) ++p;
_Bool last_blank = 0;
for ( ; *p; ++p )
{
++n;
if ( ( last_blank = ( *p == ' ' || *p == '\t' ) ) )
{
while ( p[1] == ' ' || p[1] == '\t' ) ++p;
}
}
if ( last_blank ) --n;
char *q = malloc( n + 1 );
if ( q )
{
p = s;
// skip leading blanks
while ( *p == ' ' || *p == '\t' ) ++p;
size_t i = 0;
for ( ; i < n; i++, ++p )
{
q[i] = *p == '\t' ? ' ' : *p;
if ( q[i] == ' ' )
{
while ( p[1] == ' ' || p[1] == '\t' ) ++p;
}
}
q[i] = '\0';
}
return q;
}
int main(void)
{
char s[] = "\t\tChocolate \t Can \t Boost Your Workout ";
printf( "\"%s\"\n", s );
char *t = trim_blanks( s );
printf( "\"%s\"\n", t );
free( t );
return 0;
}
The program output is
" Chocolate Can Boost Your Workout "
"Chocolate Can Boost Your Workout"

Related

C - 3 problems with Segmentation fault when try to return string

I have 3 problems but I think they're essentially the same.
I have 3 functions that are doing something on the String they get as parameter, but when I try to return the result, I get a segmentation fault every time and I can't understand why.
/* the function gets a string, and return the string without blank spaces (is exists) in the end of the string */
char *trimRightSpaces(char *str, unsigned int len)
{
unsigned int i = len;
char *trimStr = NULL;
if(str == NULL)
return NULL;
while(i > 0)
{
if(isspace((int)str[i]))
break;
i--;
}
strncpy(trimStr, str, i-1);
trimStr[i+1] = '\0';
return trimStr;
}
and this function gets labels from my program, that are just strings with ':' character in the end:
/* The function gets a pointer to a string, and returns the name of label without ':' if it's a valid label, NULL if not. */
char *isLabel(char *str)
{
int i;
char tempStr[80];
if(str == NULL)
return NULL;
if(strlen(str) > VALID_LABEL_LENGTH)
return NULL;
for(i = 0; i < strlen(str); i++)
{
if(i == 0)
{
/* if the first letter of the string is not small or capital letter, then it's not a valid label. */
if(!isalpha((int)str[0]))
return NULL;
}
if(i == (strlen(str) - 1))
{
if((int)str[i] != ':') /* check it the word ends with ':', otherwise it's not a valid label */
return NULL;
break;
}
if(!isalnum((int)str[i]))
return NULL;
}
strncpy(tempStr, str, strlen(str) - 1);
if(isLanguageWord(tempStr))
return NULL;
return str;
}
and:
/* the function get a string, and check if it's a valid string: a string inside " ". if it's valid, it returns the string without " ", and NULL otherwise. */
char *validString(char *str)
{
char temp[80];
char *temp2 = NULL;
int i;
if(str == NULL)
return NULL;
if(str[0] != '"' || str[strlen(str) - 1] != '"')
return NULL;
for(i = 1; i < strlen(str) - 1; i++)
{
temp[i] = str[i];
}
temp2 = temp;
return temp2;
}
in the function:
char *validString(char *str)
this statement:
temp2 = temp;
is setting the pointer to point to a local variable.
Then this statement:
return temp2;
is returning that pointer.
The problem is when the local variable 'goes out of scope' (which happens when the function exits.) that stack variable no longer is usable.
accessing the contents of that variable in the calling function is undefined behavior.
I.E. the function can be reduced to :
/* the function get a string, and check if it's a valid string: a string inside " ". if it's valid, it returns the string without " ", and NULL otherwise. */
char *validString(char *str)
{
if(str == NULL)
return NULL;
if(str[0] != '"' || str[strlen(str) - 1] != '"')
return NULL;
return strdup( str );
} // end function: validString
the function: trimRightSpaces() does not actually trim the trailing spaces AND has the same problem as the validString() function. Suggest:
/* the function gets a string, and return the string without blank spaces (is exists) in the end of the string */
char *trimRightSpaces( char *str )
{
if(str == NULL)
return NULL;
size_t i;
for( i = strlen( str ); i > 0 && ' ' == str[i]; i-- );
char *trimstr = strdup( str );
if( trimstr )
trimstr[i] = '\0'; // note: this may need to be [i+1]
return trimstr;
} // end function: trimRightSpaces
the function: islabel() has the same problem AND a few other problems. Suggest:
/* The function gets a pointer to a string, and returns the name of label without ':' if it's a valid label, NULL if not. */
char *isLabel(char *str)
{
if(str == NULL)
return NULL;
if(strlen(str) > VALID_LABEL_LENGTH)
return NULL;
if(isLanguageWord(str)) // note: this 'may' not work, but function not posted so don't know
return NULL;
if(str[strlen( str ) -1] != ':') /* check it the word ends with ':', otherwise it's not a valid label */
return NULL;
/* if the first letter of the string is not small or capital letter, then it's not a valid label. */
if(!isalpha((int)str[0]))
return NULL;
for( size_t i = strlen(str); i ; i-- )
{
if(!isalnum((int)str[i]))
return NULL;
}
return strdup( str );
} // end function: isLabel
There are various problems in your code.
For example, if you declate pointer to char
char *trimStr = NULL; // Points to NULL, cant dereference
char *trimStr; // Uninitialized ptr, cant dereference
then you cant dereference NULL or uninitialized pointer. Whats worse you are trying to copy data inside. What you have to do is allocate enough memory on heap, for example
char *trimStr = malloc(len);
Then you can copy len bytes into trimStr.
Second, you cant return pointer to local variable like you do in validString because after program counter returns back from function, the frame is destroyed and local variable is out of scope -> no more reachable. You have to return pointer to allocated memory on heap or pass an pointer to array to function, where you will fill this array.
Also i can see some logical problems like
if(isspace((int)str[i]))
Where you want to trim spaces but isspace returns non-zero if its space. So you have to negate the expression
if(!isspace((int)str[i]))
Here is the example of trimRightSpaces function.

garbage output after whitespace removing

i've this code:
int i =0;
char * str = "ar bitrary whitespace";
int whitespace=0,index;
for(index = 0;index < strlen(str);index++)
{
if(isspace(str[index]) != 0)
{
whitespace++;
}
}
char * tmp = (char *)calloc(strlen(str)-whitespace +1,sizeof(char));
memset(tmp,'\0',strlen(tmp)+1);
while(i < strlen(str))
{
if(isspace(str[i]) != 0)
{
i++;
continue;
}else if(isspace(str[i]) == 0)
{
strcat(tmp,&str[i]);
i++;
}
}
printf("\nnew string is: %s \n",tmp);
the problem is that the output is a string without the whitespace removed + some garbage character.
I've used memset to null terminate tmp,is there the problem?
The length of the source string could be calculated before this loop
for(index = 0;index < strlen(str);index++)
Otherwise if the code will not be optimized the function strlen will be called for each iteration of the loop. In fact using of the function is redundant for such a task.
This statement
memset(tmp,'\0',strlen(tmp)+1);
does not make sense because the call of calloc already initialized the memory with zeroes.
This statement
strcat(tmp,&str[i]);
also copies blanks from the source string after the position i. So it can write beyond the memory allocated for the array pointed to by the pointer tmp.
You can write a separate function that can look as it is shown in this demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
char * remove_blanks( const char *s )
{
size_t n = 0;
const char *p = s;
do
{
if ( !isspace( ( unsigned char )*p ) ) ++n;
} while ( *p++ );
char *t = malloc( n );
if ( t )
{
char *q = t;
p = s;
do
{
if ( !isspace( ( unsigned char )*p ) ) *q++ = *p;
} while ( *p++ );
}
return t;
}
int main(void)
{
char * str = "ar bitrary whitespace";
printf( "\"%s\"\n", str );
char *t = remove_blanks( str );
printf( "\"%s\"\n", t );
free( t );
}
The program output is
"ar bitrary whitespace"
"arbitrarywhitespace"
this is your problem
memset(tmp,'\0',strlen(tmp)+1);
strlen(tmp) works by looking for '\0' in tmp, you have a chicken and egg situation here.
You should not be doing a memset any way, just tack on a '\0' when you fnish copying
And dont use strcat, instead maintain a pointer to tmp and just do *p = str[i] then increment p
I will not read your question, you overwrite the '\0' terminator for sure.
Now that I read your question, it looks like you need to understand strings and arrays better,
Don't ever write while (i < strlen(str))
Don't use strcat() for adding a single character, you apparently did overwrite the '\0' there. Furthermore, don't ever use strcat() for concatenating more than to pieces of a string.
Also notable,
You memset() after calloc() which already initialized to 0. That means that you are enforcing something that is not necessary, and trying it twice as if it failed the first time which I can guarantee it didn't.
In fact, since you have used calloc() and all bytes pointed to by tmp are 0 then strlen(tmp) will return 0, thus your memset() is equivalent to
tmp[0] = '\0';
and you REALLY don't need initialize tmp except when you finally copy the actual bytes from str.
I always advice against calloc() for strings, because
You don't really need to initialize something twice.
You should be sure your code does take the terminating '\0' into account and not simply assume that it's there because you calloc()ed. That is a bug that you just hide with calloc() but it shows up at some point.
Try this and see if you can understand the reasons for my changes
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
int whitespace;
int length;
char *str = "ar bitrary whitespace";
char *tmp;
whitespace = 0;
for (length = 0; str[length] != '\0'; ++length) {
if (isspace(str[length]) != 0) {
whitespace++;
}
}
tmp = malloc(length - whitespace + 1);
if (tmp == NULL)
return -1;
for (int i = 0, j = 0; str[i] != '\0'; ++i) {
if (isspace(str[i]) != 0)
continue;
tmp[j++] = str[i];
}
tmp[length - whitespace] = '\0';
printf("new string is: %s\n",tmp);
free(tmp);
return 0;
}

Reversing words in a sentence using pointers using c

I'm writing a program in which a function that reverses each word in a string. When I call the function, it will pass the pointer to source string and then return the pointer to modified string.
input: Why always me?
output: yhW syawla ?em
But for some reason, it is not working. No errors. And logic seemed fine to me (i'm not that good with c, btw)
Here's my code:
char *reverse_words(char *source_string)
{
char *startW, *endW;
startW = source_string;
while(*startW != '\0')
{
while(*startW == ' ')
startW++; //Skip multiple spaces in the beginning
endW = startW;
while(*endW != ' ' || *endW != '\0')
endW++;
char *_start = startW;
char *_end = endW - 1;
char temp;
while(_end > _start)
{
temp = *_start;
*_start++ = *_end;
*_end++ = temp;
}
startW = endW;
}
return source_string;
}
void main() {
char *s;
s = malloc(256);
gets(s);
printf("%s\n", s);
char *r = reverse_words(s);
printf("\nReversed String : %s",r);
free(s);
free(r);
}
Also, i'm using codeblocks IDE. After I input my string, it prints it back (scanf and printf in main) and after that, the program stops working.
Any help would be appreciated.
First,
while(*endW != ' ' || *endW != '\0')
is an infinite loop, try this instead:
while(*endW != ' ' && *endW != '\0')
Second,
*_end++ = temp;
should be this:
*_end-- = temp;
In the innermost while(_end > _start) loop you increment both _start and _end. So the condition will never become false. (Well, not until _end overflows.)
I'd recommend figuring out how to do step-by-step debugging in your IDE. Then you can easily understand what exactly goes wrong in a case like this, without simulating the execution in your head.
#include <stdio.h>
#include <stdlib.h>
char *reverse_words(const char *source_string){
const char *startW, *endW;
char *p, *rev = malloc(256);
startW = source_string;
p = rev;
while(*startW != '\0'){
while(*startW == ' ')
*p++ = *startW++;
if(!*startW)
break;
endW = startW;
while(*endW != ' ' && *endW != '\0')
endW++;
const char *endW2 = endW;
do{
*p++ = *--endW;
}while(startW!=endW);
startW = endW2;
}
*p = '\0';
return rev;
}
int main() {
char s[256];
scanf("%255[^\n]", s);
printf("%s,\n", s);
char *r = reverse_words(s);
printf("\nReversed String : %s.", r);
free(r);
return 0;
}

Removing spaces from a string

I am trying to copy from one string to another, but the second string should omit the space. I tried to approach this by saying, if a character in the original string is a space, do not copy it. Instead, copy the next character. However, the program deletes everything after the space. Any ideas?
char deleteSpaces(char phrase[256], int length){
int j, i=0;
char phrase2[length];
for(j=0;j<length;j++){
if(phrase[i]==' '){
phrase2[j]=phrase[i+1];
i++;
}
phrase2[j]=phrase[i];
}
return phrase2;
}
Here is a solution:
void deleteSpaces(char src[], char dst[]){
// src is supposed to be zero ended
// dst is supposed to be large enough to hold src
int s, d=0;
for (s=0; src[s] != 0; s++)
if (src[s] != ' ') {
dst[d] = src[s];
d++;
}
dst[d] = 0;
}
First, you're returning a static tab and this is wrong.
Secondly you don't increment 'i' if there is no space.
And to finish you will copy spaces if there is more than one space in a row. And you do not control if you reach the end of your source.
for(j = 0; j < length; j++)
{
while (src[i] == ' ' && i < length) i++;
if (i < length)
dest[j] = src[i++];
else
{
dest[j] = 0;
break;
}
}
My solution. Arguments and their order are chosen to match strncpy().
#include <ctype.h>
char *strip_whitespace(char *dest, const char *src, size_t n)
{
char *s, *d;
/*
* Copy 'src' to 'dest', omitting whitespace and making sure we don't
* overflow 'dest'.
*/
for(s=src, d=dest; *s && (d-dest)<n; s++) {
if( !isspace(*s) ) {
*d = *s;
d++;
}
}
/* Ensure that dest is NUL terminated in any event */
if( d-dest < n ) {
*d = '\0';
} else {
dest[n-1] = '\0';
}
return dest;
}
As pointed out already you need to allocate a new string and return a pointer to it. This code works:
char* strip (char* input)
{
int loop;
char *output = (char*) malloc (strlen(input));
char *dest = output;
if (output)
{
for (loop=0; loop<strlen(input); loop++)
if (input[loop] != ' ')
*dest++ = input[loop];
*dest = '\0';
}
return output;
}
int main (void)
{
char srcString[] = " this is a test with spaces at the end ";
char* dstString = strip (srcString);
printf ("source string = '%s'\n", srcString);
printf (" dest string = '%s'\n", dstString ? dstString : "malloc failed in strip");
free (dstString);
return 0;
}
Output:
source string = ' this is a test with spaces at the end '
dest string = 'thisisatestwithspacesattheend'
It takes the input string and allocates a destination string the same size which is safe, although wasteful of a few bytes.
The method is simple; only copy a character if it is not a space. After all the characters are copied, I write the terminator on the end and return the pointer.
****WHAT YOU WERE DOING** IS THAT if a character in the original string is a space, do not copy it. Instead, copy the next character. IS NOT A GOOD idea because
Case 1. When multiple spaces are present, it simply discard the first spaces and copies the second one...
Case 2: Your programme copies the string only after space is found,,it is simply skipping the first word of string which doesn't start with spaces.
case 3. You are only returning the character pointed by phrase2[0] as return type is char,and the scope of local variable is limited to only that function....
//the corrected programme
int deleteSpaces(char phrase[256],charphrase2[256])
{
int i,j;
i=j=0;
while(phrase[i]!=NULL){
if(phrase[i]!=' '){
phrase2[j]=phrase[i];
j++;
}
i++;
}//end while
phrase2[j]=phrase[i] //nulcharceter copied
return 0;
}//end deleteSpaces function
I use this:
char input[100], foreval[100];
for(i=0;i<strlen(input);i++){
if(isspace(input[i])){
continue;
}
strncat(foreval,&input[i],1);
}

How do I replace multiple spaces with a single space?

Well I'm looking for a function that reduce multiple space characters ' ' in a string.
For example for string s given :
s="hello__________world____!"
The function must return "hello_world_!"
In python we can do it via regexp simply as:
re.sub("\s+", " ", s);
A version that modifies the string in place, run it on a copy if the original must be preserved:
void compress_spaces(char *str)
{
char *dst = str;
for (; *str; ++str) {
*dst++ = *str;
if (isspace(*str)) {
do ++str;
while (isspace(*str));
--str;
}
}
*dst = 0;
}
There is no such function in the C standard library. One must write a function to do so or use a third-party library.
The following function should do the trick. Use the source string as the destination pointer to perform the operation in place. Otherwise, ensure that the destination buffer is sufficiently sized.
void
simplifyWhitespace(char * dst, const char * src)
{
for (; *src; ++dst, ++src) {
*dst = *src;
if (isspace(*src))
while (isspace(*(src + 1)))
++src;
}
*dst = '\0';
}
void remove_more_than_one_space(char *dest, char *src)
{
int i, y;
assert(dest && src);
for(i=0, y=0; src[i] != '\0'; i++, y++) {
if(src[i] == ' ' && src[i+1] == ' ') {
/* let's skip this copy and reduce the y index*/
y--;
continue;
}
/* copy normally */
dest[y] = src[i];
}
dest[y] = '\0';
}
int main()
{
char src[] = "Hello World ! !! !";
char dest[strlen(src) + 1];
remove_more_than_one_space(dest, src);
printf("%s\n", dest);
}
I just made this, hope it helps.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main()
{
char word[100];
gets(word);
//the word has more than a single space in between the words
int i=0,l,j;
l=strlen(word);
for (i=0;i<l;i++)
{
if(word[i]==' '&&word[i+1]==' ')
{
for(j=i+1;j<l;j++)
word[j]=word[j+1];
}
}
puts(word);
return 0;
}
This code is very simple and it worked like a charm for me. I don't know if this code will have some other problems I haven't come across, but for now this works.
I'm just learning C, so I'm using much more basic code. I'm reading the first chapter of "The C programming language", and I was trying to find the answer to a task set in there.
This is what I came up with:
#include <stdio.h>
int main()
{
/* Set two integers:
c is the character being assessed,
lastspace is 1 if the lastcharacter was a space*/
int c, lastspace;
lastspace = 0;
/* This while loop will exit if the character is EOF
The first "If block" is true if the character is not a space,
and just prints the character
It also tells us that the lastcharacter was not a space
The else block will run if the character is a space
Then the second IF block will run if the last character
was not also a space (and will print just one space) */
while((c = getchar()) != EOF){
if (c != ' '){
putchar(c);
lastspace = 0;
}
else {
if (lastspace != 1)
putchar(c);
lastspace = 1;
}
}
return 0;
}
Hope that helps!
Also, I am well aware that this code is perhaps not optimised, but it should be simple for a beginner like me to understand!
Thanks, Phil
another way of doing this to print only the first occurrence of space until next character comes, here is my brute force solution.
#include<stdio.h>
typedef int bool;
#define True 1
#define False 0
int main()
{
int t;
bool flag = False;
while ((t = getchar()) != EOF)
if (t == ' ' && !flag)
{
putchar(' ');
flag = True; // flag is true for the first occurence of space
}
else if(t == ' '&& flag)
continue;
else
{
putchar(t);
flag = False;
}
return 0;
}
hope it helps.

Resources