【发布时间】:2020-08-03 01:51:36
【问题描述】:
我要解决的问题是 KR2 练习 1-22; '编写一个程序,在第 n 列输入之前出现的最后一个非空白字符之后将长输入行“折叠”成两行或多行较短的行。确保你的程序用很长的行做一些智能的事情,如果在指定的列之前没有空格或制表符。
我试图处理一个递归函数,但它只是卡住了。
错误行为示例:
你好世界
输出 >>
地狱
喔喔
喔喔
喔喔
喔喔
....
...
预期行为:
你好世界
输出 >>
地狱
喔喔
rld
错误行为的第二个例子:
你好世界
输出 >>
他
呵呵
洛
呵呵
洛
呵呵
呵呵
....
...
次要预期行为:
你好世界
输出 >>
他
呵呵
工作
见下面的代码:
#include <stdio.h>
#define PAGEWIDTH 5
#define MAXLINE 1000
int getline(char line[], int maxline);
void fold(char line[], int start);
/* "fold" long input lines into two or more shorter lines after
the last non-blnk character that occurs before the n-th
column of input */
int main()
{
int len; /* current line length*/
char line[MAXLINE]; /* current input lne*/
while ((len = getline(line, MAXLINE)) > 0)
if (len > PAGEWIDTH)
fold(line, 0);
return 0;
}
/* getline : read a line into s, return length */
int getline(char s[], int lim)
{
int c, i;
c = 0;
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;
}
void fold(char line[], int start)
{
int i, lstnb;
i = lstnb = 0;
for (i = 0; i < PAGEWIDTH-1 && line[start + i] != '\0'; ++i) {
if (line[start + i] != ' ')
lstnb = i;
}
for (i = 0; i <= lstnb; ++i)
putchar(line[start + i]);
putchar('\n');
if(line[lstnb + 1] != '\0')
fold(line, lstnb + 1);
}
【问题讨论】:
-
我会开始使用调试器。但是为什么要递归而不是循环呢?
-
以这种方式接近它感觉更直观。如果我无法弄清楚当前的问题,我计划重写它以迭代地工作。尽管我仍然感到困惑,但我已经使用了打印语句和调试器。在函数 fold 的初始调用中使用调试器并检查变量“start”,值为 0。随后,它是 -129496704,而不是给定的第一个示例“hello world”输入所期望的 4。打印提供给 fold 的参数(开始)确实显示 4。我认为编译器优化可能是差异的原因,因为事情仍然在一定程度上起作用。
-
以下 for 循环中出现问题:
for (i = 0; i < PAGEWIDTH-1 && line[start + i] != '\0'; ++i) { if (line[start + i] != ' ') lstnb = i; -
提示:问题出在
fold函数的最后两行。提示 2:考虑lstnb实际代表什么。 -
递归是解决问题的好方法;但是当您发现自己在递归函数定义中编写循环,或者在返回
void的递归函数定义中编写循环时,您应该怀疑自己是否走在正确的轨道上。顺便说一句,您的函数定义是尾递归的; C 不保证尾调用消除,但 GCC 确实 支持它。不过,我不知道任何其他 C 编译器会进行这种优化,而且我严重怀疑 MSVC 会这样做。
标签: c visual-studio visual-c++