K&R 第 1 章 - 练习 22 的解决方案,你觉得怎么样?

发布于 2024-07-17 01:21:56 字数 1504 浏览 5 评论 0原文

我正在从 k&r 学习 C 作为第一语言,我只是想问,如果你认为这个练习是以正确的方式解决的,我知道它可能没有你想要的那么完整,但我想要观点,这样我就知道我正在正确地学习 C。

谢谢

/* Exercise 1-22. Write a program to "fold" long input lines into two or
 * more shorter lines, after the last non-blank character that occurs
 * before then n-th column of input. Make sure your program does something
 * intelligent with very long lines, and if there are no blanks or tabs
 * before the specified column.
 * 
 * ~svr
 *
 * [NOTE: Unfinished, but functional in a generic capacity]
 * Todo:
 * Handling of spaceless lines
 * Handling of lines consisting entirely of whitespace
 */

#include <stdio.h>
#define FOLD 25
#define MAX 200
#define NEWLINE '\n'
#define BLANK ' '
#define DELIM 5
#define TAB '\t'

int
main(void)
{
    int line  = 0, 
        space = 0,
        newls = 0,
            i = 0, 
            c = 0, 
            j = 0;

    char array[MAX] = {0};

    while((c = getchar()) != EOF) {
        ++line;
        if(c == NEWLINE)
            ++newls;
        if((FOLD - line) < DELIM) {
            if(c == BLANK) {
                if(newls > 0) {
                    c = BLANK;
                    newls = 0;
                }
                else
                    c = NEWLINE;
                line = 0;
            }
        }
        array[i++] = c;
    }
    for(line = 0; line < i; line++) {
        if(array[0] == NEWLINE)
            ;
        else
            printf("%c", array[line]);
    }
    return 0;
}

I'm learning C from the k&r as a first language, and I just wanted to ask, if you thought this exercise was being solved the right way, I'm aware that it's probably not as complete as you'd like, but I wanted views, so I'd know I'm learning C right.

Thanks

/* Exercise 1-22. Write a program to "fold" long input lines into two or
 * more shorter lines, after the last non-blank character that occurs
 * before then n-th column of input. Make sure your program does something
 * intelligent with very long lines, and if there are no blanks or tabs
 * before the specified column.
 * 
 * ~svr
 *
 * [NOTE: Unfinished, but functional in a generic capacity]
 * Todo:
 * Handling of spaceless lines
 * Handling of lines consisting entirely of whitespace
 */

#include <stdio.h>
#define FOLD 25
#define MAX 200
#define NEWLINE '\n'
#define BLANK ' '
#define DELIM 5
#define TAB '\t'

int
main(void)
{
    int line  = 0, 
        space = 0,
        newls = 0,
            i = 0, 
            c = 0, 
            j = 0;

    char array[MAX] = {0};

    while((c = getchar()) != EOF) {
        ++line;
        if(c == NEWLINE)
            ++newls;
        if((FOLD - line) < DELIM) {
            if(c == BLANK) {
                if(newls > 0) {
                    c = BLANK;
                    newls = 0;
                }
                else
                    c = NEWLINE;
                line = 0;
            }
        }
        array[i++] = c;
    }
    for(line = 0; line < i; line++) {
        if(array[0] == NEWLINE)
            ;
        else
            printf("%c", array[line]);
    }
    return 0;
}

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

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

发布评论

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

