gpt4 book ai didi

c++ - C++换行符中的ascii艺术生成器

转载 作者:行者123 更新时间:2023-12-02 18:33:29 25 4
gpt4 key购买 nike

我正在尝试生成给定字符串的 ASCII 艺术。

艺术.cpp

#pragma once

#include <string>
#include <vector>

#include "art.h"

std::string Art::display(std::string& text) {
std::string final_text;
final_text.reserve(text.length());
for (char letter: text) {
std::string single = letters[letter];
/* tried this */ single.erase(std::remove(single.begin(), single.end(), '\n'), single.end());
final_text += single;
}
return final_text;
}

艺术.h

#pragma once

#include <string>
#include <vector>
#include <map>

class Art {
public:
std::map<char, std::string> letters = {
std::make_pair('a', std::string(R"(
_
/ \
/ _ \
/ ___ \
/__/ \__\
)")),
std::make_pair('b', std::string(R"(
____
| __ )
| _ \
| |_) |
|____/
)")),
std::make_pair('c', std::string(R"(
____
/ ___|
| |
| |___
\____|
)")),
std::make_pair('d', std::string(R"(
____
| _ \
| | | |
| |_| |
|____/
)")),
std::make_pair('e', std::string(R"(
_____
| ____|
| _|
| |___
|_____|
)")),
std::make_pair('f', std::string("asdf")),
std::make_pair('g', std::string("asdf")),
std::make_pair('h', std::string(R"(
_ _
| | | |
| |_| |
| _ |
|_| |_|
)")),
std::make_pair('i', std::string("asdf")),
std::make_pair('j', std::string("asdf")),
std::make_pair('k', std::string(R"(
_ __
| |/ /
| ' /
| . \
|_|\_\
)")),
std::make_pair('l', std::string("asdf")),
std::make_pair('m', std::string("asdf")),
std::make_pair('n', std::string("asdf")),
std::make_pair('o', std::string(R"(
___
/ _ \
| | | |
| |_| |
\___/
)")),
std::make_pair('p', std::string("asdf")),
std::make_pair('q', std::string("asdf")),
std::make_pair('r', std::string(R"(
____
| _ \
| |_) |
| _ <
|_| \_\
)")),
std::make_pair('s', std::string("asdf")),
std::make_pair('t', std::string("asdf")),
std::make_pair('u', std::string("asdf")),
std::make_pair('v', std::string("asdf")),
std::make_pair('w', std::string("asdf")),
std::make_pair('x', std::string("asdf")),
std::make_pair('y', std::string(R"(
__ __
\ \ / /
\ V /
| |
|_|
)")),
std::make_pair('z', std::string("asdf"))

};

std::string display(std::string& text);

};

这是采用 str 引用,然后循环遍历每个字符并在映射中找到该字符并获取其对应的 ASCII 艺术字母,然后将其添加到最终字符串。
这就提出了一个问题。当我想打印 Art::display() 返回的字符串时,它会在新行上打印每个字符。
我试过什么?我曾尝试删除换行符,但这会把零碎的东西混在一起/分开。
我想让它做什么?我希望它从左到右打印一个单词,而不是在新行上打印每个字符。

最佳答案

我将添加一个 Letter 类来简化解析和打印字母。

例子:

#include <iomanip>
#include <iostream>
#include <map>
#include <string_view>
#include <vector>

class Letter {
public:
// The constructor takes a string_view and parses it into lines that
// it stores in a vector<string_view>
Letter(std::string_view l) : width_(0) {
auto b = l.begin();
for(auto it = b; it != l.end(); ++it) {
if(*it == '\n') {
auto w = it - b;
if(w > width_) width_ = w;
svs.emplace_back(b, w);
b = it + 1;
}
}
auto w = l.end() - b;
if(w > width_) width_ = w;
svs.emplace_back(b, w);
}

// some convenience functions
unsigned width() const { return width_; }
unsigned height() const { return svs.size(); }

// An operator to get a specific line to render from this Letter.
// It returns a string with the proper width (the max width of all the
// lines for this Letter). If `line` is out of bounds, it returns a
// blank line.
std::string operator()(unsigned line) const {
if(line >= svs.size()) return std::string(width_, ' ');
return std::string(svs[line]) + std::string(width_ - svs[line].size(), ' ');
}

// If you just want to print one letter:
friend std::ostream& operator<<(std::ostream& os, const Letter& l) {
for(auto& sv : l.svs) os << sv << '\n';
return os;
}

private:
std::vector<std::string_view> svs;
unsigned width_;
};

// A user defined literal operator to simplify creating the map:
Letter operator "" _L(const char* str, std::size_t len) {
return std::string_view{str, len};
}

//---------------------------------------------------------------
std::map<char, Letter> letters = {
{' ', " "_L }, // space
{'a',
R"( _
/ \
/ _ \
/ ___ \
/__/ \__\
)"_L},
{'b',
R"( ____
| __ )
| _ \
| |_) |
|____/
)"_L}
}; // note that each Letter ends with _L to trigger the user defined literal

// A printing function that can either be called with a specified height,
// or be made to find the appropriate height for this string.
void print(std::string_view txt, unsigned height = 0) {
if(height == 0) {
for(char ch : txt) {
try {
auto w = letters.at(ch).height();
if(w > height) height = w;
}
catch(...) {} // don't mind non-existing letters
}
}
for(unsigned i = 0; i < height; ++i) {
for(char ch : txt) {
const Letter& l = letters.at(ch);
std::cout << l(i);
}
std::cout << '\n';
}
}

int main() {
print("abab baba");
}

输出:

    _     ____      _     ____      ____      _     ____      _    
/ \ | __ ) / \ | __ ) | __ ) / \ | __ ) / \
/ _ \ | _ \ / _ \ | _ \ | _ \ / _ \ | _ \ / _ \
/ ___ \ | |_) | / ___ \ | |_) | | |_) | / ___ \ | |_) | / ___ \
/__/ \__\|____/ /__/ \__\|____/ |____/ /__/ \__\|____/ /__/ \__\

