【发布时间】:2018-07-20 06:01:01
【问题描述】:
编写一个程序,在输入的第 n 列之前出现的最后一个非空白字符之后将长输入行“折叠”成两行或多行较短的行。确保你的程序用很长的行做一些智能的事情,如果在指定的列之前没有空格或制表符。
我决定遵循的算法如下:
- 如果输入行的长度
- 如果不是,我从 maxcol 向左检查,找到最接近的非空格字符是正确的,并将它们保存为“第一个”和“最后一个”。然后我打印从 line[0] 到 line[first] 的字符数组,然后数组的其余部分,从 line[last] 到 line[len] 成为新的线数组。
这是我的代码:
#include <stdio.h>
#define MAXCOL 5
int getline1(char line[]);
int main()
{
char line[1000];
int len, i, j, first, last;
len = getline1(line);
while (len > 0) {
if (len < MAXCOL) {
printf("%s\n", line);
break;
}
else {
for (i = MAXCOL - 1; i >= 0; i--) {
if (line[i] != ' ') {
first = i;
break;
}
}
for (j = MAXCOL - 1; j <= len; j++) {
if (line[j] != ' ') {
last = j;
break;
}
}
//printf("first %d last %d\n", first, last);
for (i = 0; i <= first; i++)
putchar(line[i]);
putchar('\n');
for (i = 0; i < len - last; i++) {
line[i] = line[last + i];
}
len -= last;
first = last = 0;
}
}
return 0;
}
int getline1(char line[])
{
int c, i = 0;
while ((c = getchar()) != EOF && c != '\n')
line[i++] = c;
if (c == '\n')
line[i++] = '\n';
line[i] = '\0';
return i;
}
以下是问题:
- 它不会用很长的线条做一些智能的事情(这很好,因为我可以将它添加为边缘情况)。
- 它对选项卡没有任何作用。
- 我无法理解输出的一部分。
例如,输入:
asd de def deffff
我得到了输出:
asd
de
def
defff //Expected until here
//Unexpected lines below
ff
fff
deffff
deffff
deffff
问题 1 - 为什么会打印出意外的行?如何让我的程序/算法变得更好?
最终,在这个问题上花了很长时间后,我放弃了,决定查看clc-wiki 以获取解决方案。这里的每个程序都没有工作,保存一个(其他的没有工作,因为它们没有涵盖某些边缘情况)。有效的是最大的一个,对我来说没有任何意义。它没有任何 cmets,我也无法正确理解变量名及其代表的含义。但只有 wiki 中的 ONLY 程序有效。
#include <stdio.h>
#define YES 1
#define NO 0
int main(void)
{
int TCOL = 8, ch, co[3], i, COL = 19, tabs[COL - 1];
char bls[COL - 1], bonly = YES;
co[0] = co[1] = co[2] = 0;
while ((ch = getchar()) != EOF)
{
if (ch != '\t') {
++co[0];
++co[2];
}
else {
co[0] = co[0] + (TCOL * (1 + (co[2] / TCOL)) - co[2]);
i = co[2];
co[2] = TCOL + (co[2] / TCOL) * TCOL;
}
if (ch != '\n' && ch != ' ' && ch != '\t')
{
if (co[0] >= COL) {
putchar('\n');
co[0] = 1;
co[1] = 0;
}
else
for (i = co[1]; co[1] > 0; --co[1])
{
if (bls[i - co[1]] == ' ')
putchar(bls[i - co[1]]);
else
for (; tabs[i - co[1]] != 0;)
if (tabs[i - co[1]] > 0) {
putchar(' ');
--tabs[i - co[1]];
}
else {
tabs[i - co[1]] = 0;
putchar(bls[i - co[1]]);
}
}
putchar(ch);
if (bonly == YES)
bonly = NO;
}
else if (ch != '\n')
{
if (co[0] >= COL)
{
if (bonly == NO) {
putchar('\n');
bonly = YES;
}
co[0] = co[1] = 0;
}
else if (bonly == NO) {
bls[co[1]] = ch;
if (ch == '\t') {
if (TCOL * (1 + ((co[0] - (co[2] - i)) / TCOL)) -
(co[0] - (co[2] - i)) == co[2] - i)
tabs[co[1]] = -1;
else
tabs[co[1]] = co[2] - i;
}
++co[1];
}
else
co[0] = co[1] = 0;
}
else {
putchar(ch);
if (bonly == NO)
bonly = YES;
co[0] = co[1] = co[2] = 0;
}
}
return 0;
}
问题 2 - 您能帮我理解这段代码及其工作原理吗?
它解决了我的解决方案的所有问题,并且还可以通过逐个字符读取,因此看起来更有效。
【问题讨论】:
-
看到不需要的输出,我怀疑在某处缺少空终止,我只发现
getline1中写入了一个零。但要查明问题,我推荐ericlippert.com/2014/03/05/how-to-debug-small-programs 和stackoverflow.com/questions/2069367/how-to-debug-using-gdb,如果这些没有帮助ericlippert.com/2014/03/21/find-a-simpler-problem -
@Yunnosch 感谢您提供这些链接! getline1 中的 '\0' 不算作空终止吗?
-
这是我找到的唯一一个。我希望每个所需的输出线至少有一个。
-
从 line[0:first] 打印后,我还使 line[0:len-last] = line[last:len]。那不应该将在 line[len] 处找到的 null 终止也复制到每个输出行吗?
-
调试是否显示您描述的机制按预期工作?如果没有其他人愿意告诉您问题出在哪里,那么调试就是要走的路。调试时要遵循的提示:准确找出输出的哪一部分是由代码的哪一部分以及何时引起的。如果 "%s" 打印的内容多于预期,请确保存在
\0。
标签: c arrays text-processing kernighan-and-ritchie