将C中的空行压缩为一个空行
您好,请参考相同的问题,但代码不同 我想把多个空行压缩成一个空行,但它似乎不起作用,在StgOUT上的CygWin终端上,最后一行给了我一个额外的空行,虽然输入端没有空行。p> 例如将C中的空行压缩为一个空行,c,C,您好,请参考相同的问题,但代码不同 我想把多个空行压缩成一个空行,但它似乎不起作用,在StgOUT上的CygWin终端上,最后一行给了我一个额外的空行,虽然输入端没有空行。p> 例如 输入 期望输出 实际产量 请解释 您正在两次递增nlines: else if(c == '\n'){ if(++nlines >2){ /* incremented here */ continue; } else { nlines++;
输入 期望输出 实际产量
请解释 您正在两次递增
nlines
:
else if(c == '\n'){
if(++nlines >2){ /* incremented here */
continue;
}
else {
nlines++; /* incremented here */
nspace = 0;
}
putchar(c);
}
你只想做一次。我建议只增加计数器直到它达到2,然后不再增加它。这只意味着一个小小的改变:
if(nlines >= 2){
continue;
}
您正在两次递增
nlines
:
else if(c == '\n'){
if(++nlines >2){ /* incremented here */
continue;
}
else {
nlines++; /* incremented here */
nspace = 0;
}
putchar(c);
}
你只想做一次。我建议只增加计数器直到它达到2,然后不再增加它。这只意味着一个小小的改变:
if(nlines >= 2){
continue;
}
这是您的代码的变体。我取消了
format()
函数(这对我来说是不寻常的,因为大多数程序都使用了足够的函数),将它直接合并到main()
。该代码现在更加对称地处理空格和换行符,修复了在年代中发现的双增量问题。如果末尾没有换行符,它也只在末尾打印一个换行符。这将规范化不以换行符结尾的文件。nlines的初始化=1代码>在文件开头处理多个换行符-这已经做得很好了
#include <stdio.h>
int main(void)
{
int c;
size_t nlines = 1;
size_t nspace = 0;
while ((c = getchar()) != EOF)
{
if (c == '\t')
c = ' ';
if (c == ' ')
{
if (nspace < 1)
{
putchar(c);
nspace++;
nlines = 0;
}
}
else if (c == '\n')
{
if (nlines < 2)
{
putchar(c);
nlines++;
nspace = 0;
}
}
else
{
putchar(c);
nspace = 0;
nlines = 0;
}
}
if (nlines == 0)
putchar('\n');
return 0;
}
以及:
以及:
处理CRLF行结束符
注释表明上述代码在Cygwin终端上不起作用,可能的原因是被修改的数据有CRLF行结尾。围绕这一点有多种方法。一种是找到一种将标准输入强制转换为文本模式的方法。在文本模式下,输入时CRLF行尾应映射到Unix样式的'\n'
(仅限NL或LF)行尾,输出时,Unix样式的行尾应映射到CRLF行尾
或者,可以简单地忽略CR字符:
--- sb73.c 2017-06-08 22:04:28.000000000 -0700
+++ sb47.c 2017-06-08 22:40:24.000000000 -0700
@@ -19,6 +19,8 @@
nlines = 0;
}
}
+ else if (c == '\r')
+ continue; // Windows?
else if (c == '\n')
{
if (nlines < 2)
--sb73.c 2017-06-08 22:04:28.000000000-0700
+++sb47.c 2017-06-08 22:40:24.000000000-0700
@@ -19,6 +19,8 @@
nlines=0;
}
}
+else如果(c=='\r')
+继续;//窗户?
else如果(c=='\n')
{
如果(nlines<2)
这是一个显示代码中两个额外行的“统一差异”。或者可以将不后跟LF的CR作为常规字符处理,而将后跟LF的CR作为换行组合处理:
--- sb73.c 2017-06-08 22:04:28.000000000 -0700
+++ sb59.c 2017-06-08 22:42:43.000000000 -0700
@@ -19,6 +19,17 @@
nlines = 0;
}
}
+ else if (c == '\r')
+ {
+ if ((c = getchar()) == '\n')
+ {
+ ungetc(c, stdin);
+ continue;
+ }
+ putchar('\r');
+ nspace = 0;
+ nlines = 0;
+ }
else if (c == '\n')
{
if (nlines < 2)
--sb73.c 2017-06-08 22:04:28.000000000-0700
+++sb59.c 2017-06-08 22:42:43.000000000-0700
@@ -19,6 +19,17 @@
nlines=0;
}
}
+else如果(c=='\r')
+ {
+如果((c=getchar())=='\n')
+ {
+ungetc(c、stdin);
+继续;
+ }
+putchar('\r');
+nspace=0;
+nlines=0;
+ }
else如果(c=='\n')
{
如果(nlines<2)
可能有一种方法可以编写一个处理CR的状态机,但这将更加复杂
我有一个utod
程序,可以将Unix风格的行尾转换为Windows风格;我在管道中使用它来测试新的代码变体。这里是您的代码变体。我删除了format()
函数(这对我来说是不寻常的,因为大多数程序都使用了足够的函数)将其直接合并到main()中
。该代码现在更加对称地处理空格和换行符,解决了s中也发现的双增量问题。如果末尾没有换行符,它也只在末尾打印一个换行符。这将规范化不以换行符结尾的文件。nlines=1;
的初始化处理多个新行符文件开头的行-这已经做得很好了
#include <stdio.h>
int main(void)
{
int c;
size_t nlines = 1;
size_t nspace = 0;
while ((c = getchar()) != EOF)
{
if (c == '\t')
c = ' ';
if (c == ' ')
{
if (nspace < 1)
{
putchar(c);
nspace++;
nlines = 0;
}
}
else if (c == '\n')
{
if (nlines < 2)
{
putchar(c);
nlines++;
nspace = 0;
}
}
else
{
putchar(c);
nspace = 0;
nlines = 0;
}
}
if (nlines == 0)
putchar('\n');
return 0;
}
以及:
以及:
处理CRLF行结束符
注释表明上述代码在Cygwin终端上不起作用,合理的原因是正在修改的数据具有CRLF行结尾。有多种方法可以解决此问题。一种是找到一种方法,将标准输入强制转换为文本模式。在文本模式下,CRLF行结尾应映射到Unix样式的'\n'
(仅限NL或LF)输入端和Unix样式的行结束应映射到输出端的CRLF行结束
或者,可以简单地忽略CR字符:
--- sb73.c 2017-06-08 22:04:28.000000000 -0700
+++ sb47.c 2017-06-08 22:40:24.000000000 -0700
@@ -19,6 +19,8 @@
nlines = 0;
}
}
+ else if (c == '\r')
+ continue; // Windows?
else if (c == '\n')
{
if (nlines < 2)
--sb73.c 2017-06-08 22:04:28.000000000-0700
+++sb47.c 2017-06-08 22:40:24.000000000-0700
@@ -19,6 +19,8 @@
nlines=0;
}
}
+else如果(c=='\r')
+继续;//Windows?
else如果(c=='\n')
{
如果(nlines<2)
这是一个显示代码中两个额外行的“统一差异”。或者可以将不后跟LF的CR作为常规字符处理,而将后跟LF的CR作为换行组合处理:
--- sb73.c 2017-06-08 22:04:28.000000000 -0700
+++ sb59.c 2017-06-08 22:42:43.000000000 -0700
@@ -19,6 +19,17 @@
nlines = 0;
}
}
+ else if (c == '\r')
+ {
+ if ((c = getchar()) == '\n')
+ {
+ ungetc(c, stdin);
+ continue;
+ }
+ putchar('\r');
+ nspace = 0;
+ nlines = 0;
+ }
else if (c == '\n')
{
if (nlines < 2)
--sb73.c 2017-06-08 22:04:28.000000000-0700
+++sb59.c 2017-06-08 22:42:43.000000000-0700
@@ -19,6 +19,17 @@
nlines=0;
}
}
+else如果(c=='\r')
+ {
+如果((c=getchar())=='\n')
+ {
+ungetc(c、stdin);
+继续;
+ }
+putchar('\r');
+nspace=0;
+nlines=0;
+ }
else如果(c=='\n')
{
如果(nlines<2)
可能有一种方法可以编写一个处理CR的状态机,但这将更加复杂
我有一个utod
程序,可以将Unix样式的行尾转换为Windows样式;我在管道中使用它来测试代码的新变体。您提供的输出是您想要的输出或您正在获得的输出。isspace()<
--- sb73.c 2017-06-08 22:04:28.000000000 -0700
+++ sb47.c 2017-06-08 22:40:24.000000000 -0700
@@ -19,6 +19,8 @@
nlines = 0;
}
}
+ else if (c == '\r')
+ continue; // Windows?
else if (c == '\n')
{
if (nlines < 2)
--- sb73.c 2017-06-08 22:04:28.000000000 -0700
+++ sb59.c 2017-06-08 22:42:43.000000000 -0700
@@ -19,6 +19,17 @@
nlines = 0;
}
}
+ else if (c == '\r')
+ {
+ if ((c = getchar()) == '\n')
+ {
+ ungetc(c, stdin);
+ continue;
+ }
+ putchar('\r');
+ nspace = 0;
+ nlines = 0;
+ }
else if (c == '\n')
{
if (nlines < 2)