评论(4

↘人皮目录ツ 2024-07-24 01:21:56

我确信你在正确的轨道上,但有一些可读性的提示:

  • 评论你的东西,
  • 正确命名变量,如果你拒绝
  • 结果,至少给出一个描述,一些单行如果你使用,有些你不使用。 (恕我直言,始终使用 {},这样更具可读性)
  • 最后一个 for 循环中的 if 语句可能会更好,例如

    if(array[0] != NEWLINE)  
    {   
        printf("%c", array[line]); 
    }

I'm sure you on the rigth track, but some pointers for readability:

  • comment your stuff
  • name the variables properly and at least give a description if you refuse
  • be consequent, some single-line if's you use and some you don't. (imho, always use {} so it's more readable)
  • the if statement in the last for-loop can be better, like

    if(array[0] != NEWLINE)  
    {   
        printf("%c", array[line]); 
    }
落在眉间の轻吻 2024-07-24 01:21:56

恕我直言,这不好。

首先,它不符合您的要求。 您应该在输出行边界之前的非空白之后找到最后一个空白。 你的程序甚至没有远程尝试这样做,它似乎努力寻找 (margin - 5) 个字符后的第一个空白(5 来自哪里?如果所有单词都有 9 个字母怎么办?)。 然而,由于您对 newls 变量的操作,它也不会这样做。 另外,这:

for(line = 0; line < i; line++) {
    if(array[0] == NEWLINE)
        ;
    else
        printf("%c", array[line]);
}

可能是错误的,因为您检查在整个循环中永远不会改变的条件。

最后但并非最不重要的一点是,将整个文件存储在固定大小的缓冲区中并不好,因为有两个原因:

  • 缓冲区在大文件上必然会溢出,
  • 即使它永远不会溢出,人们仍然不会喜欢你存储例如。 内存中的一个 GB 文件只是为了将其切成 25 个字符的块,

我认为您应该重新开始,重新考虑您的算法(包括极端情况),然后才开始编码。 我建议您:

  • 逐行处理文件(意味着输出行)
  • 将行存储在足够大的缓冲区中以容纳最大的输出行
  • 搜索您将在缓冲区中中断的字符,
  • 然后打印它(提示:您可以用 '\0' 终止字符串并用 printf("%s", ...)) 打印,将未打印的内容复制到缓冲区的开头,从那里继续

That's no good IMHO.

First, it doesn't do what you were asked for. You were supposed to find the last blank after a nonblank before the output line boundary. Your program doesn't even remotely try to do it, it seems to strive for finding the first blank after (margin - 5) characters (where did the 5 came from? what if all the words had 9 letters?). However it doesn't do that either, because of your manipulation with the newls variable. Also, this:

for(line = 0; line < i; line++) {
    if(array[0] == NEWLINE)
        ;
    else
        printf("%c", array[line]);
}

is probably wrong, because you check for a condition that never changes throughout the loop.

And, last but not least, storing the whole file in a fixed-size buffer is not good, because of two reasons:

  • the buffer is bound to overflow on large files
  • even if it would never overflow, people still wouldn't like you for storing eg. a gigabyte file in memory just to cut it into 25-character chunks

I think you should start again, rethink your algorithm (incl. corner cases), and only after that, start coding. I suggest you:

  • process the file line-by-line (meaning output lines)
  • store the line in a buffer big enough to hold the largest output line
  • search for the character you'll break at in the buffer
  • then print it (hint: you can terminate the string with '\0' and print with printf("%s", ...)), copy what you didn't print to the start of the buffer, proceed from that
罪歌 2024-07-24 01:21:56

一个明显的问题是您静态分配“数组”并且在访问它时从不检查索引限制。 缓冲区溢出等待发生。 事实上,您从未在第一个循环中重置 i 变量,所以我对程序应该如何工作感到有点困惑。 看来您在打印自动换行之前将完整的输入存储在内存中?

因此,建议:将两个循环合并在一起,并打印已完成的每一行的输出。 然后您可以在下一行中重新使用该数组。

哦,还有更好的变量名和一些注释。 我不知道“DELIM”应该做什么。

An obvious problem is that you statically allocate 'array' and never check the index limits while accessing it. Buffer overflow waiting to happen. In fact, you never reset the i variable within the first loop, so I'm kinda confused about how the program is supposed to work. It seems that you're storing the complete input in memory before printing it word-wrapped?

So, suggestions: merge the two loops together and print the output for each line that you have completed. Then you can re-use the array for the next line.

Oh, and better variable names and some comments. I have no idea what 'DELIM' is supposed to do.

逆夏时光 2024-07-24 01:21:56

看起来(未经测试)它可以工作,但似乎有点复杂。

这是我的第一个想法的一些伪代码

const int MAXLINE = ??  — maximum line length parameter
int chrIdx = 0 — index of the current character being considered 
int cand = -1  — "candidate index",  Set to a potential break character
char linebuf[bufsiz]
int lineIdx = 0 — index into the output line
char buffer[bufsiz]   — a character buffer
read input into buffer
for ix = 0 to bufsiz -1
do     
   if buffer[ix] == ' ' then
      cand = ix
   fi
   linebuf[lineIdx] = buffer[ix]
   lineIdx += 1
   if lineIdx >= MAXLINE then
      linebuf[cand] = NULL — end the string
      print linebuf
      do something to move remnants to front of line (memmove?)
   fi
 od

现在已经晚了,我只有一条腰带,所以可能存在缺陷,但它显示了总体思路 - 加载缓冲区,并将缓冲区的内容复制到行缓冲区,跟踪可能的情况断点。 当接近结尾时,使用断点。

It looks (without testing) like it could work, but it seems kind of complicated.

Here's some pseudocode for my first thought

const int MAXLINE = ??  — maximum line length parameter
int chrIdx = 0 — index of the current character being considered 
int cand = -1  — "candidate index",  Set to a potential break character
char linebuf[bufsiz]
int lineIdx = 0 — index into the output line
char buffer[bufsiz]   — a character buffer
read input into buffer
for ix = 0 to bufsiz -1
do     
   if buffer[ix] == ' ' then
      cand = ix
   fi
   linebuf[lineIdx] = buffer[ix]
   lineIdx += 1
   if lineIdx >= MAXLINE then
      linebuf[cand] = NULL — end the string
      print linebuf
      do something to move remnants to front of line (memmove?)
   fi
 od

It's late and I just had a belt, so there may be flaws, but it shows the general idea — load a buffer, and copy the contents of the buffer to a line buffer, keeping track of the possible break points. When you get close to the end, use the breakpoint.

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