473,394 Members | 1,722 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Remove extra blanks

Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?

Oct 15 '06 #1
34 4041
Registered User wrote:
>
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.

Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
Try this. Notice the absence of string buffers. Should work until
you get over 32767 consecutive blanks.

#include <stdio.h>
int main(void)
{
int blanks, ch;

blanks = 0;
while (EOF != (ch = getchar())) {
if (' ' == ch) {
++blanks;
if (1 == blanks) putchar(' ');
}
else {
putchar(ch);
blanks = 0;
}
}
return 0;
}

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Oct 15 '06 #2
"Registered User" <in*******************@gmail.comwrites:
Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
Much faster & efficient IMO (in most cases I would think) to
malloc a new string, copy the original one into it and then update the
original in place - no repeated shuffling.

strcpy(refCopy,refStr)
char *d=refStr; /*destination*/
char *s=refCopy; /*original string copy - source*/
while(*d++=(ch=*s++))
if(ch==' '){
while((ch=*s++)&&(ch==' ')); /*gobble up following spaces
if (!(*d++=ch)) /* store first non space */
break;
}

Not tested, but you will get the idea.
--
--
Oct 15 '06 #3
CBFalconer wrote:
Registered User wrote:
>I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.

Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?

Try this. Notice the absence of string buffers. Should work until
you get over 32767 consecutive blanks.

#include <stdio.h>
int main(void)
{
int blanks, ch;

blanks = 0;
while (EOF != (ch = getchar())) {
if (' ' == ch) {
++blanks;
if (1 == blanks) putchar(' ');
}
else {
putchar(ch);
blanks = 0;
}
}
return 0;
}
Or maybe..

#include <stdio.h>
int main(void) {
int ch, last = 0;
while ((ch = getchar()) != EOF) {
if (!(ch == ' ' && last == ch))
putchar(ch);
last = ch;
}
return 0;
}

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Oct 15 '06 #4
Joe Wright <jo********@comcast.netwrites:
CBFalconer wrote:
>Registered User wrote:
>>I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.

Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
Try this. Notice the absence of string buffers. Should work until
you get over 32767 consecutive blanks.
#include <stdio.h>
int main(void)
{
int blanks, ch;
blanks = 0;
while (EOF != (ch = getchar())) {
if (' ' == ch) {
++blanks;
if (1 == blanks) putchar(' ');
}
else {
putchar(ch);
blanks = 0;
}
}
return 0;
}
Or maybe..

#include <stdio.h>
int main(void) {
int ch, last = 0;
while ((ch = getchar()) != EOF) {
if (!(ch == ' ' && last == ch))
putchar(ch);
last = ch;
}
return 0;
}
The problem is that I think the OP was only using fgets to get a sample
string - it is therefore not the excercise to simplify the algorithm
using getchar() or whatever.

His spec was to remove excess spaces from a string.

I could be wrong : if not, see other post.

--
Oct 15 '06 #5

Richard wrote:
Joe Wright <jo********@comcast.netwrites:
CBFalconer wrote:
Registered User wrote:
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.

Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
Try this. Notice the absence of string buffers. Should work until
you get over 32767 consecutive blanks.
#include <stdio.h>
int main(void)
{
int blanks, ch;
blanks = 0;
while (EOF != (ch = getchar())) {
if (' ' == ch) {
++blanks;
if (1 == blanks) putchar(' ');
}
else {
putchar(ch);
blanks = 0;
}
}
return 0;
}
Or maybe..

#include <stdio.h>
int main(void) {
int ch, last = 0;
while ((ch = getchar()) != EOF) {
if (!(ch == ' ' && last == ch))
putchar(ch);
last = ch;
}
return 0;
}

The problem is that I think the OP was only using fgets to get a sample
string - it is therefore not the excercise to simplify the algorithm
using getchar() or whatever.

His spec was to remove excess spaces from a string.
Yes, that's what I want to do: remove excess spaces from a given string.

