简体   繁体   English

Kernighan 和 Ritchie C 练习 1-18

[英]Kernighan and Ritchie C exercise 1-18

I was trying to complete the task requested by this exercise from the K&R book:我试图完成 K&R 书中本练习要求的任务:

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 .函数 blank1 将字符串s[]和字符串的长度len作为输入。

Then it cycles for all the string and increases the counter i every time it hits a blank or tab.然后它对所有字符串循环并在每次遇到空白或制表符时增加计数器i 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 ).如果字符串完全由空格或制表符组成,例如\\t\\t\\t\\n\\0 ,则i的值将与字符串的长度相同 - 1(可以说,长度为不包括字符\\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.如果字符串完全为空,则返回 1,否则返回 0。所以这样如果blank(string,string's length)返回 1,我们知道它是一个完全空白的字符串,我们可以避免打印它,正如练习所要求的.

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);
        }
    }
}

getchar() == EOF in main is swallowing your first character from each line (after the first). getchar() == EOF in main正在从每一行(在第一行之后)吞下你的第一个字符。 You are better off calling getchar in only one place.你最好只在一个地方调用getchar

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 .导致最小的流失到您当前实现一种可能性是保持唯一getchar内部通话get_line1和返回-1get_line1如果EOF读那里,然后被内部处理main ,而不是调用getchar内部main

Do not program in main use functions for similar tasks.不要在main用途函数中为类似任务编程。

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 https://godbolt.org/z/hxW5zP5Mx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM