C++ Windows 10是否会导致管道输出和重定向输入失败?(第二次编辑)
第二次编辑:事实证明,当程序(第一次编辑中的“P1”)是用Dev-C++(奥威尔的5.11版,如果需要的话)编译并在Windows 10上运行时(至少,在我办公室使用的PC上,安装了该操作系统),就会出现下面描述的问题。 如果使用MS编译器编译相同的程序,它将按预期工作(也在办公室中)。几年来,用Dev-C++编译的程序至少在两个windows7系统上运行或按预期运行 所以,我有一个简单的经验解决方案:当Dev-C++“失败”时使用MS编译器 但我还是不明白。到底发生了什么? 由Dev-C++构建的代码是否“错误”?(这将是我第一次观察到这种现象)。但它过去是有用的。。。 或者它只是与Windows 10不兼容?(使用Dev-C++编译的其他程序在Windows 10中的工作方式与在Windows 7中的工作方式完全相同)。 还是我写了一个错误的源代码(在编译器和操作系统的某些组合中)只是出于运气 这是第一次编辑: hyposis:编写并编译一个程序(比如:“P1.cpp”),如下所示:C++ Windows 10是否会导致管道输出和重定向输入失败?(第二次编辑),c++,c,windows-10,pipe,io-redirection,C++,C,Windows 10,Pipe,Io Redirection,第二次编辑:事实证明,当程序(第一次编辑中的“P1”)是用Dev-C++(奥威尔的5.11版,如果需要的话)编译并在Windows 10上运行时(至少,在我办公室使用的PC上,安装了该操作系统),就会出现下面描述的问题。 如果使用MS编译器编译相同的程序,它将按预期工作(也在办公室中)。几年来,用Dev-C++编译的程序至少在两个windows7系统上运行或按预期运行 所以,我有一个简单的经验解决方案:当Dev-C++“失败”时使用MS编译器 但我还是不明白。到底发生了什么? 由Dev-C++构
include <stdio.h>
int main(int argc, char *argv[])
{
unsigned char c;
while(1)
{
c=(unsigned char)fgetc(stdin); if(feof(stdin)) break;
if(c<=' ') fputc(c,stdout);
else if(c&128) fputc('N',stdout); // Non-ASCII
else fputc('a',stdout); // ASCII
}
return 0;
}
(编码为代码页850,DOS样式行尾)
此时,在Windows 10中运行CMD.EXE(如果需要,将代码页更改为850)和CMD中的一些命令
D>type A
aÑa
cËc
zzz
D>rffo A
FILE: "A" [cp:850]...
Offs:dec Offs:hex dec hex chr bin U-8
0 0 97 61 'a' 01100001 'a'
1 1 165 A5 'Ñ' 10100101 ?!?
2 2 97 61 'a' 01100001 'a'
3 3 13 D CR 00001101 CR
4 4 10 A LF 00001010 LF
5 5 99 63 'c' 01100011 'c'
6 6 211 D3 'Ë' 11010011 . 2
7 7 99 63 'c' 01100011 'c'
8 8 13 D CR 00001101 CR
9 9 10 A LF 00001010 LF
10 A 122 7A 'z' 01111010 'z'
11 B 122 7A 'z' 01111010 'z'
12 C 122 7A 'z' 01111010 'z'
13 D 13 D CR 00001101 CR
14 E 10 A LF 00001010 LF
D>type A | sort
aÑa
cËc
zzz
D>type A | P1
aNa
aNa
aaa
D>
注:rffo
是一个转储文件内容的程序,仅用于检查:两个非ASCII字符实际上是一个字节165/A5(CP850中的“ñ”)和一个字节211/D3(Ë”)。[在这种情况下,“U-8”列并不重要]
程序P1已按预期为ASCII字母写“a”,为非ASCII字母写“N”
现在,将“Ë”替换为“Ä”(字节142/8E),并运行相同的命令
D>type A
aÑa
cÄc
zzz
D>rffo A
FILE: "A" [cp:850]...
Offs:dec Offs:hex dec hex chr bin U-8
0 0 97 61 'a' 01100001 'a'
1 1 165 A5 'Ñ' 10100101 ?!?
2 2 97 61 'a' 01100001 'a'
3 3 13 D CR 00001101 CR
4 4 10 A LF 00001010 LF
5 5 99 63 'c' 01100011 'c'
6 6 142 8E 'Ä' 10001110 ?!?
7 7 99 63 'c' 01100011 'c'
8 8 13 D CR 00001101 CR
9 9 10 A LF 00001010 LF
10 A 122 7A 'z' 01111010 'z'
11 B 122 7A 'z' 01111010 'z'
12 C 122 7A 'z' 01111010 'z'
13 D 13 D CR 00001101 CR
14 E 10 A LF 00001010 LF
D>type A | sort
aÑa
cÄc
zzz
D>type A | P1
aNa
aNa^C
D>
就是这样:P1不起作用。在写了第二行(不包括换行符)之后,它开始无限期地等待,我不得不用[Ctrl]+[C]终止它
通过冗长乏味的测试,结果是:有“坏”的符号,也有“安全”的符号。如果读取了一个“坏”符号,程序将在包含它的行的末尾进入一个无限循环(无论行的长度如何)。
更准确地说:当读取“坏”符号后的换行符时,此指令“挂起”(永不结束):c=(unsigned char)fgetc(stdin)代码>。
(顺便说一句,如果“坏”符号在最后一行,没有CR+LF跟随,P1可以正常工作)。
“安全”符号不会造成伤害
在Windows 7中,所有符号都是“安全的”,即像P1这样的程序从未失败过。
在Windows 10中,“坏”符号使P1失败
问题是:为什么?!?
发生了什么事
一些“安全”符号是ñ、ñ、Ï(仅大写)、Ë(仅大写)、ß、ü(仅小写),以及带有单线的方框图字符,如│ ┤ ┬ 等
一些“坏”符号是ä,ë,Ä,Ü,Ü
问题不在管道中:type A | sort
工作正常
正如在一篇评论中指出的,stdin不是作为二进制文件读取的。(我怎么能把它读成二进制?)(为什么这只会给一些符号带来麻烦?)(为什么在Windows7上没有?)(为什么……?)
原始问题
一个常见的任务:有时,一组四个以“代码页850”编码的文件应该转换为UTF-8
解决方案:一个简单的程序(名为“850U8”,花了很大的力气编写),它从stdin读取字节,转换非ASCII字节,然后写入stdout。
它的用途如下:输入文件| 850U8>输出文件
如果文件日期可靠,自2016年起,该程序在Windows 7下一直正常工作。
不久前,不幸的是,电脑被另一台电脑取代,安装了Windows 10。
然后,当我尝试转换时→UTF-8,我有一个惊喜:它可以处理四个文件中的三个。对于第四个文件,它“挂起”,就像无限循环中的程序或等待未到达的输入
为了快速解决问题,我修改了程序“850U8”,让它直接读取输入文件,并直接写入输出文件。它工作正常
所以,我可以称之为“问题解决”,但我不明白发生了什么。Windows 10是否无法将类型的输出导入850U8
?为什么,以防万一?为什么四个文件中只有一个会发生这种情况(不管是什么原因)?我很困惑。任何想法都将受到高度赞赏
一些细节。。。
首先,当我说“四分之一”的时候。实际上,对于每个“作业”(一组输出),有四个文件需要转换:现在,其中一个文件的转换会定期失败。同样使用旧文件,在Windows7时代从未出现过问题
另一种尝试从标准输入运行程序的方法:850U8output\u file
也不起作用。结果与类型
和管道完全相同
同样的可执行文件,同样的输入,在我的Windows7电脑上(在家里)以各种可能的方式工作
转换失败的文件如下所示开始:
┌──────┬──┬─────┬─┬──────────────────────────────────────┬┬────┬─────┬────┐
│Xxxxxx│ │ │ │7 77-77-77 XXX:7777││X/Ä:│Xxxxx│ │
├──────┤X │XXxx │ └───────────────────────┬──────────────┘├────┼─────┤ ││││
│Xxxxx │ │ │Xxxx │Xxxxxxxxxxx │ │ │ ││ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│ X7777│ │ │XXXXX XXXXXXX │XX77777777X7777│ │ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│------│--│-----│-------------------------│---------------│----│-----│----│
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│ +│ │X7777│XXXX/XXXX.XXXXX XXXXXX │XXXX777777X7777│ │ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│ +│ │X7777│XXXX.XXXXX XXXXXX │XXXX777777X7777│ │ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
它有许多方框图字符,以及一些非ASCII字母,如第二行中的“Ä”(当然,都编码为代码页850,可能与本页不同)。
通过管道转换的其他三个文件中也存在相同的字符混合。
每行以36个空格+CR+LF结尾(每行总共111个可打印字符+CR+LF)。另外,其他三个文件的尾随空格为+CR+LF。无论如何,宽度是不同的
显示的文件有点“被删”。。。转换挂起时,此审查版本与原始文件(以及类似文件)的挂起点完全相同。
这一点在第二行的尾随空格之后,当它要读取换行符时(实际上只有LF:当它被显示出来时,Windows的type
在读取CR+LF时只输出LF)
程序“850U8”的来源
┌──────┬──┬─────┬─┬──────────────────────────────────────┬┬────┬─────┬────┐
│Xxxxxx│ │ │ │7 77-77-77 XXX:7777││X/Ä:│Xxxxx│ │
├──────┤X │XXxx │ └───────────────────────┬──────────────┘├────┼─────┤ ││││
│Xxxxx │ │ │Xxxx │Xxxxxxxxxxx │ │ │ ││ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│ X7777│ │ │XXXXX XXXXXXX │XX77777777X7777│ │ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│------│--│-----│-------------------------│---------------│----│-----│----│
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│ +│ │X7777│XXXX/XXXX.XXXXX XXXXXX │XXXX777777X7777│ │ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
│ +│ │X7777│XXXX.XXXXX XXXXXX │XXXX777777X7777│ │ │ │
├──────┼──┼─────┼─────────────────────────┼───────────────┼────┼─────┼────┤
// "Transcodifica" un file di testo: da CodePage 850 a UTF-8
// [v2]
#include <stdio.h>
unsigned char t850[]=
{
// ===UTF-8===== // CP.850
// dec, dec, dec // dec hx
0, 000, 195, 135, // 128 80
0, 000, 195, 188, // 129 81
0, 000, 195, 169, // 130 82
0, 000, 195, 162, // 131 83
0, 000, 195, 164, // 132 84
0, 000, 195, 160, // 133 85
0, 000, 195, 165, // 134 86
0, 000, 195, 167, // 135 87
0, 000, 195, 170, // 136 88
0, 000, 195, 171, // 137 89
0, 000, 195, 168, // 138 8A
0, 000, 195, 175, // 139 8B
0, 000, 195, 174, // 140 8C
0, 000, 195, 172, // 141 8D
0, 000, 195, 132, // 142 8E
0, 000, 195, 133, // 143 8F
0, 000, 195, 137, // 144 90
0, 000, 195, 166, // 145 91
0, 000, 195, 134, // 146 92
0, 000, 195, 180, // 147 93
0, 000, 195, 182, // 148 94
0, 000, 195, 178, // 149 95
0, 000, 195, 187, // 150 96
0, 000, 195, 185, // 151 97
0, 000, 195, 191, // 152 98
0, 000, 195, 150, // 153 99
0, 000, 195, 156, // 154 9A
0, 000, 195, 184, // 155 9B
0, 000, 194, 163, // 156 9C
0, 000, 195, 152, // 157 9D
0, 000, 195, 151, // 158 9E
0, 000, 198, 146, // 159 9F
0, 000, 195, 161, // 160 A0
0, 000, 195, 173, // 161 A1
0, 000, 195, 179, // 162 A2
0, 000, 195, 186, // 163 A3
0, 000, 195, 177, // 164 A4
0, 000, 195, 145, // 165 A5
0, 000, 194, 170, // 166 A6
0, 000, 194, 186, // 167 A7
0, 000, 194, 191, // 168 A8
0, 000, 194, 174, // 169 A9
0, 000, 194, 172, // 170 AA
0, 000, 194, 189, // 171 AB
0, 000, 194, 188, // 172 AC
0, 000, 194, 161, // 173 AD
0, 000, 194, 171, // 174 AE
0, 000, 194, 187, // 175 AF
0, 226, 150, 145, // 176 B0
0, 226, 150, 146, // 177 B1
0, 226, 150, 147, // 178 B2
0, 226, 148, 130, // 179 B3
0, 226, 148, 164, // 180 B4
0, 000, 195, 129, // 181 B5
0, 000, 195, 130, // 182 B6
0, 000, 195, 128, // 183 B7
0, 000, 194, 169, // 184 B8
0, 226, 149, 163, // 185 B9
0, 226, 149, 145, // 186 BA
0, 226, 149, 151, // 187 BB
0, 226, 149, 157, // 188 BC
0, 000, 194, 162, // 189 BD
0, 000, 194, 165, // 190 BE
0, 226, 148, 144, // 191 BF
0, 226, 148, 148, // 192 C0
0, 226, 148, 180, // 193 C1
0, 226, 148, 172, // 194 C2
0, 226, 148, 156, // 195 C3
0, 226, 148, 128, // 196 C4
0, 226, 148, 188, // 197 C5
0, 000, 195, 163, // 198 C6
0, 000, 195, 131, // 199 C7
0, 226, 149, 154, // 200 C8
0, 226, 149, 148, // 201 C9
0, 226, 149, 169, // 202 CA
0, 226, 149, 166, // 203 CB
0, 226, 149, 160, // 204 CC
0, 226, 149, 144, // 205 CD
0, 226, 149, 172, // 206 CE
0, 000, 194, 164, // 207 CF
0, 000, 195, 176, // 208 D0
0, 000, 195, 144, // 209 D1
0, 000, 195, 138, // 210 D2
0, 000, 195, 139, // 211 D3
0, 000, 195, 136, // 212 D4
0, 000, 196, 177, // 213 D5
0, 000, 195, 141, // 214 D6
0, 000, 195, 142, // 215 D7
0, 000, 195, 143, // 216 D8
0, 226, 148, 152, // 217 D9
0, 226, 148, 140, // 218 DA
0, 226, 150, 136, // 219 DB
0, 226, 150, 132, // 220 DC
0, 000, 194, 166, // 221 DD
0, 000, 195, 140, // 222 DE
0, 226, 150, 128, // 223 DF
0, 000, 195, 147, // 224 E0
0, 000, 195, 159, // 225 E1
0, 000, 195, 148, // 226 E2
0, 000, 195, 146, // 227 E3
0, 000, 195, 181, // 228 E4
0, 000, 195, 149, // 229 E5
0, 000, 194, 181, // 230 E6
0, 000, 195, 190, // 231 E7
0, 000, 195, 158, // 232 E8
0, 000, 195, 154, // 233 E9
0, 000, 195, 155, // 234 EA
0, 000, 195, 153, // 235 EB
0, 000, 195, 189, // 236 EC
0, 000, 195, 157, // 237 ED
0, 000, 194, 175, // 238 EE
0, 000, 194, 180, // 239 EF
0, 000, 194, 173, // 240 F0
0, 000, 194, 177, // 241 F1
0, 226, 128, 151, // 242 F2
0, 000, 194, 190, // 243 F3
0, 000, 194, 182, // 244 F4
0, 000, 194, 167, // 245 F5
0, 000, 195, 183, // 246 F6
0, 000, 194, 184, // 247 F7
0, 000, 194, 176, // 248 F8
0, 000, 194, 168, // 249 F9
0, 000, 194, 183, // 250 FA
0, 000, 194, 185, // 251 FB
0, 000, 194, 179, // 252 FC
0, 000, 194, 178, // 253 FD
0, 226, 150, 160, // 254 FE
0, 000, 194, 160 // 255 FF
};
int main(int argc, char *argv[])
{
unsigned char c;
int i;
unsigned int xx; //xx
FILE *fi=stdin;
FILE *fo=stdout;
for(i=1; i<argc; i++)
if(argv[i][0]=='/') ; // TO DO: opzioni?
else if(fi==stdin) {fi=fopen(argv[i],"rb"); if(!fi) {fprintf(stderr,"ERRORE nell'apertura del file \"%s\" (rb).\n", argv[i]); return 1;}}
else if(fo==stdout) {fo=fopen(argv[i],"wb"); if(!fo) {fprintf(stderr,"ERRORE nell'apertura del file \"%s\" (wb).\n", argv[i]); return 1;}}
else {fprintf(stderr,"Parametro \"%s\" di troppo...\n"); return 2;}
xx=0; //xx
while(1)
{
fprintf(stderr,"@%4u",xx++); //xx
c=(unsigned char)fgetc(fi); if(feof(fi)) break;
fprintf(stderr," : %3d : %2X\n", (int)c, (int)c);//xx
if(c&128) // Non-ASCII
{
i=((c&127)<<2)|1; // Indice del numero (in seconda colonna sopra, dopo lo "0" - potrebbe essere "000".
if(c=t850[i])fputc(c,fo); // 1° numero: output se non è "000".
fputc(t850[i+1],fo); // 2° numero
fputc(t850[i+2],fo); // 3° numero
}
else fputc(c,fo); // ASCII
}
if(fi!=stdin) fclose(fi);
if(fo!=stdout) fclose(fo);
return 0;
}