Oct 15 '06 #6
On Sun, 2006-10-15 at 04:22 -0700, Registered User wrote:
Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
Well, use spaces instead of tabs. I've replaced yours with two-space
indents. (On USENET, tabs can be filtered out or displayed incorrectly.)
>
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
It'd be better to use two strings, an input and an output. That way, you
can make a function that accepts string literals. (String literals are
non-mutable, in case you didn't know.)

If you use two strings, you can simply copy each character until you hit
a space. Then, copy a space, skip to the next non-whitespace character,
and continue as you were.

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>

Oct 15 '06 #7

Registered User wrote:
Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
just as an alternative,

/*removes extra blanks from a string, replaces two or more consecutive
blanks in a string by a single space.*/
int sglspc(char *s){
int n;
char *p, *p2;

n = 0;
p = s;

while (*p){
if (*p == ' ' && *(p + 1) == *p){
n++;
p2 = p;

while (*p2){
*p2 = *(p2 + 1);
p2++;
}
} else
p++;
}

return n;
}

#include <stdio.h>
#include <string.h>
int main(void){
char s[] = " hello world ";
int n;

printf("%s, %d\n", s, strlen(s));
n = sglspc(s);
printf("%s, %d, (-%d)\n", s, strlen(s), n);

return 0;
}

$ a.out
hello world , 27
hello world , 13, (-14)

$

Oct 15 '06 #8
Richard <rg****@gmail.comwrites:
"Registered User" <in*******************@gmail.comwrites:
>Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?

Much faster & efficient IMO (in most cases I would think) to
malloc a new string, copy the original one into it and then update the
original in place - no repeated shuffling.

strcpy(refCopy,refStr)
char *d=refStr; /*destination*/
char *s=refCopy; /*original string copy - source*/
while(*d++=(ch=*s++))
if(ch==' '){
while((ch=*s++)&&(ch==' ')); /*gobble up following spaces
if (!(*d++=ch)) /* store first non space */
break;
}

Not tested, but you will get the idea.
Idiocy alert : you dont even need the copy thus saving fannying around
with mallocs etc. Just set s to be d. This is fine since s is always
the same or, after the first double space, ahead of the destination pointer.

Whoops.
--
Oct 15 '06 #9
The strtrim function from the lcc-win32 compiler looks like this:
#include <ctype.h>
int strtrim(char *str)
{
char *src = str,*dst = str,*start = str;

while (isspace(*src)) // Skip leading spaces
src++;
do {
// Copy non space chars
while (*src && !isspace(*src))
*dst++ = *src++;
// Here we have either zero or a space
if (*src) {
*dst++ = *src++; // Copy first space
while (isspace(*src) && // Skip the rest
*src != '\n' && *src != '\r')
src++;
}
} while (*src);
// If the last character before a newline is space, delete it.
if (dst != start && isspace(dst[-1]) && dst[-1] != '\n')
dst--;
*dst = 0;
return dst - src;
}
Oct 15 '06 #10
This si as simple as it gets, i think...
Problem with this code is that it adds a SPACE character at the end of
a file.

====================Start paste=======================
#include<stdio.h>
#include<string.h>
#define MAX_LINE_LENGHTH 200
#define MAX_FN_LENGTH 20

int main(void){
char filein[MAX_FN_LENGTH], fileout[MAX_FN_LENGTH],
s1[MAX_LINE_LENGHTH], *s2;
FILE *ff1, *ff2;

printf("Enter input file: ");
scanf("%s",filein);
printf("\nEnter output file: ");
scanf("%s",fileout);
ff1=fopen(filein,"r");
ff2=fopen(fileout,"w");

while(!feof(ff1)){
fgets(s1,MAX_LINE_LENGHTH,ff1);
s2=strtok(s1," ");
fprintf(ff2,"%s ",s2);
while((s2=strtok('\0'," "))!=NULL){
if(s2[strlen(s2)-1]!='\n')
fprintf(ff2,"%s ",s2);
else
fprintf(ff2,"%s",s2);
}
}

fclose(ff1);
fclose(ff2);
return 0;
}
===================End Paste=================

Oct 16 '06 #11
Richard wrote:
Richard <rg****@gmail.comwrites:
"Registered User" <in*******************@gmail.comwrites:
Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

Here's what I did:

#include <stdio.h>
#include <string.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/

if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/

if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/

i=j;
}
puts(s);

