c++ 在同一程序中混合使用cout和wcout

oipij1gg  于 2022-12-30  发布在  其他
关注(0)|答案(6)|浏览(229)

我正在阅读"C++ Cookbook",其中有以下片段:

// cout  << s  << std::endl;  // You shouldn't be able to
wcout << ws << std::endl;     // run these at the same time

如果你有兴趣看实际的例子,这里有一个链接到谷歌图书的页面。
还有,我发现了这个SO question,它似乎声明混合wcout和cout是可以的。有人能给我解释一下这个评论在说什么吗?

    • 编辑**

来自C标准[27.4.1]:
对相应的宽字符流和窄字符流的混合操作遵循与对FILE的混合操作相同的语义,如ISO C标准的修订1中所指定的。
来自C标准[7.19.2]:
每个流都有一个方向。在流与外部文件关联之后,但在对其执行任何操作之前,该流没有方向。一旦宽字符输入/输出函数应用于没有方向的流,该流就成为宽方向的流。类似地,一旦字节输入/输出函数应用于没有方向的流,流将成为面向字节的流。只有调用freopen函数或fwide函数才能改变流的方向。(成功调用freopen会删除任何方向。)
字节输入/输出函数不得应用于宽方向流,宽字符输入/输出函数不得应用于字节方向流。
所以,标准似乎说你不应该把它们混在一起。然而,我发现了这句话from this article
对于Visual C
10.0,fwide函数被记录为未实现。从实际的Angular 来看,至少在输出整行的级别上,混合使用cout和wcout显然工作得很好。因此,令人高兴的是,Visual C++显然忽略了标准的要求,没有维护不切实际的显式C FILE流方向。
另外,关于gcc,我发现了here中的这段话:
这是一个(新)特性,而不是bug,请参阅libstdc ++/11705和C标准(C99,7.19.2)中有关流定向的一般搜索。简单地说,您不能混合使用面向字节和面向宽的I/O。目前,由于libstdc ++/11705中指出的 * bug *,您可以通过调用std::ios::sync_with_stdio(false);在你节目的开头。

ogsagwnx

ogsagwnx1#

coutwcout第一次被调用时,stdout的方向被设置。在cout的情况下,stdout成为一个字节方向的流,在wcout的情况下,stdout成为一个宽方向的流。根据C++标准[27.4.1]和C标准[7.19.2],一旦设置了流的方向,就不应该调用与该流的方向不兼容的函数。

1zmg4dgp

1zmg4dgp2#

违反标准中的“不应该“通常会让你陷入未定义行为的领域。未定义行为在某些实现中可能会很好地工作。

wqnecbli

wqnecbli3#

从技术上讲,你完全可以同时使用窄流和宽流。然而,除非你安排它们对字符进行相同的编码,否则结果可能会很混乱。不幸的是,这伴随着一个警告,你不能控制标准流对象使用的编码,至少不能移植。即使编码是相同的,你需要确保部分字符被完全写入,也就是说,当切换到另一个宽度时,至少你需要刷新缓冲区。

5us2dqdw

5us2dqdw4#

我不知道。
除了线程,你不能"同时"运行两条语句。当然,你可以在程序的不同点使用coutwcout。它们都Map到STDOUT,就这样......尽管在某些情况下,你可能会遇到不同的缓冲区,得到稍微出乎意料的顺序。
显然,每一个都在"目的地"流STDOUT上注入了一个 * 方向 *,并且不允许在已经注入了方向[C++11: 27.4.1][C99: 7.19.2]的流上混合操作。

yrwegjxp

yrwegjxp5#

我猜:coutwcout是两个不同的流,您提供的引号没有说明流方向与底层文件方向的相关性,可能流在幕后悄悄地重新调整stdout的方向吗?

czq61nw1

czq61nw16#

  • 如果启用了与stdio同步
  • 如果首先调用cout,则标准输出流是面向字节的;
  • 如果首先调用wcout,则标准输出流是面向宽字节的;
  • 如果与stdio同步被禁用-std::ios::sync_with_stdio(false);
  • 标准输出流总是不确定的。

尝试此代码

#include <iostream>                                                             
#include <fstream>                                                              
                                                                                
void checkStdoutOrientation()                                                   
{                                                                               
    std::fstream fs("result.txt", std::ios::app);                               
    int ret = fwide(stdout, 0);                                                 
    if (ret > 0) {                                                              
        fs << "wide byte oriented\n";                                           
    } else if (ret < 0) {                                                       
        fs << "byte oriented\n";                                                
    } else {                                                                    
        fs << "undecided oriented\n";                                           
    }                                                                           
    fs.close();                                                                 
}

int main()
{
    std::ios::sync_with_stdio(false);                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::cout << "123" << std::endl;                                            
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::wcout << "456" << std::endl;                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                                       
    return 0;
}

我在Debian10+GCC8.3.0中执行它,结果是:

    • 一米二米一x**

    • 一米三米一x**

相关问题