这个小 C 程序满足 K&R 练习吗?

发布于 2024-09-13 16:53:40 字数 1229 浏览 2 评论 0原文

我正在进行 K&R 的练习 1-18

编写一个程序来删除每行输入中的尾随空白和制表符,并删除整个空白行。

这是我到目前为止所想出的

#include <stdio.h>

#define MAXLINE 1000

int getline(char line[], int maxline);
void copy(char to[], char from[]);

int main () {

    int len;
    char line[MAXLINE];

    while (getline(line, MAXLINE) > 0) {
            printf("%s", line);
    }
    return 0;
}


int getline(char s[], int lim) {
    int c, i, lastNonBlankIndex;
    lastNonBlankIndex = 0;

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

        if (c != ' ' && c != '\t') {
            lastNonBlankIndex = i + 1;

        } 

        s[i] = c;
    }

    if (i != lastNonBlankIndex) {
        i = lastNonBlankIndex;
        c = '\n';
    }

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

第二部分听起来很困难,因为我不确定如果该行只有空格或制表符,我应该返回什么。毕竟,如果我返回 0,它将停止 getline() 调用。我应该在此处设置 #define,例如 ALL_BLANKS

无论如何,对于实际的主要问题,这是从行中删除尾随空格和制表符的正确方法吗?我运行了一些输入,它似乎有效。但是,如果我将带有换行符的文本复制并粘贴到 CL 中,它看起来全部串在一起。当我在 CL 中输入一行并按 Enter 键时,它会自动打印它。我应该构建一系列行,然后循环遍历并在完成后打印它们吗?

I'm on to K&R's Exercise 1-18

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

This is what I've came up with so far

#include <stdio.h>

#define MAXLINE 1000

int getline(char line[], int maxline);
void copy(char to[], char from[]);

int main () {

    int len;
    char line[MAXLINE];

    while (getline(line, MAXLINE) > 0) {
            printf("%s", line);
    }
    return 0;
}


int getline(char s[], int lim) {
    int c, i, lastNonBlankIndex;
    lastNonBlankIndex = 0;

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

        if (c != ' ' && c != '\t') {
            lastNonBlankIndex = i + 1;

        } 

        s[i] = c;
    }

    if (i != lastNonBlankIndex) {
        i = lastNonBlankIndex;
        c = '\n';
    }

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

The second part sounded hard, as I wasn't sure what I should return if the line only has blanks or tabs. After all, if I return 0, it will halt the getline() calling. Would this be where I should set up a #define, such as ALL_BLANKS.

Anyway, to actual main question, is this a correct way to remove trailing blanks and tabs from lines? I ran a few inputs through, and it seemed to work. However, if I copy and paste text with newlines into the CL, it appears all strung together. And when I type a line into the CL and push enter, it automatically prints it. Should I be building an array of lines, and then looping through and printing them when done ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

毁梦 2024-09-20 16:53:40

您的代码看起来是正确的,但我认为如果您将从 stdin 读取一行的操作分开并去除尾随空白行(解耦),效果会更好。然后你可以使用书中未修改的getline(代码重用),并且不会出现返回0时停止的问题。

如果你对其他解决方案感兴趣,CLC-wiki有一个几乎K&R2 解决方案的完整列表。

#include <stdio.h>
#define MAXLINE 1024

int getline(char s[], int lim);

main()
{
    int i, len;
    char line[MAXLINE];

    while ((len = getline(line, MAXLINE)) > 0) {
        i = len - 2;
        while (i >= 0 && (line[i] == ' ' || line[i] == '\t'))
            --i;
        if (i >= 0) {
            line[i+1] = '\n';
            line[i+2] = '\0';
            printf("%s", line);
        }
    }
    return 0;
}

这是我前段时间写的1类解决方案。 getline 如本书第 28 页所示。将删除空格放在单独的函数 rstrip 中可能会更好,但我将其作为练习留给读者。

Your code looks correct, but I think it would be better if you separate the operations of reading a line from stdin and stripping the line of trailing whitespace (decoupling). Then you can use the unmodified getline from the book (code reuse) and won't have the problem of halting on returning 0.

And if you are interested in other solutions, the CLC-wiki has an almost complete list of K&R2 solutions.

#include <stdio.h>
#define MAXLINE 1024

int getline(char s[], int lim);

main()
{
    int i, len;
    char line[MAXLINE];

    while ((len = getline(line, MAXLINE)) > 0) {
        i = len - 2;
        while (i >= 0 && (line[i] == ' ' || line[i] == '\t'))
            --i;
        if (i >= 0) {
            line[i+1] = '\n';
            line[i+2] = '\0';
            printf("%s", line);
        }
    }
    return 0;
}

This is the category 1 solution I wrote some time ago. getline is as on page 28 of the book. It might be nicer to put the removal of whitespace in a separate function rstrip, but I leave this as an exercise for the reader.

回忆那么伤 2024-09-20 16:53:40

你的基本设计是合理的。正如您所做的那样,最好在构建后立即打印一条剥离的行,这样您的程序只需在内存中一次保留一行,而不是整个文件。

您的代码有一个小问题:它没有实现问题的第二部分(“删除整个空白行”)。这是因为您总是在字符串末尾添加 '\n' 。这很容易修复,但请记住,您必须向调用者返回一个非零值,因为空行并不表示文件结尾。

