【问题标题】:Basic C++ Text Justification基本 C++ 文本对齐
【发布时间】:2017-08-11 05:00:28
【问题描述】:

我正在尝试编写一个程序,该程序从文件中获取输入行并使其正好为 80 个字符(假设输入行始终小于 80),然后打印该行。这是通过在以下标点符号后添加最多两个空格来完成的:.,!;?如果一行少于 41 个字符,则直接打印。

如果该行仍然不是 80 个字符,则可以在整个行中添加随机空格,均匀性对此无关紧要。

输入文件是: Lorem Ipsum 只是印刷和排版行业的虚拟文本吗?洛雷姆 自 1500 年代以来,Ipsum 一直是业界标准的虚拟文本,当时 不知名的打印机拿了一个打字机,并把它打乱成一个打字标本 书。它不仅经历了五个世纪,而且经历了电子领域的飞跃 排版,基本保持不变。 1960年代普及 随着包含 Lorem Ipsum 段落等的 Letraset 表的发布 最近使用了 Aldus PageMaker 等桌面排版软件,包括 Lorem Ipsum 的版本。

输出文件应如下所示:

这个。注意每一行是如何对齐的

这是我的代码:

const int maxLine = 80;

ifstream fin("unjustified.txt");
ofstream fout("justified.txt");

void randomSpace(string &input);
void spaceAdder(string &input);

int main() {

    string inputLine;

    while (getline(fin, inputLine)) {

        if (inputLine.size() > 40)
        {
            spaceAdder(inputLine);
        }

        else {
            fout << inputLine << endl;

        }
    }

    system("pause");
    fin.close();
    fout.close();
    return 0;
}

void spaceAdder(string &input) {



    int perPos = input.find('.');
    while (perPos != string::npos && input.size() < maxLine) {
        input.insert(perPos + 1, " ");
        perPos = input.find('.', perPos + 1);
    }


    int commaPos = input.find(',');
    while (commaPos != string::npos && input.size() < maxLine) {
        input.insert(commaPos + 1, " ");
        commaPos = input.find(',', commaPos + 1);
    }


    int questPos = input.find('?');
    while (questPos != string::npos && input.size() < maxLine) {
        input.insert(questPos + 1, " ");
        questPos = input.find('?', questPos + 1);
    }


    int semiPos = input.find(';');
    while (semiPos != string::npos && input.size() < maxLine) {
        input.insert(semiPos + 1, " ");
        semiPos = input.find(';', semiPos + 1);
    }


    int exclamPos = input.find('!');
    while (exclamPos != string::npos && input.size() < maxLine) {
        input.insert(exclamPos + 1, " ");
        exclamPos = input.find('!', exclamPos + 1);
    }


    if (input.size() < maxLine) {
        randomSpace(input);


    }
    else
        fout << input << endl;


}



void randomSpace(string &input) {

    srand(time(0));

    while (input.size() < maxLine) {


        int spacePos = input.find(" ");
        bool i = (rand() % 2 == 1) ? true : false;

        if (i = true && spacePos != string::npos)
        {
            input.insert(spacePos, " ");
            spacePos = input.find(" ", spacePos + 1);

        }

    }

    fout << input << endl;
}

但是我的代码创建的输出是:

这个。请注意第 2 行和第 4 行如何与文本的其余部分不对齐

我终其一生都无法弄清楚我的代码出了什么问题。请指出我正确的方向!谢谢

【问题讨论】:

  • srand(time(0)); 应该在程序开始时调用一次,否则每次在同一秒内调用该函数时,您只会一遍又一遍地获得相同的序列。跨度>
  • 请将您的输出发布为文本,而不是图像。
  • 提示1:不是这两行太长。其他行太短了。
  • 提示 2。if (i = true &amp;&amp; ... 并没有像你想象的那样做。
  • 谢谢。我非常感谢你的提示。让我在提示 2 中解释我的想法,请告诉我我的逻辑哪里错了;我是一个新程序员。所以选择0-1之间的随机数,如果选择了1,且空格的位置不在行尾,则加一个空格。

标签: c++ string justify


【解决方案1】:

一个简单的 C++ 代码可以是:

std::ifstream input_file_stream( "file" );

unsigned counter = 0;
while( ++counter <= 80 && std::char_traits< char >::not_eof( input_file_stream.peek() ) ){
    std::cout << char ( input_file_stream.get() );
    if( counter == 80 ){
        std::cout << '\n';
        counter = 0;
    }
}

每行输出长度为80个字符:


注意

您可以将其写入输出文件,而不是使用std::cout
同样,这里缺少一些单词,例如第 2 行末尾和第 3 行开头的 the
因此,另一种解决方案可能是这样的:

输入:

Is Lorem Ipsum just dummy text of the printing and typesetting industry? Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when
an unknown printer took a galley of type and scrambled it to make a type specimen
book. It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged. It was popularised in the 1960s
with the release of Letraset sheets containing Lorem Ipsum passages, and more
recently with desktop publishing software like Aldus PageMaker including
versions of Lorem Ipsum.

C++ 代码:

std::ifstream input_file_stream( "file" );

unsigned max_size = 0;
for( std::string line; std::getline( input_file_stream, line );  ){
    // find the longest line
    if ( max_size < line.size() ) max_size = line.size();
}

input_file_stream.clear();
input_file_stream.seekg( 0 , std::ios_base::beg );  // rewind

for( std::string line; std::getline( input_file_stream, line );  ){

    if( line.size() == max_size ){
        std::cout << line << '\n';

    } else if (  line.size() > 70 ) {

        line.insert( line.rfind( ' ' ),std::string(  max_size - line.size() ,' ' ) );
        std::cout << line << '\n';

    } else {
        std::cout << line << '\n';
    }
}

input_file_stream.close();

输出:

Is Lorem Ipsum just dummy text of the printing and typesetting industry?    Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s,      when
an unknown printer took a galley of type and scrambled it to make a type specimen
book. It has survived not only five centuries, but also the leap into  electronic
typesetting, remaining essentially unchanged. It was popularised in the     1960s
with the release of Letraset sheets containing Lorem Ipsum passages, and     more
recently with desktop publishing software like Aldus PageMaker          including
versions of Lorem Ipsum.

它是如何工作的

这很容易。首先,您需要找到最长的线,这里是 81,然后根据这条最长的线,您可以使用 line.rfind(意味着找到最后一件事)和 line.insert 来证明其他线的合理性插入你想要的。由您决定每行的长度应该是多少。这里我用的是 81 到 70 之间。

每一行都根据这一行对齐:

一个不知名的印刷商拿了一个打字机,并把它打乱了做一个打字标本

但是这里的输出并不漂亮,因为最后所有空间都聚集了。为此,您可以在 else if 部分中的其他空间之间分布 所有空间,如下所示:

    } else if (  line.size() > 70 ) {

        unsigned need_space = max_size - line.size();
        unsigned count_space = std::count( line.begin(), line.end(), ' ' );

        std::istringstream iss( line );
        std::string temp_line;

        while( need_space-- && count_space-- ){
            std::string temp;
            iss >> temp;
            temp_line +=  temp + "__";
        }
        iss.get();  // get rid of a single space in the iss stream
        // extracts the rest of the iss stream:
        temp_line.append(  std::istreambuf_iterator<char>( iss ), std::istreambuf_iterator<char>() );
        std::cout  << temp_line << '\n';

    } else {
        std::cout << line << '\n';
    }

输出:

Is__Lorem__Ipsum__just dummy text of the printing and typesetting industry? Lorem
Ipsum__has__been__the__industry's__standard dummy text ever since the 1500s, when
an unknown printer took a galley of type and scrambled it to make a type specimen
book.__It has survived not only five centuries, but also the leap into electronic
typesetting,__remaining__essentially__unchanged.__It was popularised in the 1960s
with__the__release__of__Letraset sheets containing Lorem Ipsum passages, and more
recently__with__desktop__publishing__software__like__Aldus__PageMaker__including
versions of Lorem Ipsum.

正如您在此处看到的,我使用 __ 而不是 2-spaces 来显示输出中发生的情况,因此您可以将其更改为 2 个空格。 虽然代码仍然有一些问题,例如 最后一行 没有像其他人一样修复,但我不想让代码复杂,我认为这对于大多数情况来说已经足够了。

【讨论】:

  • 谢谢。这是一个很好的见解,但是我是一个非常新的程序员,试图仅使用我目前所学的知识来完成这项任务。
