打印时如何格式化文件内容,使文件内容居中显示?
How to format a file's content when printing it so that the file's contents appear centered?
假设我有一个文件 abc.txt
。该文件包含大量文本段落(例如,这个:https://loremipsum.io/generator/?n=5&t=p)。
我正在尝试使用 stringstream
和 rdbuf()
读取 abc.txt
的内容并将其打印到控制台上。虽然控制台上显示的文本是完美的,但我想用 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 上看到了很多关于 "centering text in 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 中推荐一些东西。
(我假设你的意思是相对于终端居中)
与其直接打印它,不如将其作为字符串获取,将其长度与终端宽度进行比较(参见 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()
的实现详见上文 link,如果您使用多个平台,可能会在多个版本中实现)
编辑:为 difference < 0 case 创建了一些东西,打印它可以打印的内容,然后将尾部居中。
对于 8 的终端宽度,单词 abcdefghijklmnopqrstuvwxyz 将打印为(空格为 _)
abcdefgh
ijklmnop
qrstuvwx
___yz___
更复杂的方法可能会用连字符分隔新行,可能会尝试通过尽可能保持单词完整来分隔,或者甚至可能足够聪明,可以像人一样在单词内进行分隔(就像文本软件通常做的那样)确实如此),尽管这需要付出很大的努力(或者一个非常好的了解语言的图书馆)。
请注意,在任何情况下,如果终端 window 在打印后由用户调整大小,那么居中当然会停止。
另外,从你的问题的评论来看,你似乎不喜欢 getline
因为速度的原因:
如果你想这样做,你几乎必须逐行阅读,正如有人已经说过的,阅读和打印都已经很慢了,我真的很想知道你是否能够注意到任何差异。
也许这里有一个重要的建议,过早的优化通常是一个错误。仅当它成为问题时才优化速度。
如果要使输出居中,则需要在每行前面添加可变数量的空格,数量为((终端宽度)-(打印行长度)/2)。为了能够分辨出每一行的长度,您需要逐行而不是逐字符读取您的输入。 std::getline
是一个很好的功能。
如果要在每行前补n个空格,则在每行前打印n个空格。您也可以在每行之后打印 n 个空格,但这可能对可见输出没有影响,除了可能的丑陋和不必要的换行。至少在空格不可见的默认设置下。在这种情况下使用 std::getline
也很方便。或者,您可以逐个字符地输出并自己观察换行符。
假设我有一个文件 abc.txt
。该文件包含大量文本段落(例如,这个:https://loremipsum.io/generator/?n=5&t=p)。
我正在尝试使用 stringstream
和 rdbuf()
读取 abc.txt
的内容并将其打印到控制台上。虽然控制台上显示的文本是完美的,但我想用 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 上看到了很多关于 "centering text in 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 中推荐一些东西。
(我假设你的意思是相对于终端居中)
与其直接打印它,不如将其作为字符串获取,将其长度与终端宽度进行比较(参见 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()
的实现详见上文 link,如果您使用多个平台,可能会在多个版本中实现)
编辑:为 difference < 0 case 创建了一些东西,打印它可以打印的内容,然后将尾部居中。
对于 8 的终端宽度,单词 abcdefghijklmnopqrstuvwxyz 将打印为(空格为 _)
abcdefgh
ijklmnop
qrstuvwx
___yz___
更复杂的方法可能会用连字符分隔新行,可能会尝试通过尽可能保持单词完整来分隔,或者甚至可能足够聪明,可以像人一样在单词内进行分隔(就像文本软件通常做的那样)确实如此),尽管这需要付出很大的努力(或者一个非常好的了解语言的图书馆)。
请注意,在任何情况下,如果终端 window 在打印后由用户调整大小,那么居中当然会停止。
另外,从你的问题的评论来看,你似乎不喜欢 getline
因为速度的原因:
如果你想这样做,你几乎必须逐行阅读,正如有人已经说过的,阅读和打印都已经很慢了,我真的很想知道你是否能够注意到任何差异。
也许这里有一个重要的建议,过早的优化通常是一个错误。仅当它成为问题时才优化速度。
如果要使输出居中,则需要在每行前面添加可变数量的空格,数量为((终端宽度)-(打印行长度)/2)。为了能够分辨出每一行的长度,您需要逐行而不是逐字符读取您的输入。 std::getline
是一个很好的功能。
如果要在每行前补n个空格,则在每行前打印n个空格。您也可以在每行之后打印 n 个空格,但这可能对可见输出没有影响,除了可能的丑陋和不必要的换行。至少在空格不可见的默认设置下。在这种情况下使用 std::getline
也很方便。或者,您可以逐个字符地输出并自己观察换行符。