打印时如何格式化文件内容,使文件内容居中显示?

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)。

我正在尝试使用 stringstreamrdbuf() 读取 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 也很方便。或者,您可以逐个字符地输出并自己观察换行符。