【解决方案2】:

您的spaceAdder 函数仅检查字符串的长度

if (input.size() < maxLine) {
    randomSpace(input);
}
else
    fout << input << endl;

在所有的标点空格都被添加之后。

【讨论】:

  • 我的意图是:1)如果字符串的大小小于最大值(80),则将其发送到 randomSpace 使其变为 80。2)否则,打印字符串,因为它不小于最大值
【解决方案3】:

你在哪里:

while (input.size() < maxLine) {...}

我相信你想拥有:

//changed < to <=
while (input.size() <= maxLine) {...}

同样如此:

if (input.size() < maxLine) {
    randomSpace(input);
}

改为:

//changed < to <=
if (input.size() <= maxLine) {
    randomSpace(input);
}

【讨论】:

  • 感谢您的回复。我将这两个操作数都更改为您建议的内容,但对输出没有影响。
【解决方案4】:

这是我对此的看法。我假设您的输入文本实际上是断线,而不是一条长线,这实际上会使事情变得更简单,因为 k-5 的答案显示。

我的输入文件:(第一行是保证一行上的多个标点符号能正常工作)

a.b,c.d,e?f;g?h!i.j;k?l,ma.b,c.d,e?f;g?h!i.j;k?l,m
Lorem Ipsum just dummy text of the printing and typesetting industry? Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen
book. It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged. It was popularised in the 1960s
with the release of Letraset sheets containing Lorem Ipsum passages, and more
recently with desktop publishing software like Aldus PageMaker including
versions of Lorem Ipsum.

我的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>

using namespace std;

const int maxLine = 80;

void padAfterPunctuation(string &input)
{
    const std::string punct = ".,?;!";

    for (char p : punct)
// for(size_t i = 0; i < punct,size(); ++i) if you can't use a range based for loop.
// use punct[i] rather than p in find below as well.
    {
        size_t pos = 0;
        while ((pos = input.find(p, pos)) != string::npos && input.size() < maxLine)
        {
            input.insert(++pos, " ");
        }
    }
}

void padRandomAfterSpace(string &input)
{
    size_t pos = 0;
    while (input.size() < maxLine)
    {
        pos = input.find(' ', pos);
        if (pos < input.size() && pos != string::npos)
        {
            if (rand() & 1)
            {
                input.insert(pos, " ");
            }
            pos = input.find_first_not_of(' ', pos);
        }
        else
        {
            pos = 0;
        }
    }
}

int main()
{
    srand(time(0));

    ifstream fin("unjustified.txt");
    ofstream fout("justified.txt");
    string inputLine;

    while (getline(fin, inputLine))
    {
        if (inputLine.size() > 40 && inputLine.size() < maxLine)
        {
            padAfterPunctuation(inputLine);
            if (inputLine.size() < maxLine)
            {
                padRandomAfterSpace(inputLine);
            }
        }
        fout << inputLine << endl;
    }
    return 0;
}

我没有花太多时间找出您的代码出了什么问题,但是看着它我怀疑 c.z.是正确的。我没有向一个过长和复杂的函数添加更多代码,而是选择了简化,这样可以在添加每个空格后轻松检查行长。

我还选择在 main 中使您的文件成为局部变量,并在一个地方写入数据。最好使范围尽可能小,并且每个函数都有一个单一的职责,以避免可能多次写入数据。我没有明确关闭这些文件,因为它们会在超出范围时自动关闭。

示例输出:

a.  b, c.  d,  e?  f; g? h!  i.  j; k? l, ma. b, c. d, e? f; g? h! i. j; k? l, m
Lorem Ipsum  just dummy  text of  the  printing and typesetting industry?  Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s,  when an
unknown printer took  a galley  of type and scrambled it to make a type specimen
book. It has survived not only five centuries, but also the leap into electronic
typesetting,   remaining essentially unchanged.  It was popularised in the 1960s
with the release  of  Letraset sheets containing Lorem Ipsum passages,  and more
recently   with  desktop  publishing  software like  Aldus  PageMaker  including
versions of Lorem Ipsum.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-03
    • 2020-07-12
    • 2013-08-11
    • 2015-02-12
    • 2020-05-23
    • 2017-02-17
    • 2011-08-10
    • 2013-07-10
    相关资源
    最近更新 更多