注意:MSVC(Visual Studio 中包含的编译器)出于某种原因在我的 string_view 上出现问题。下面是一个使用 std::string 来让 MSVC 满意的版本:

#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <vector>

class Letter {
public:
// The constructor takes a string_view and parses it into lines that
// it stores in a vector<string_view>
Letter() = default;
Letter(const std::string& str) {
auto b = str.cbegin();
auto end = str.cend();
for(std::string::const_iterator it = b; it != end; ++it) {
if(*it == '\n') {
std::size_t w = std::distance(b, it);
if(w > width_) width_ = w;
svs.emplace_back(b, it);
b = it + 1;
}
}
std::size_t w = std::distance(b, str.cend());
if(w > width_) width_ = w;
svs.emplace_back(b, str.cend());
}

// some convenience functions
std::size_t width() const { return width_; }
std::size_t height() const { return svs.size(); }

// An operator to get a specific line to render from this Letter.
// It returns a string with the proper width (the max width of all the
// lines for this Letter). If `line` is out of bounds, it returns a
// blank line.
std::string operator()(std::size_t line) const {
if(line >= svs.size()) return std::string(width_, ' ');
return svs[line] + std::string(width_ - svs[line].size(), ' ');
}

// If you just want to print one letter:
friend std::ostream& operator<<(std::ostream& os, const Letter& l) {
for(auto& sv : l.svs) os << sv << '\n';
return os;
}

private:
std::vector<std::string> svs;
std::size_t width_ = 0;
};

// A user defined literal operator to simplify creating the map:
Letter operator "" _L(const char* str, std::size_t len) {
return std::string(str, str + len);
}

//---------------------------------------------------------------
std::map<char, Letter> letters = {
{' ', " "_L },
{'a',
R"( _
/ \
/ _ \
/ ___ \
/__/ \__\
)"_L},
{'b',
R"( ____
| __ )
| _ \
| |_) |
|____/
)"_L}
}; // note that each Letter ends with _L to trigger the user defined literal

// A printing function that can either be called with a specified height,
// or be made to find the appropriate height for this string.
void print(std::string_view txt, std::size_t height = 0) {
if(height == 0) {
for(char ch : txt) {
try {
auto w = letters.at(ch).height();
if(w > height) height = w;
}
catch(...) {} // don't mind non-existing letters
}
}
for(std::size_t i = 0; i < height; ++i) {
for(char ch : txt) {
const Letter& l = letters.at(ch);
std::cout << l(i);
}
std::cout << '\n';
}
}

int main() {
print("abab baba");
}

关于c++ - C++换行符中的ascii艺术生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69124538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com