Remove extra blanks

Discussion in 'C Programming' started by Registered User, Oct 15, 2006.

  1. 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*/

    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) /*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?
    Registered User, Oct 15, 2006
    #1
    1. Advertising

  2. Registered User

    CBFalconer Guest

    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*/
    >
    > 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) /*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>
    CBFalconer, Oct 15, 2006
    #2
    1. Advertising

  3. Registered User

    Richard Guest

    "Registered User" <> writes:

    > 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*/
    >
    > 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) /*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.


    --


    --
    Richard, Oct 15, 2006
    #3
  4. Registered User

    Joe Wright Guest

    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*/
    >>
    >> 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) /*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 ---
    Joe Wright, Oct 15, 2006
    #4
  5. Registered User

    Richard Guest

    Joe Wright <> writes:

    > 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*/
    >>>
    >>> 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) /*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.

    --
    Richard, Oct 15, 2006
    #5
  6. Richard wrote:
    > Joe Wright <> writes:
    >
    > > 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*/
    > >>>
    > >>> 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) /*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.
    Registered User, Oct 15, 2006
    #6
  7. 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*/
    >
    > 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) /*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/>
    Andrew Poelstra, Oct 15, 2006
    #7
  8. Registered User

    Guest

    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*/
    >
    > 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) /*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, 2006
    #8
  9. Registered User

    Richard Guest

    Richard <> writes:

    > "Registered User" <> writes:
    >
    >> 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*/
    >>
    >> 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) /*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.


    --
    Richard, Oct 15, 2006
    #9
  10. Registered User

    jacob navia Guest

    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;
    }
    jacob navia, Oct 15, 2006
    #10
  11. Registered User

    Guest

    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, 2006
    #11
  12. Richard wrote:
    > Richard <> writes:
    >
    > > "Registered User" <> writes:
    > >
    > >> 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*/
    > >>
    > >> 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) /*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.
    Registered User, Oct 16, 2006
    #12
  13. Registered User

    Guest

    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, 2006
    #13
  14. 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)
    Richard Heathfield, Oct 16, 2006
    #14
  15. Registered User

    Guest

    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, 2006
    #15
  16. Registered User

    Thad Smith Guest

    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
    Thad Smith, Oct 16, 2006
    #16
  17. Registered User

    Guest

    Thad Smith wrote:
    > 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, 2006
    #17
  18. Registered User

    Guest

    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, 2006
    #18
  19. Registered User

    Guest

    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, 2006
    #19
  20. Registered User

    Thad Smith Guest

    wrote:
    > Thad Smith wrote:
    >> 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
    Thad Smith, Oct 16, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. harryos
    Replies:
    3
    Views:
    1,212
    harryos
    Dec 15, 2008
  2. mathieu
    Replies:
    3
    Views:
    593
    Bo Persson
    Sep 4, 2009
  3. Replies:
    1
    Views:
    157
    Vedran SubotiƦ
    Sep 7, 2005
  4. McKirahan

    Remove extra CrLf's from textarea

    McKirahan, Mar 6, 2004, in forum: Javascript
    Replies:
    3
    Views:
    530
    McKirahan
    Mar 6, 2004
  5. Replies:
    4
    Views:
    173
Loading...

Share This Page