return 0;
}

The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
Much faster & efficient IMO (in most cases I would think) to
malloc a new string, copy the original one into it and then update the
original in place - no repeated shuffling.

strcpy(refCopy,refStr)
char *d=refStr; /*destination*/
char *s=refCopy; /*original string copy - source*/
while(*d++=(ch=*s++))
if(ch==' '){
while((ch=*s++)&&(ch==' ')); /*gobble up following spaces
if (!(*d++=ch)) /* store first non space */
break;
}

Not tested, but you will get the idea.
Thanks for the idea, Richard. I've implemented something similar:

#include <stdio.h>
#define MAX 80
int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=j=0;
while(s[i++]=s[j++])
{
if (s[i-1]==' ') /*If the last character copied was a space*/
{
while (s[j++]==' ') /*gobble up following spaces */
;
if ((s[i++]=s[j-1])=='\0')
break;
}
}
puts(s);
return 0;
}
>
Idiocy alert : you dont even need the copy thus saving fannying around
with mallocs etc. Just set s to be d. This is fine since s is always
the same or, after the first double space, ahead of the destination pointer.

Whoops.
Yeah, that was funny.

Oct 16 '06 #12
Actually made the body of my lst post too complex, here is the bug
free, simpler version.

===================Start paste===============
#include<stdio.h>
#include<string.h>
#define MAX_LINE_LENGHTH 200
#define MAX_FN_LENGTH 20

int main(void){
char filein[MAX_FN_LENGTH], fileout[MAX_FN_LENGTH],
s1[MAX_LINE_LENGHTH], *s2;
FILE *ff1, *ff2;

printf("Enter input file: ");
scanf("%s",filein);
printf("\nEnter output file: ");
scanf("%s",fileout);
ff1=fopen(filein,"r");
ff2=fopen(fileout,"w");

while(!feof(ff1)){
fgets(s1,MAX_LINE_LENGHTH,ff1);
s2=strtok(s1," ");
fprintf(ff2,"%s",s2);
while((s2=strtok('\0'," "))!=NULL){
fprintf(ff2," %s",s2);
}
}

fclose(ff1);
fclose(ff2);
return 0;
}
=================End Paste====================

This one has no bugs either.

Oct 16 '06 #13
fr**********@yahoo.com said:
This si as simple as it gets, i think...
Problem with this code is that it adds a SPACE character at the end of
a file.

====================Start paste=======================
#include<stdio.h>
#include<string.h>
#define MAX_LINE_LENGHTH 200
#define MAX_FN_LENGTH 20