Your basic design is sound. It is better, as you did, to print a stripped line as soon as you've built it, so that your program only needs to keep one line at a time in memory and not the whole file.

There is a small problem with your code: it doesn't implement the second part of the question (“delete entirely blank line”). That's because you always tack a '\n' at the end of the string. This is easy to fix, but remember that you must return a nonzero value to your caller since a blank line doesn't indicate the end of the file.

调妓 2024-09-20 16:53:40

如果出现错误或达到 EOF,getline 应返回 -1(一般为负值)。然后你的循环条件可以检查它是否返回 >= 0 并且仍然允许 0 长度的行。

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

我几乎从不在循环条件中包含赋值。我宁愿添加 10 行代码来避免这样做,因为它很难阅读。我特别避免将它们与复杂的条件一起使用。

int i = 0;

while (i < lim) {
   c = getchar();
   if (c == EOF || c == '\n') {
       break;
   }
   line[i] = (char)c;
   i++;
}
line[i] = '\0'; // Null terminate the string

这段代码应该为您读成一行。我会将行的读入与尾随空白的删除分开。您可以很容易地从字符串末尾向后操作,以删除我以 null 终止该行的位置处的空格,因为在读入该行后,您现在知道它的长度。本质上,你会生长绳子,然后在它完成生长后将其修剪回来。

getline should return -1 (a negative value in general) if there is an error or if EOF is reached. Then your loop conditional can check that it returns something >= 0 and still allow for 0 length lines.

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

I almost never include an assignment within a loop conditional. I would rather add 10 lines of code to get around doing that because it's difficult to read. I would especially refrain from using them with complicated conditionals.

int i = 0;

while (i < lim) {
   c = getchar();
   if (c == EOF || c == '\n') {
       break;
   }
   line[i] = (char)c;
   i++;
}
line[i] = '\0'; // Null terminate the string

This code should read in a line for you. I would separate the reading in of the line from the removal of the trailing white space. You could very easily work backwards from the end of the string to remove white spaces at the location where I null terminated the line, since after having read in the line you now know its length. Essentially you grow the string and then you prune it back down after it has finished growing.

等风也等你 2024-09-20 16:53:40

我就是这样做的。

#include <stdio.h>
#define MAXLINE 1000

#define IN 1
#define OUT 0

int state = OUT;

int getline(char s[], int lim);
void copy(char to[], char from[]);

int main(void)
{
int lenght;
int max = 0;
char line[MAXLINE];
char longest[MAXLINE];

while ((lenght = getline(line, MAXLINE)) > 0)
    if (lenght > max)
    {
        max = lenght;
        copy(longest, line);
    }
if (max > 0)
    printf("\n%s\n", longest);

    return 0;

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


    if (state == IN && c != ' ' && c != '\t')
    {
        s[i] = ' ';
        i++;
        state = OUT;
    }
    if (s[0] == ' ')
    {
        s[0] = '\b';
    }


    s[i] = c;


    if (c == ' ' || c == '\t')
    {
        i--;
        state = IN;
    }
}
if (c == '\n')
{
    s[i] = c;
    i++;
}
s[i] = '\0';

return i;
 }

void copy(char to[], char from[])
{
int i = 0;
while ((to[i] = from[i]) != '\0')
    i++;
}

This is how i did it.

#include <stdio.h>
#define MAXLINE 1000

#define IN 1
#define OUT 0

int state = OUT;

int getline(char s[], int lim);
void copy(char to[], char from[]);

int main(void)
{
int lenght;
int max = 0;
char line[MAXLINE];
char longest[MAXLINE];

while ((lenght = getline(line, MAXLINE)) > 0)
    if (lenght > max)
    {
        max = lenght;
        copy(longest, line);
    }
if (max > 0)
    printf("\n%s\n", longest);

    return 0;

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


    if (state == IN && c != ' ' && c != '\t')
    {
        s[i] = ' ';
        i++;
        state = OUT;
    }
    if (s[0] == ' ')
    {
        s[0] = '\b';
    }


    s[i] = c;


    if (c == ' ' || c == '\t')
    {
        i--;
        state = IN;
    }
}
if (c == '\n')
{
    s[i] = c;
    i++;
}
s[i] = '\0';

return i;
 }

void copy(char to[], char from[])
{
int i = 0;
while ((to[i] = from[i]) != '\0')
    i++;
}
浮生未歇 2024-09-20 16:53:40
#include <stdio.h>

#define MAXLINE 1000

size_t getline(char *s,size_t lim)
{
  if( fgets(s,lim,stdin) )
  {
    while( *s && strchr(" \t\n",s[strlen(s)-1]) )
      s[strlen(s)-1]=0;
    return strlen(s);
  }
  return 0;
}

main()
{
    int len;
    char line[MAXLINE];

    while (getline(line,sizeof line)) {
            printf("%s", line);
    }
    return 0;
}
#include <stdio.h>

#define MAXLINE 1000

size_t getline(char *s,size_t lim)
{
  if( fgets(s,lim,stdin) )
  {
    while( *s && strchr(" \t\n",s[strlen(s)-1]) )
      s[strlen(s)-1]=0;
    return strlen(s);
  }
  return 0;
}

main()
{
    int len;
    char line[MAXLINE];

    while (getline(line,sizeof line)) {
            printf("%s", line);
    }
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文