将C中的空行压缩为一个空行

将C中的空行压缩为一个空行,c,C,您好,请参考相同的问题,但代码不同 我想把多个空行压缩成一个空行,但它似乎不起作用,在StgOUT上的CygWin终端上,最后一行给了我一个额外的空行,虽然输入端没有空行。p> 例如 输入 期望输出 实际产量 请解释 您正在两次递增nlines: else if(c == '\n'){ if(++nlines >2){ /* incremented here */ continue; } else { nlines++;

您好,请参考相同的问题,但代码不同

我想把多个空行压缩成一个空行,但它似乎不起作用,在StgOUT上的CygWin终端上,最后一行给了我一个额外的空行,虽然输入端没有空行。p> 例如
输入

期望输出

实际产量


请解释

您正在两次递增
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)