Home > Blockchain >  Kernighan and Ritchie C exercise 1-18
Kernighan and Ritchie C exercise 1-18

Time:10-13

I was trying to complete the task requested by this exercise from the K&R book:

Write a program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.

I still have to figure out how to implement the first task, but I have this idea for the second one:

#include <stdio.h>

#define MAXLINE 1000
#define IN 1
#define OUT 1
 
int blank1(char s[], int len){
    int i;
    int c=0;
    for (i=0; i<len;i  ){
    if(s[i] == ' ' | s[i] == '\t')
        c  ;
    }
    if (c==(len-1))
        return 1;
    else
        return 0;
}

int get_line1(char s[], int lim){
    int c,i;

    for (i=0; i<lim-1 && ((c=getchar())!= EOF) && c!='\n'; i  ){
        s[i]=c;
     }

     if (c=='\n'){
         s[i]=c;
         i  ;
     }

     s[i] = '\0';
     return i;
}

int main() {
    char line[MAXLINE];     
    int len;
    int j=1;
    int  i;
    
    while(j){
        len=get_line1(line,MAXLINE);
        if ((blank1(line,len)) == 0) {
        printf("%s", line);
        }

        if (getchar() == EOF){
            j=0;
        }
    }
}

The function blank1 takes as input a string s[] and the string's length len.

Then it cycles for all the string and increases the counter i every time it hits a blank or tab. If the string is completely made of blank or tab, such as \t\t\t\n\0, then the value of i will be the same value of the length of the string - 1 (so to speak, the length of the string excluding the character \n). If the string is completely blank, then 1 will be returned, otherwise 0. So in this way if blank(string,string's length) returns 1, we know it is a wholly blank string and we can avoid printing it, as the exercise requests.

The problem is that with some outputs this program cuts the first letter. For instance with:

Once upon a time\n
There was a little monkey\n
That\n

What is printed is:

Once upon a time
here was a little monke
hat

I can't manage to get why this truncation occurs.

EDIT:

#include <stdio.h>

#define MAXLINE 1000
#define IN 1
#define OUT 1

int blank1(char s[], int len){
    int i;
    int c=0;
    for (i=0; i<len;i  ){
        if(s[i] == ' ' | s[i] == '\t')
            c  ;
    }
    if (c==(len-1))
        return 1;
    else
        return 0;
}

int get_line1(char s[], int lim){
    int c,i;

    for (i=0; i<lim-1 && ((c=getchar())!= EOF) && c!='\n'; i  ){
        s[i]=c;
    }

    if (c==EOF)
        return -1;  /////

    if (c=='\n'){
        s[i]=c;
        i  ;
    }

    s[i] = '\0';
    return i;
}

int main() {
    char line[MAXLINE];
    char verso[MAXLINE];
    char longest[MAXLINE];
    int len;
    int j=1;
    int  i;
    
    while(j){
        len=get_line1(line,MAXLINE);
        if (len==-1){            ///////////
            j=0;
        }       
        else if ((blank1(line,len)) == 0) {
            printf("%s", line);
        }
    }
}

CodePudding user response:

getchar() == EOF in main is swallowing your first character from each line (after the first). You are better off calling getchar in only one place.

One possibility that causes minimal churn to your current implementation is to keep the only getchar call inside get_line1 and return -1 from get_line1 if a EOF is read there, to then be handled inside main, instead of the call to getchar inside main.

CodePudding user response:

Do not program in main use functions for similar tasks.

char *skipLeadingBlanks(char *str)
{
    char *wrk = str;

    while((*wrk && *wrk != '\n') && (*wrk == ' ' || *wrk == '\t')) *wrk  ;
    memmove(str, wrk, strlen(wrk)   1);
    return str;
}

int main(void)
{
    char str[1024];

    while(fgets(str, sizeof(str), stdin))
    {
        skipLeadingBlanks(str);
        if(!*str || *str == '\n') continue;  //empty line
        printf("%s",str);
    }
}

https://godbolt.org/z/hxW5zP5Mx

  • Related