C++ Windows 10是否会导致管道输出和重定向输入失败?(第二次编辑)

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++构

第二次编辑:事实证明,当程序(第一次编辑中的“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”),如下所示:

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;
}