Как выровнять пользовательский ввод в C ++ (не используя iomanip) - PullRequest
3 голосов
/ 06 апреля 2019

Предполагается, что моя программа выравнивает введенный текст в соответствии с тем, что указывает пользователь, поэтому я получил возможность изменять ширину, но не выравнивать текст (влево, вправо, по центру).Я видел <iomanip>, но это не помогает в моем случае.Код, который я получил до сих пор:

#include <iostream>
#include <sstream>
#include <vector>
#include <iterator>
using namespace std;

string repeatChar(char c, int n) {
    string out;
    for (; n > 0; n--) {
        out.push_back(c);
    }
    return out;
}
vector<string> getInput() {
    vector<string> output;
    string line;
    cout << "Enter text, empty return will quit the input" << endl;
    do {
        cout << "> ";
        getline(cin, line);
        if (line.empty())
            continue;
        istringstream in(line);
        string word;
        while (in.good()) {
            in >> word;
            if (!word.empty())
                output.push_back(word);
        }

    } while (!line.empty());
    return output;
}
void printLine(vector<string>::iterator start, vector<string>::iterator end,
        int width) {
    if(start == end)
        return;
    int chars = 0;
    int spaces = -1;
    vector<string> currentLine;
    for (; start != end; start++) {
        string &word = *start;
        int newchars = chars + word.length();
        int newspaces = spaces + 1;
        if (newchars + newspaces <= width) {
            currentLine.push_back(word);
            chars = newchars;
            spaces = newspaces;
        } else
            break;
    }
    cout << '|';
    if (spaces <= 0) {
        cout << currentLine[0] << repeatChar(' ', (width - chars));
    } else {
        int spaceWidth = (width - chars) / spaces;
        int extraWidth = (width - chars) % spaces;
        int i;
        for (i = 0; i < currentLine.size() - 1; i++) {
            cout << currentLine[i];
            cout << repeatChar(' ', spaceWidth);
            if (extraWidth > 0) {
                cout << ' ';
                extraWidth--;
            }
        }
        cout << currentLine[i];
    }
    cout << '|' << endl;
    printLine(start, end, width);
    return;
}
void printJustify(vector<string> words, int width) {
cout << '+' << repeatChar('-', width) << '+' << endl;
printLine(words.begin(), words.end(), width);
cout << '+' << repeatChar('-', width) << '+' << endl;
}
int main() {
vector<string> input = getInput();
int maxWidth = 0;
for (int i = 0; i < input.size(); i++) {
    maxWidth = (input[i].length() > maxWidth) ? input[i].length() : maxWidth;
}
int width;
do {
    cout << "> Enter width of text and align(Left, Right, Center) ";
    cin >> width;
    if (width == 0)
        continue;
    width = (width < maxWidth) ? maxWidth : width;
    printJustify(input, width);
} while (width > 0);
return 0;
}

, но он только регулирует ширину, поэтому мой вывод

Enter text, empty return will quit the input
> There are many types of Parrots in the world,
> for example, African Greys, Macaws, 
> Amazons. And much much more. 
> 
> Enter width of text and align(Left, Right, Center) 30
+------------------------------+
|There   are   many   types  of|
|Parrots   in  the  world,  for|
|example,     African    Greys,|
|Macaws,  Macaws,  Amazons. And|
|much    much    more.    more.|
+------------------------------+
> Enter width of text and align(Left, Right, Center) 

Это здорово, но мне также нужно выровнять Left, Right,Центр, в зависимости от того, что вводит пользователь.Я использовал <iomanip>, но это было бесполезно.Как я могу получить выходные данные для выравнивания влево, вправо или по центру?

1 Ответ

1 голос
/ 06 апреля 2019

Быстро и грязно.Но вы должны понять.

#include <cstdlib>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <algorithm>

std::string get_text(std::istream &is = std::cin)
{
    std::string text;

    for(std::string line; std::cout << "> ", std::getline(is, line) && !line.empty(); text += ' ' + line);

    return text;
}

enum alignment_t { align_left, align_right, align_center };
alignment_t const align_choices[]{ align_left, align_right, align_center };
char const *align_choices_strings[]{ "Left", "Right", "Center" };

