假设我有一个文件abc.txt
。该文件包含大量文本段落(例如,这一段:https://loremipsum.io/generator/?n=5&t=p)。
我正在尝试使用abc.txt
和stringstream
将rdbuf()
的内容读取并打印到控制台上。虽然控制台上显示的文本是完美的,但我想在每行的开头加上n
空格,并在结尾处也使用相同的n
空格。
例如,一行:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
应成为:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
在这里,我用4个空格填充了行的开头和结尾。
请注意,我不想以任何方式更改文件。它本身以read
模式打开,不允许对其进行任何写操作。
我在SO上遇到了很多有关“在C ++中居中放置文本”的答案,但是大多数答案都使用setw
。对于我来说,不可能知道每行可能包含不同的宽度(一行中的字符数),并且setw
必须大于输出(行)的宽度。
我该怎么做?
这是我现在从文件读取并将其发送到控制台的方式:
string file_slurper(std::ifstream& infile)
{
stringstream ssm;
ssm << infile.rdbuf();
return ssm.str();
}
std::ifstream read_f(files[ch_index]);
if (read_f.is_open())
{
cout << file_slurper(read_f);
}
此外,如果有帮助,我在此文件中使用Boost
库,因此如果更好,您也可以从Boost中提出一些建议。
答案 0 :(得分:1)
(我假设您的意思是相对于终端居中)
与其直接打印,不如将其作为字符串获取,将其长度与终端宽度进行比较(请参见Get size of terminal window (rows/columns))并相应地进行填充。
请注意,当字符串大于终端时,您必须考虑该怎么做。
void print_centered(const string& str)
{
int difference = terminal_width() - str.length() ;
if(difference < 0)
{
// see edit note below
cout << str.substr(0, terminal_width()) << endl;
print_centered(str.substr(terminal_width(), str.length() - terminal_width());
}
else
{
cout << string(difference/2, ' ');
cout << str << endl;
}
}
(如以上链接中所述,int terminal_width()
已实现,如果您使用多个平台,则可能有多个版本)
编辑:为差异<0的情况创建了一些内容,将其打印出可以显示的内容,然后将尾巴居中。
对于8的终端宽度,单词abcdefghijklmnopqrstuvwxyz将被打印为(用_表示空格)
abcdefgh
ijklmnop
qrstuvwx
___yz___
更复杂的方法可能是用连字符将新行分隔开,如果可能的话,可能尝试通过保持单词完整来进行分隔,甚至可能像人一样聪明地将单词分隔开(就像文本软件通常那样) ,尽管这需要一些大的努力(或者是一个非常好的了解语言的库)。
请注意,在任何情况下,如果在打印后用户调整了终端窗口的大小,那么居中当然将不再是
。另外,从您问题的评论中,您似乎出于速度原因不赞成getline
:
如果要这样做,您几乎必须逐行阅读,而且正如有人已经说过的那样,阅读和打印都已经很慢了,我真的很想知道您是否能够注意到任何区别。
在这里也许是一个重要的建议,过早的优化通常是一个错误。仅在出现问题时才进行速度优化。
答案 1 :(得分:0)
如果要使输出居中,则需要在每行前面添加可变数量的空格,该数量为((端子的宽度)-(要打印的行的长度)/ 2)。为了能够分辨每行的长度,您需要逐行读取输入内容,而不是逐字符读取。 std::getline
是一个很好的功能。
如果要在每行前面填充n个空格,请在每行前面打印n个空格。您还可以在每行之后打印n个空格,但这可能对可见输出没有影响,除了可能的丑陋和不必要的换行。至少使用不可见空格的默认设置。在这种情况下,也方便使用std::getline
。另外,您可以逐字符输出字符,并自己查看换行符。