int main(void){
char filein[MAX_FN_LENGTH], fileout[MAX_FN_LENGTH],
s1[MAX_LINE_LENGHTH], *s2;
FILE *ff1, *ff2;

printf("Enter input file: ");
scanf("%s",filein);
ThisIsWhatITypeInResponseToYourInputRequest. That's mischievous, but not
malicious. If you use "%s" with scanf, you open yourself up to malice as
well as mischief.

printf("\nEnter output file: ");
scanf("%s",fileout);
Same applies.
ff1=fopen(filein,"r");
ff2=fopen(fileout,"w");
What if these operations fail?
>
while(!feof(ff1)){
fgets(s1,MAX_LINE_LENGHTH,ff1);
This code will process the last line twice. Instead, use:

while(fgets(s1, MAX_LINE_LENGHTH, ff1) != NULL)
{

or better still:

while(fgets(s1, sizeof s1, ff1) != NULL)
{

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 16 '06 #14
lovecreatesbea...@gmail.com wrote:
Registered User wrote:
>>Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.

just as an alternative,

/*removes extra blanks from a string, replaces two or more consecutive
blanks in a string by a single space.*/
int sglspc(char *s){
int n;
char *p, *p2;

n = 0;
p = s;

while (*p){
if (*p == ' ' && *(p + 1) == *p){
n++;
p2 = p;

while (*p2){
*p2 = *(p2 + 1);
p2++;
}
} else
p++;
}

return n;
}

#include <stdio.h>
#include <string.h>
int main(void){
char s[] = " hello world ";
int n;

printf("%s, %d\n", s, strlen(s));
n = sglspc(s);
printf("%s, %d, (-%d)\n", s, strlen(s), n);

return 0;
}
int sglspc(char *s){
int n = 0;
char *d = s;
while (*d++ = *s)
while (*s++ == ' ' && *s == ' ') n++;
return n;
}

As part of a real program, it would be longer.

--
Thad
Oct 16 '06 #15
Can any one make it even shorter than this:
===================Start Paste===========================
#include<stdio.h>
#include<string.h>
#define MAX_LINE_LENGHTH 200

int main(int argc[], char *argv[]){
char s1[MAX_LINE_LENGHTH], *s2;
FILE *ff1, *ff2;

ff1=fopen(argv[1],"r");
ff2=fopen(argv[2],"w");

while(fgets(s1,MAX_LINE_LENGHTH,ff1)!=NULL){
s2=strtok(s1," ");
fprintf(ff2,"%s",s2);
while((s2=strtok('\0'," "))!=NULL) fprintf(ff2," %s",s2);
}

fclose(ff1);
fclose(ff2);
return 0;
}
=======================End Paste==========================

Oct 16 '06 #16
Thad Smith wrote:
lovecreatesbea...@gmail.com wrote:
Registered User wrote:
>Hi experts,
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.
just as an alternative,

/*removes extra blanks from a string, replaces two or more consecutive
blanks in a string by a single space.*/
int sglspc(char *s){
int n;
char *p, *p2;

n = 0;
p = s;

while (*p){
if (*p == ' ' && *(p + 1) == *p){
n++;
p2 = p;

while (*p2){
*p2 = *(p2 + 1);
p2++;
}
} else
p++;
}

return n;
}

#include <stdio.h>
#include <string.h>
int main(void){
char s[] = " hello world ";
int n;

printf("%s, %d\n", s, strlen(s));
n = sglspc(s);
printf("%s, %d, (-%d)\n", s, strlen(s), n);

return 0;
}
Your code is better than mine, thanks for sharing. I've learnt a lot
from your code.
int sglspc(char *s){
int n = 0;
char *d = s;
H&S5 says that initializations would be skipped. So I use explicit
assignments there. Do understand it correctly?
while (*d++ = *s)
while (*s++ == ' ' && *s == ' ') n++;
Excellent! It's clearer and more understandable and readable than the
one in my last post. At the very start, frankly, I don't understand it
- stupid me - but catch it finally.
return n;
}

As part of a real program, it would be longer.
Should it check in real program whether the parameter pointer s is null
or not inside this function body itself?

Oct 16 '06 #17
This version does not need the string.h header file

================Start Paste===================

#include<stdio.h>
#define MAX_LINE_LENGHTH 200

int main(int argc[], char *argv[]){
char s1[MAX_LINE_LENGHTH], ch=' ';
FILE *ff1, *ff2;
int i1;

ff1=fopen(argv[1],"r");
ff2=fopen(argv[2],"w");

while(fgets(s1,MAX_LINE_LENGHTH,ff1)!=NULL){
i1=-1;
while(s1[(i1++)+1]!=NULL){
if(s1[i1]!=' ' || s1[i1]!=ch)
ch=fputc(s1[i1],ff2);
}
}
fclose(ff1);
fclose(ff2);
return 0;
}

====================End Paste========================

Oct 16 '06 #18

lovecreatesbea...@gmail.com wrote:
Thad Smith wrote:
<snip>
>
int sglspc(char *s){
int n = 0;
char *d = s;

H&S5 says that initializations would be skipped. So I use explicit
assignments there. Do understand it correctly?
Sorry, it is not complete.

I remember that H&S5 says for anto variables, their initializations
will be skipped. Do I understand it correctly?

Oct 16 '06 #19
lovecreatesbea...@gmail.com wrote:
Thad Smith wrote:
>>lovecreatesbea...@gmail.com wrote:
>>>Registered User wrote:

I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.
>>int sglspc(char *s){
int n = 0;
char *d = s;


H&S5 says that initializations would be skipped. So I use explicit
assignments there. Do understand it correctly?
No, initializations of auto variables are performed on encountering the
declarations in the control flow. I don't have H&S to refer to. Maybe
they meant that an initialization of static variables would only occur
once, not each invocation.
>
> while (*d++ = *s)
while (*s++ == ' ' && *s == ' ') n++;
return n;
}

As part of a real program, it would be longer.


Should it check in real program whether the parameter pointer s is null
or not inside this function body itself?
I wouldn't do that, but would instead clearly document the parameter
requirements and return value. I would also add more to make the
program a little easier to read and use my own brace rules:

while ((*d++ = *s) != '\0') {
while (*s++ == ' ' && *s == ' ') n++;
}
return n;
}

The explicit comparison with '\0' makes the intent clearer and
eliminates a warning from some compilers. The unneeded braces is my own
rule to use braces if the statement following a for, while, if, or else
is on a following line (otherwise I have forgotten that there is no
brace and added another indented line below the original -- oops!).

--
Thad
Oct 16 '06 #20

Thad Smith wrote:
lovecreatesbea...@gmail.com wrote:
Thad Smith wrote:
>lovecreatesbea...@gmail.com wrote:
Registered User wrote:

I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.
>int sglspc(char *s){
int n = 0;
char *d = s;

H&S5 says that initializations would be skipped. So I use explicit
assignments there. Do understand it correctly?

No, initializations of auto variables are performed on encountering the
declarations in the control flow. I don't have H&S to refer to. Maybe
they meant that an initialization of static variables would only occur
once, not each invocation.
Thad, thanks for the clarification of the usage of the initialization
of auto variables.
while (*d++ = *s)
while (*s++ == ' ' && *s == ' ') n++;
return n;
}

As part of a real program, it would be longer.

Should it check in real program whether the parameter pointer s is null
or not inside this function body itself?

I wouldn't do that, but would instead clearly document the parameter
requirements and return value. I would also add more to make the
program a little easier to read and use my own brace rules:

while ((*d++ = *s) != '\0') {
while (*s++ == ' ' && *s == ' ') n++;
}
return n;
}

The explicit comparison with '\0' makes the intent clearer and
eliminates a warning from some compilers. The unneeded braces is my own
rule to use braces if the statement following a for, while, if, or else
is on a following line (otherwise I have forgotten that there is no
brace and added another indented line below the original -- oops!).
Regards

Oct 16 '06 #21
Registered User wrote:
Richard wrote:
>Joe Wright <jo********@comcast.netwrites:
>>CBFalconer wrote:
Registered User wrote:
I'm trying to write a program that replaces two or more consecutive
blanks in a string by a single blank.
>
Here's what I did:
>
#include <stdio.h>
#include <string.h>
#define MAX 80
>
int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=strlen(s);
while(i)
{
while (s[--i]!=' ' && i>0) /*Find the last space*/
;
j=i;
while (s[--j]==' ' && j>0) /*Go to the last non-space*/
; /*char before s[i]*/
>
if (s[j]!=' ')
j++; /*Increment j so that s[j] is a space*/
>
if (j<i) /*If extra spaces have been found, remove*/
while (s[i]) /*them by left shifting */
s[++j]=s[++i]; /*the characters on the right*/
>
i=j;
}
puts(s);
>
return 0;
}
>
The program works fine, but I have a feeling that I've made it
unnecessarily complicated.
>
Can anyone suggest ways on which I can improve upon the code? Is there
a better algorithm?
Try this. Notice the absence of string buffers. Should work until
you get over 32767 consecutive blanks.

#include <stdio.h>
int main(void)
{
int blanks, ch;
blanks = 0;
while (EOF != (ch = getchar())) {
if (' ' == ch) {
++blanks;
if (1 == blanks) putchar(' ');
}
else {
putchar(ch);
blanks = 0;
}
}
return 0;
}

Or maybe..

#include <stdio.h>
int main(void) {
int ch, last = 0;
while ((ch = getchar()) != EOF) {
if (!(ch == ' ' && last == ch))
putchar(ch);
last = ch;
}
return 0;
}

The problem is that I think the OP was only using fgets to get a
sample string - it is therefore not the excercise to simplify the
algorithm using getchar() or whatever.

His spec was to remove excess spaces from a string.

Yes, that's what I want to do: remove excess spaces from a given
string.
Oh very well. Try this:

#include <stdio.h>

/* ----------------- */

static void deblank(char *d, const char *s)
{
char last;

last = ' '; /* to elide all leading blanks, else use '\0' */
while (*s) {
if ((' ' != *s) || (' ' != last)) *d++ = *s;
last = *s++;
}
*d = '\0';
}

/* ----------------- */

int main(void)
{
char s[] = " A string with excess blanks.";
char d[sizeof s];

puts(s);
deblank(d, s);
puts(d);
return 0;
}

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Oct 16 '06 #22
On Mon, 2006-10-16 at 03:14 -0400, CBFalconer wrote:
Oh very well. Try this:

#include <stdio.h>

/* ----------------- */

static void deblank(char *d, const char *s)
{
char last;

last = ' '; /* to elide all leading blanks, else use '\0' */
while (*s) {
if ((' ' != *s) || (' ' != last)) *d++ = *s;
last = *s++;
}
*d = '\0';
}

/* ----------------- */

int main(void)
{
char s[] = " A string with excess blanks.";
char d[sizeof s];

puts(s);
deblank(d, s);
puts(d);
return 0;
}
I think that a useful extension would be to have deblank() return the
number of characters stripped (to help the caller reallocate if
necessary.

I'm not sure who that's best left as an exercise to.

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>

Oct 16 '06 #23
Andrew Poelstra wrote:
On Mon, 2006-10-16 at 03:14 -0400, CBFalconer wrote:
>Oh very well. Try this:

#include <stdio.h>

/* ----------------- */

static void deblank(char *d, const char *s)
{
char last;

last = ' '; /* to elide all leading blanks, else use '\0' */
while (*s) {
if ((' ' != *s) || (' ' != last)) *d++ = *s;
last = *s++;
}
*d = '\0';
}

/* ----------------- */

int main(void)
{
char s[] = " A string with excess blanks.";
char d[sizeof s];

puts(s);
deblank(d, s);
puts(d);
return 0;
}

I think that a useful extension would be to have deblank() return
the number of characters stripped (to help the caller reallocate
if necessary.
In the interest of vertical economy and obfuscation, try:

*/ Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++) {
if ((' ' != *s) || (' ' != last)) *d++;
}
return d - p;
}

This cat has been sufficiently skinned.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Oct 16 '06 #24

"Registered User" <in*******************@gmail.comwrote in message
news:11*********************@h48g2000cwc.googlegro ups.com...
Richard wrote:
Richard <rg****@gmail.comwrites:
"Registered User" <in*******************@gmail.comwrites:
>
>Hi experts,
>I'm trying to write a program that replaces two or more consecutive
>blanks in a string by a single blank.
>>
>Here's what I did:
>>
>#include <stdio.h>
>#include <string.h>
>#define MAX 80
>>
>int main()
>{
>char s[MAX];
>int i, j;
>fgets(s, MAX, stdin);
>i=strlen(s);
>while(i)
>{
>while (s[--i]!=' ' && i>0) /*Find the last space*/
>;
>j=i;
>while (s[--j]==' ' && j>0) /*Go to the last non-space*/
>; /*char before s[i]*/
>>
>if (s[j]!=' ')
>j++; /*Increment j so that s[j] is a space*/
>>
>if (j<i) /*If extra spaces have been found, remove*/
>while (s[i]) /*them by left shifting */
>s[++j]=s[++i]; /*the characters on the right*/
>>
>i=j;
>}
>puts(s);
>>
>return 0;
>}
>>
>The program works fine, but I have a feeling that I've made it
>unnecessarily complicated.
>>
>>
>Can anyone suggest ways on which I can improve upon the code? Is
there
>a better algorithm?
>>
>
Much faster & efficient IMO (in most cases I would think) to
malloc a new string, copy the original one into it and then update the
original in place - no repeated shuffling.
>
strcpy(refCopy,refStr)
char *d=refStr; /*destination*/
char *s=refCopy; /*original string copy - source*/
while(*d++=(ch=*s++))
if(ch==' '){
while((ch=*s++)&&(ch==' ')); /*gobble up following
spaces
if (!(*d++=ch)) /* store first non space */
break;
}
>
Not tested, but you will get the idea.
>

Thanks for the idea, Richard. I've implemented something similar:

#include <stdio.h>
#define MAX 80
int main()
{
char s[MAX];
int i, j;
fgets(s, MAX, stdin);
i=j=0;
while(s[i++]=s[j++])
{
if (s[i-1]==' ') /*If the last character copied was a space*/
{
while (s[j++]==' ') /*gobble up following spaces */
;
if ((s[i++]=s[j-1])=='\0')
break;
}
}
puts(s);
return 0;
}

Idiocy alert : you dont even need the copy thus saving fannying around
with mallocs etc. Just set s to be d. This is fine since s is always
the same or, after the first double space, ahead of the destination
pointer.

Whoops.

Yeah, that was funny.
A variant for your perusal:

#include <stdio.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j, k;
fgets(s, MAX, stdin);

for(i=0,j=0,k=0;s[j];i++,j++,k=j)
{
while(s[j]==' ')
j++;
if(k!=j)
j--;
s[i]=s[j];
}
s[i]='\0';

printf("|%s|\n",s);
return 0;
}
Rod Pemberton
Oct 21 '06 #25
Rod Pemberton said:

<snip>
>
A variant for your perusal:

#include <stdio.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j, k;
fgets(s, MAX, stdin);

for(i=0,j=0,k=0;s[j];
Undefined behaviour if fgets returned NULL.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 21 '06 #26
Richard Heathfield wrote:
Rod Pemberton said:

<snip>
>>
A variant for your perusal:

#include <stdio.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j, k;
fgets(s, MAX, stdin);

for(i=0,j=0,k=0;s[j];

Undefined behaviour if fgets returned NULL.
I repeat my earlier suggestion. In the interest of vertical
economy and obfuscation, try:

/* Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) *d++;
return d - p;
}

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Oct 21 '06 #27
CBFalconer said:

<snip>
>
/* Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) *d++;
return d - p;
}
I recommend accepting size_t len, the maximum number of bytes that can
legitimately be written to the memory whose start is pointed to by d.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 21 '06 #28
Richard Heathfield wrote:
CBFalconer said:

<snip>
>>
/* Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) *d++;
return d - p;
}

I recommend accepting size_t len, the maximum number of bytes
that can legitimately be written to the memory whose start is
pointed to by d.
Huh? I do NOT understand the comment. It returns size_t.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Oct 21 '06 #29
CBFalconer wrote:
Richard Heathfield wrote:
CBFalconer said:

<snip>
>
/* Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) *d++;
return d - p;
}
I recommend accepting size_t len, the maximum number of bytes
that can legitimately be written to the memory whose start is
pointed to by d.

Huh? I do NOT understand the comment. It returns size_t.
I think it's intended to avoid buffer overflows (fgets() vs. gets()).
You may not really need it, though, since no more than strlen(s)+1
characters can ever be written, and that much memory should be
available when the function is called.

Oct 21 '06 #30
CBFalconer said:
Richard Heathfield wrote:
>CBFalconer said:

<snip>
>>>
/* Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) *d++;
return d - p;
}

I recommend accepting size_t len, the maximum number of bytes
that can legitimately be written to the memory whose start is
pointed to by d.

Huh? I do NOT understand the comment. It returns size_t.
By the time the function returns, it's a little late to worry about whether
it overwrote memory the program doesn't own.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 21 '06 #31
On Sat, 2006-10-21 at 05:52 +0000, Richard Heathfield wrote:
Rod Pemberton said:

<snip>

A variant for your perusal:

#include <stdio.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j, k;
fgets(s, MAX, stdin);

for(i=0,j=0,k=0;s[j];

Undefined behaviour if fgets returned NULL.
Why?

I can see how the /contents/ of s[] could be undefined, but I'm
clearly missing something.

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>

Oct 21 '06 #32
On Sat, 2006-10-21 at 05:52 +0000, Richard Heathfield wrote:
Rod Pemberton said:

<snip>

A variant for your perusal:

#include <stdio.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j, k;
fgets(s, MAX, stdin);

for(i=0,j=0,k=0;s[j];

Undefined behaviour if fgets returned NULL.
--
Andrew Poelstra <http://www.wpsoftware.net/projects/>

Oct 21 '06 #33
Richard Heathfield wrote:
CBFalconer said:
>Richard Heathfield wrote:
>>CBFalconer said:

<snip>

/* Remove multiple blanks, return strlen(d) */
static size_t deblank(char *d, const char *s)
{
char last, *p;

for (p = d, last = ' '; (*d = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) *d++;
return d - p;
}

I recommend accepting size_t len, the maximum number of bytes
that can legitimately be written to the memory whose start is
pointed to by d.

Huh? I do NOT understand the comment. It returns size_t.

By the time the function returns, it's a little late to worry
about whether it overwrote memory the program doesn't own.
I see what you are getting at. In the original use the caller
created the destination using sizeof(source), which guaranteed
sufficient space, and allowed a string constant. How about:

/* Remove multiple blanks in place, return strlen(src) */
static size_t deblank(char *src)
{
char last, *p, *s;

for (p = s = src, last = ' '; (*p = *s); last = *s++)
if ((' ' != *s) || (' ' != last)) p++;
return p - src;
}

I still think it is nicely obfuscated.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Oct 22 '06 #34
Andrew Poelstra wrote:
On Sat, 2006-10-21 at 05:52 +0000, Richard Heathfield wrote:
>Rod Pemberton said:

<snip>
>>>
A variant for your perusal:

#include <stdio.h>
#define MAX 80

int main()
{
char s[MAX];
int i, j, k;
fgets(s, MAX, stdin);

for(i=0,j=0,k=0;s[j];

Undefined behaviour if fgets returned NULL.

Why? I can see how the /contents/ of s[] could be undefined, but
I'm clearly missing something.
Because if fgets fails it writes nothing into the uninitialized
s[], which therefore may not have a terminating '\0', and not be a
valid string. From N869:

[#3] The fgets function returns s if successful. If end-of-
file is encountered and no characters have been read into
the array, the contents of the array remain unchanged and a
null pointer is returned. If a read error occurs during the
operation, the array contents are indeterminate and a null
pointer is returned.

Note that initializing s to an empty string will not suffice,
because of the read error provision.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Oct 22 '06 #35

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: john | last post by:
I am using this to remove everything except the 0-9 and a-z characters, but I also want to remove blanks spaces as well(yes even ones in between words) $strippedtext =...
10
by: Hermann.Richter | last post by:
Is there any way to remove automatically all blank chars from the html sent to the client?? Example: ---------------------------------------------------------------- <? echo "HTML tags...
3
by: afr02hrs | last post by:
Hi Experts I am trying to get the following program running correctly. I would like to be able to input a line of text containing multiple space characters between words and have the program...
4
by: eBob.com | last post by:
I have a RichTextBox in which I'd like blanks to appear different from nothing. Imagine a file which does not fill up the RTB. You can't tell how many, if any, blanks might follow the last...
4
by: Sam | last post by:
Could someone help me by providing a formula that will change the formatting, in a query of a phone number.. The data in the table is formatted as (123) 456-7890. I need the field to be 123456789...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.