方向是什么意思?我认为可以解释为粒度。众所周知,OOD是面向对象设计,这意味着设计的粒度是对象。另一个例子是字节流定向协议——TCP,这意味着如果我们基于TCP构建应用程序,我们必须关注字
一些示例
我编写了一个名为checkStdoutOrientation
的函数,用于获取标准输出流的方向
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();
}
演示01:先调用wcout,然后调用cout
#include <cstdio>
#include <iostream>
#include <fstream>
int main()
{
checkStdoutOrientation();
std::wcout << "456" << std::endl;
checkStdoutOrientation();
std::cout << "123" << std::endl;
checkStdoutOrientation();
return 0;
}
Debian10 Buster + GCC 8.3.0
输出:
![在此输入图像描述](https://istack.dev59.com/S5gh5.webp)
result.txt:
![在此输入图像描述](https://istack.dev59.com/h6Kp4.webp)
我的理解:
- 首先调用了wcout,因此标准输出流是宽字节定向的;
- 正因为上述情况,由cout处理的内容无法被标准输出流处理,因此“123”无法打印出来;
Win10 + VS2022
输出:
![在此输入图像描述](https://istack.dev59.com/qrQeV.webp)
result.txt:
![在此输入图像描述](https://istack.dev59.com/wzUoE.webp)
我的理解:
- 似乎窗口不符合标准,标准输出流总是未决定的方向;
- 正因为标准输出流的未决定方向,所有内容都被打印出来。
Demo02: 先调用cout,再调用wcout
#include <cstdio>
#include <iostream>
#include <fstream>
int main()
{
checkStdoutOrientation();
std::cout << "123" << std::endl;
checkStdoutOrientation();
std::wcout << "456" << std::endl;
checkStdoutOrientation();
return 0;
}
Debian10 Buster + GCC 8.3.0
输出:
![enter image description here](https://istack.dev59.com/Bg3Za.webp)
result.txt:
![enter image description here](https://istack.dev59.com/LSOoT.webp)
我的理解:
- 首先调用cout,因此标准输出流是字节定向的;
- 由于字节比宽字节更小的粒度,因此wcout内容到字节定向的标准输出流最终可以打印到控制台。
Win10 + VS2022
输出:
result.txt:
我的理解:
- 标准输出流始终是未决定方向的;
- 因此所有内容都会被打印。
Demo03:先调用wprintf,再调用printf
int main()
{
checkStdoutOrientation();
wprintf(L"456\n");
checkStdoutOrientation();
printf("123\n");
checkStdoutOrientation();
return 0;
}
“这是与Demo01相同的结论。”
Demo04:先调用printf,然后调用wprintf
#include <cstdio>
#include <iostream>
#include <fstream>
int main()
{
checkStdoutOrientation();
printf("123\n");
checkStdoutOrientation();
wprintf(L"456\n");
checkStdoutOrientation();
return 0;
}
Debian10 buster + GCC 8.3.0
输出:
![enter image description here](https://istack.dev59.com/5cnXL.webp)
result.txt:
![enter image description here](https://istack.dev59.com/LSOoT.webp)
我的理解:
- 首先调用cout,因此标准输出流是字节定向的;
- 与Demo02的结果不同,我不知道为什么没有显示"456"。
Win10 + VS2022
输出:
![在这里输入图像描述](https://istack.dev59.com/9ytN7.webp)
result.txt:
![在这里输入图像描述](https://istack.dev59.com/wzUoE.webp)
我的理解:
Demo05:禁用与 stdio、wcout 和 cout 的同步
#include <cstdio>
#include <iostream>
#include <fstream>
int main()
{
std::ios::sync_with_stdio(false);
checkStdoutOrientation();
std::wcout << "456" << std::endl;
checkStdoutOrientation();
std::cout << "123" << std::endl;
checkStdoutOrientation();
return 0;
}
Debian10 Buster + GCC 8.3.0
输出:
![输入图像描述](https://istack.dev59.com/okCqZ.webp)
result.txt:
![输入图像描述](https://istack.dev59.com/fTdBa.webp)
我的理解:
- 禁用与stdio同步后,标准输出流始终是未决定方向的;
- 因此所有内容都可以打印。
Win10 + VS2022
输出:
result.txt:
我的理解:
Demo06: 混合使用cout和printf
#include <cstdio>
#include <iostream>
int main()
{
printf("1\n");
std::cout << "2\n";
printf("3\n");
std::cout << "4\n";
printf("5\n");
printf("\n");
std::ios::sync_with_stdio(false);
printf("1\n");
std::cout << "2\n";
printf("3\n");
std::cout << "4\n";
printf("5\n");
return 0;
}
Debian10 Buster + GCC 8.3.0
输出:
![enter image description here](https://istack.dev59.com/gRekZ.webp)
我的理解:
- 默认情况下启用了与stdio的同步,因此混合使用cout和printf只需调用cout或printf即可。
- 禁用与stdio的同步后,cout将独立工作,cout和printf各自为政,因此打印内容会失序。
Win10 + VS2022
输出:
![enter image description here](https://istack.dev59.com/wk9At.webp)
我的理解:
- Windows仍然很特别,无论是否禁用与stdio的同步,混合使用cout和printf只需调用cout或printf即可。
演示07:打印非ASCII字符 -- 方法A
#include <cstdio>
#include <iostream>
int main()
{
std::locale myloc("en_US.UTF-8");
std::locale::global(myloc);
std::wcout << L"漢字\n";
wprintf(L"漢字\n");
return 0;
}
Debian10 Buster + GCC 8.3.0
输出:
![enter image description here](https://istack.dev59.com/9Nhhn.webp)
我的理解:
- 设置全局语言环境不会影响wcout,因为wcout的语言环境是C语言环境。这是因为wcout是一个对象,在构造对象时已经设置了它的语言环境。
- 那么在这种情况下,为什么wcout可以打印内容呢?别忘了C++的iostream默认与stdio同步,我们可以简单地认为,wcout在stdio的缓冲区上工作,而stdio已经通过
global(myloc)
代码设置为en_US.UTF-8。
Win10 + VS2022
输出:
Demo08: 打印非ASCII字符 -- 方法B
#include <cstdio>
#include <iostream>
int main()
{
std::ios::sync_with_stdio(false);
std::locale myloc("en_US.UTF-8");
std::wcout.imbue(myloc);
std::wcout << "wcout> " << L"漢字\n";
wprintf(L"wprintf> 漢字\n");
return 0;
}
Debian10 Buster + GCC 8.3.0
输出:
![enter image description here](https://istack.dev59.com/hiTLo.webp)
我的理解:
- 由于禁用了与stdio的同步,wprintf和wcout分别工作,因此打印顺序不正确;
- 仍然由于同步被禁用,wcout应该独立工作,因此我们必须通过
imbue
方法将wout的区域设置为en_US.UTF-8,如果不这样做,wcout将打印出类似“??”的内容;
- wprintf打印“??”,这是因为我们注释掉了
std::locale::global(myloc);
,所以stdio的区域仍然是C区域。
Win10 + VS2022
演示09:打印非ASCII字符 - 方法C
此演示依赖于Windows平台。
输出:
![enter image description here](https://istack.dev59.com/cGMsM.webp)
我的理解:
- printf和cout总是按顺序打印,这是Windows的特殊之处,已经提到过多次;
- wprintf打印空值相当于Linux中的“??”;
- 所以,新的问题是乱码!我尝试取消注释
std::locale::global(myloc);
代码,打印内容就可以了!因此,我认为Windows的实现有点特殊,wcout可能依赖更多需要通过全局语言环境设置更改的东西。
#include <cstdio>
#include <iostream>
int main()
{
_setmode(_fileno(stdout), _O_WTEXT);
std::wcout << "wcout> " << L"漢字\n";
wprintf(L"wprintf> 漢字\n");
return 0;
}
Win10 + vs2022
输出:
![输入图像描述](https://istack.dev59.com/EPTNd.webp)
我的理解:
- _setmode 后,全局和 wcout 区域设置仍然是 C 区域设置;
- 为什么 wcout 和 wprintf 都能正确打印内容?我猜可能是 Windows 在标准输出流之后实现了一种机制,通过 _setmode 指定的模式来转换内容。
std::wcout << std::endl; /* 添加此行会使 printf 消失!!! */ rl_bind_key('\t',rl_abort);//禁用自动完成 while((buf = readline("my-command : "))!=NULL) { if (strcmp(buf,"quit")==0) break; std::wcout<}
- Bo Jensencout
和printf
,而问题是关于混合使用cout
和wcout
的? - kennytm