std::string extract_line(std::stringstream &ss, int max_width)
{
    std::string line;
    std::string word;
    while ((ss >> word) && line.length() + word.length() + 1 <= max_width)
        line += word + ' ';

    if(line.length())
        line.pop_back();

    if (line.length() + word.length() + 1 >= max_width) {
        std::stringstream temp;
        temp << word;
        temp << ss.rdbuf();
        ss.swap(temp);
    }

    return line;
}

void print_box(std::string const &text, int width, alignment_t alignment = align_left, std::ostream &os = std::cout)
{
    for (int i = 1; i <= width; ++i)
        os << i % 10;
    os << '\n';

    os << '+' << std::setw(width) << std::setfill('-') << "+\n";

    std::stringstream ss;
    ss.str(text);

    for (std::string line{ extract_line(ss, width - 2) }; line.length(); line = extract_line(ss, width - 2)) {

        os << std::setw(1) << '|' << std::setw(width - 2) << std::setfill(' ');

        switch (alignment) {
        case align_left:
            os << std::left << line << std::setw(1) << "|\n";;
            break;

        case align_right:
            os << std::right << line << std::setw(1) << "|\n";;
            break;

        case align_center:
        {
            int fill = (width - line.length()) / 2;
            os << std::setw(fill + line.length()) << std::right << line << std::setw(width - line.length() - fill) << "|\n";
            break;
        }
        }
    }

    os << std::setw(1) << '+' << std::setw(width) << std::setfill('-') << std::right << "+\n";
}

int main()
{
    std::cout << "Enter text, empty return will quit the input\n";
    auto text{ get_text() };

    std::cout << "> Enter width of text and align(Left, Right, Center): ";
    int width;
    std::string alignment;
    auto alignment_choice{ std::cbegin(align_choices_strings) };

    if (!(std::cin >> width >> alignment) ||
        (alignment_choice = std::find(std::cbegin(align_choices_strings), std::cend(align_choices_strings), alignment))
        == std::cend(align_choices_strings))
    {
        std::cerr << "Input error.\n\n";
        std::cout << "Bye.\n\n";
        return EXIT_FAILURE;
    }

    print_box(text, width, align_choices[alignment_choice - std::cbegin(align_choices_strings)]);
}

Образцы прогонов:

Enter text, empty return will quit the input
> The journey began at
> Folly Bridge near Oxford
> and ended five miles away
> in the village of
> Godstow. During the trip
> Charles Dodgson told the
> girls a story that
> featured a bored little
> girl named Alice who goes
> looking for an adventure.
>
> Enter width of text and align(Left, Right, Center): 25 Right
+-----------------------+
|   The journey began at|
| Bridge near Oxford and|
| five miles away in the|
| of Godstow. During the|
|   Charles Dodgson told|
|     girls a story that|
|    a bored little girl|
| Alice who goes looking|
+-----------------------+
Enter text, empty return will quit the input
> The journey began at
> Folly Bridge near Oxford
> and ended five miles away
> in the village of
> Godstow. During the trip
> Charles Dodgson told the
> girls a story that
> featured a bored little
> girl named Alice who goes
> looking for an adventure.
>
> Enter width of text and align(Left, Right, Center): 30 Center
+----------------------------+
|  The journey began at Folly|
|  near Oxford and ended five|
|    away in the village of  |
|   During the trip Charles  |
| told the girls a story that|
|  a bored little girl named |
+----------------------------+
Enter text, empty return will quit the input
> The journey began at
> Folly Bridge near Oxford
> and ended five miles away
> in the village of
> Godstow. During the trip
> Charles Dodgson told the
> girls a story that
> featured a bored little
> girl named Alice who goes
> looking for an adventure.
>
> Enter width of text and align(Left, Right, Center): 40 Left
+--------------------------------------+
|The journey began at Folly Bridge     |
|Oxford and ended five miles away in   |
|village of Godstow. During the trip   |
|Dodgson told the girls a story that   |
|a bored little girl named Alice who   |
+--------------------------------------+

// исправили код - не глотает слова и последнюю строкудольше.Но я отказываюсь перезапускать это дерево раз для образца вывода.

...