By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,244 Members | 1,972 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,244 IT Pros & Developers. It's quick & easy.

Remove extra blanks

P: n/a
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
Share this Question
Share on Google+
34 Replies


P: n/a
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

P: n/a
"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

P: n/a
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

P: n/a
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

P: n/a

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

P: n/a
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

P: n/a

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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a

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

P: n/a
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

P: n/a

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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a

"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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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 discussion thread is closed

Replies have been disabled for this discussion.