我正在使用带有特殊字符的c ++字符串进行控制台输出。大部分结果都是可以预测的,但是其中之一超出了我的预期。我在任何地方都找不到答案。
平台: Windows 7企业版6.1(内部版本7601:Service Pack 1) 编译器: g ++(GCC)8.2.0,c ++ 17
#include <iostream>
int main(){
using namespace std;
char numString[12] = "0123456789\n";
//This is group 1
numString[3] = '\t';
numString[4] = '\b';
cout << "Group 1 output:\n" << numString << endl;
//This is group 2
numString[3] = '\b';
numString[4] = '\t';
cout << "Group 2 output:\n" << numString << endl;
//This is group 3
numString[3] = '\n';
numString[4] = '\b';
cout << "Group 3 output:\n" << numString << endl;
//This is group 4
numString[3] = '\b';
numString[4] = '\n';
cout << "Group 4 output:\n" << numString << endl;
//This is group 5
numString[2] = '\b';
numString[3] = '\b';
numString[4] = '\n';
cout << "Group 5 output:\n" << numString << endl;
return 0;
}
控制台中的输出:
Group 1 output: 01256789 Group 2 output: 01 56789 Group 3 output: 012 56789 Group 4 output: 012 56789 Group 5 output: 01 56789
第四组输出预期为
Group 4 output: 01 56789
实际上是输出,
Group 4 output: 012 56789
我不明白的是为什么字符'2'仍然存在。
任何人都可以帮助我理解问题吗? 谢谢。
看到下面的答案,尤其是zar的答案后,我相信我已经理解了这个问题,并且想在这里总结一下。
请注意移动光标。
我想在这里粘贴所有代码:
//strwithspecialchar.cpp -- Understand special characters in C++ string
#include <iostream>
int main(){
using namespace std;
char numString[12] = "0123456789\n";
//This is group 1
numString[3] = '\t';
numString[4] = '\b';
cout << "Group 1 output:\n" << numString << endl;
//This is group 2
numString[3] = '\b';
numString[4] = '\t';
cout << "Group 2 output:\n" << numString << endl;
//This is group 3
numString[3] = '\n';
numString[4] = '\b';
cout << "Group 3 output:\n" << numString << endl;
//This is group 4
numString[3] = '\b';
numString[4] = '\n';
cout << "Group 4 output:\n" << numString << endl;
//This is group 5
numString[2] = '\b';
numString[3] = '\b';
numString[4] = '\n';
cout << "Group 5 output:\n" << numString << endl;
//This is group 6
numString[2] = '\b';
numString[3] = '3';
numString[4] = '\n';
cout << "Group 6 output:\n" << numString << endl;
//This is group 7
numString[2] = '2';
numString[3] = '\b';
numString[4] = '\a';
cout << "Group 7 output:\n" << numString << endl;
//This is group 8
numString[3] = '\b';
numString[4] = '\r';
cout << "Group 8 output:\n" << numString << endl;
//This is group 9
numString[3] = '\b';
numString[4] = '\n';
numString[8] = '\r';
cout << "Group 9 output:\n" << numString << endl;
return 0;
}
下面的输出可以更好地理解这些特殊字符:
Group 1 output: 01256789 Group 2 output: 01 56789 Group 3 output: 012 56789 Group 4 output: 012 56789 Group 5 output: 01 56789 Group 6 output: 03 56789 Group 7 output: 0156789 Group 8 output: 56789 Group 9 output: 012 967
答案 0 :(得分:9)
这取决于您的终端。我们可以轻松地从一个平台上看到,该平台不会以it's present in the string at the expected location的任何特殊方式呈现控制字符'\b'
:
那么,为什么不“擦除” 2
?
如果我们打开cmd.exe并键入 A , B , Ctrl + H ,则我们看到B
被立即删除。这似乎证明cmd.exe“无损地”处理退格键as many consoles do的观点。
但这并不能反驳它!这似乎是对按键的一种特殊处理,大概与实际的退格字符的工作方式有关。毕竟,您希望退格字符实际上是擦除内容,而不是仅移动光标。
如果在不是由键盘生成的输出中找到cmd.exe,则以不同的方式对待控制字符:以一种非破坏性的方式。因此它将向后移动光标,然后下一个字符“覆盖”将要擦除的字符。
但是在第4组中,您有换行符,因此下一个字符位于下一行,并且不在正确的位置以擦除任何内容。
我们可以通过构建一个特殊文件,然后指示cmd.exe打印它来在不使用C ++的情况下重现它:
“正在工作”
“不起作用”
(您可以使用“编辑” /“字符面板”菜单项在Notepad ++中插入特殊字符ASCII 08。)
我的结论是,不要依赖于控制代码来进行此类“技巧”:如果您想从字符串中删除字符,实际上可以这样做;如果要创建GUI,则可以这样做,或者使用像 ncurses 这样的聪明的库来模拟一个GUI。
答案 1 :(得分:3)
控制台显示的是正确的输出,即
Group 4 output:
012
56789
您误会了
Group 4 output:
01
56789
\b
字符的作用是将光标向后移动一个字符,不将其删除。因此发生的事情是将光标移回2,但字符仍然在那里。
012
^
下一个字符\n
不是可打印字符,而是控制字符,它只是将光标移动到下一行,因此不会覆盖已打印的字符。
如果您改为这样做:
//This is group 4
numString[3] = '\b';
numString[4] = 'X';
cout << "Group 4 output:\n" << numString << endl;
现在\b
移到2,但是下一个字符'X'立即覆盖,它产生了预期的以下结果。
Group 4 output:
01X56789
另一个演示是即使您添加了另一个退格键:
numString[3] = '\b';
numString[4] = '\b';
numString[5] = '\n';
光标现在位于1
012
^
现在它遇到\n
(新行)作为下一个字符,它只是将光标移动到下一行,因此1和2永远不会被覆盖,因为它们已经被打印,并且现在保留在 previous中行。
因此,现在的输出符合预期:
Group 4 output:
012
6789