您好,请参考相同的问题,但代码不同。
Replacing multiple new lines in a file with just one
int main(void){
format();
printf("\n");
return 0;
}
void format(){
int c;
size_t nlines = 1;
size_t nspace = 0;
while (( c= getchar()) != EOF ){
/*TABS*/
if(c == '\t'){
c = ' ';
}
/*SPACES*/
if (c ==' '){
if(nspace > 0){
continue;
}
else{
putchar(c);
nspace++;
nlines = 0;
}
}
/*NEW LINE*/
else if(c == '\n'){
if(++nlines >2){
continue;
}
else {
nlines++;
nspace = 0;
}
putchar(c);
}
else{
putchar(c);
nspace = 0;
nlines = 0;
}
}
}
我想将多个空白行挤入一个空白行,但它似乎无法正常工作,在stdout上的Cygwin终端上,最后一行给了我额外的空白行,尽管输入没有空白最后一行。
例如
INPUT
Hello Hi\n
\n
\n
Hey\t\tHola\n
期望的输出
Hello Hi\n
\n
Hey Hola\n
实际输出
Hello Hi\n
Hey Hola\n
请解释一下!
答案 0 :(得分:1)
您正在递增nlines
两次:
else if(c == '\n'){
if(++nlines >2){ /* incremented here */
continue;
}
else {
nlines++; /* incremented here */
nspace = 0;
}
putchar(c);
}
你只想做一次。我建议只需递增计数器直到它达到2然后再不再增加它。这只是一个小小的变化:
if(nlines >= 2){
continue;
}
答案 1 :(得分:1)
这是您的代码的变体。我删除了format()
函数(这对我来说很不寻常,因为SO上的大部分程序都没有使用足够的函数)直接将它合并到main()
中。该代码现在更加对称地处理空格和换行符,修复了paddy answer中确定的双增量问题。如果最后还没有换行,它也只会在最后打印出换行符。这样可以标准化不以换行符结尾的文件。 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;
}
我的测试使用了一些特定于Bash的表示法。我的计划是sb73
:
最后一个测试输入不包括最终换行符。输出使用⌴表示输出中的换行符:
$ echo $'Hello Hi\n\n\nHey\t\tHola\n' | sb73
Hello Hi⌴
⌴
Hey Hola
⌴
$
和
$ echo $'\n\nHello Hi\n\n\n Hey\t\tHola\n' | sb73
⌴
Hello Hi⌴
⌴
Hey Hola⌴
⌴
$
和
$ printf '%s' $'\n\nHello Hi\n\n\n Hey\t\tHola' | sb73
⌴
Hello Hi⌴
⌴
Hey Hola⌴
$
注释表明上面的代码不能在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)
这是一个统一的差异&#39;在代码中显示两行。或者可以处理CR后面没有LF作为常规字符,但处理CR后跟LF作为换行组合:
--- 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)
可能有办法编写处理CR的状态机,但这会更复杂。
我有一个utod
程序,可以将Unix风格的行结尾转换成Windows风格;我在管道中使用它来测试代码的新变种。