最近在编写一些文档时,我需要将许多异步串行波形转换为ASCII图形字符。我决定写一个程序来帮我画,而不是用手画。我对代码回顾感兴趣,尤其是如果有更聪明/更短的方法来编写类的话。
#include <iostream>
#include <vector>
#include <string>
#include <bitset>
class waveform
{
public:
waveform(std::string &s) : data_(s) {}
std::vector<bool> to_bits() const
{
std::vector<bool> bits;
bits.reserve(data_.size() * 10);
for (auto &ch : data_) {
bits.push_back(0); // start bit
for (int mask=1u; mask != 0x100; mask <<= 1) {
bits.push_back(ch & mask);
}
bits.push_back(1); // stop bit
}
return bits;
}
friend std::ostream& operator<<(std::ostream& out, const waveform& w) {
auto bits = w.to_bits();
bool last = 1;
for (const auto &b : bits) {
out << (b ? "+---" : (last ? "+ " : " "));
last = b;
}
out << '\n';
last = 1;
for (const auto &b : bits) {
out << (b != last ? "| " : " ");
last = b;
}
out << '\n';
last = 1;
for (const auto &b : bits) {
out << (b ? (last ? " " : "+ ") : "+---");
last = b;
}
out << '\n';
int special = 0x201;
for (const auto &b : bits) {
if (special & 1) {
out << (b ? " P " : " S ");
} else {
out << (b ? " 1 " : " 0 ");
}
special >>= 1;
if (special == 0)
special = 0x201;
}
out << '\n';
return out;
}
private:
std::string data_;
};int main()
{
std::string msg{"ST"};
std::cout << waveform(msg) << std::endl;
}+ +---+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---
| | | | | | | | | | | | | | | |
+---+ +---+---+ +---+ +---+ +---+---+---+ +---+ +---+ +---+
S 1 1 0 0 1 0 1 0 P S 0 0 1 0 1 0 1 0 P 注意,在这个图中,S代表一个开始位,P代表一个停止位,而8个数据位首先被发送到最不重要的位。
发布于 2015-04-28 03:46:41
OOP的设计似乎对你没有多大帮助。感觉就像你只需要一个函数就能得到基本相同的效果。另一方面,operator<<方法基本上是一个状态机,它看起来比需要的要麻烦一些。这里有复制和粘贴代码,各地都有ASCII的一些艺术,还有一台使用神奇数字0x201的迷你图灵机。
假设to_bits()助手函数对您不重要(我假设它并不那么重要,因为您编写了#include <bitset>然后改变了主意),您可以通过定义一个过滤输出流来做得更好。下面是我试图实现这样一件事的尝试:
#include <climits>
#include <iostream>
#include <sstream>
#include <streambuf>
#include <string>
class waveform_ostream : public std::streambuf
{
public:
explicit waveform_ostream(std::ostream &sink) : sink(sink) {}
protected:
// Accept a byte of data
virtual std::streambuf::int_type overflow(std::streambuf::int_type c) {
output_bit(0, 'S'); // Start bit
for (int i = 0; i < CHAR_BIT; ++i) {
output_bit((c >> i) & 1); // Data bits, LSB first
}
output_bit(1, 'P'); // Stop bit
return c;
}
// Flush
int sync() {
for (int row = 0; row < 4; ++row) {
std::string s = lines[row]->str();
sink << s << '\n';
lines[row]->str("");
}
sink << std::flush;
return 0; // success
}
private:
bool state = 1;
std::ostream &sink;
std::stringstream level[2], risefall, captions;
std::stringstream *const lines[4] = {
&level[1],
&risefall,
&level[0],
&captions
};
void output_bit(bool b, char caption='\0') {
level[!b] << ((b == state) ? " " : "+ ");
risefall << ((b == state) ? " " : "| ");
level[ b] << "+---";
captions << " " << (char)(caption ? caption : b ? '1' : '0') << ' ';
state = b;
}
};
int main()
{
waveform_ostream wout(std::cout);
std::ostream out(&wout);
out << std::string("ST") << std::flush;
}发布于 2015-04-28 14:38:23
我不太喜欢原来的,所以我改变了一些东西,并制作了这个新版本。它允许可变数量的数据位和停止位,并且结构更好。每一行分别生成,图像使用两位查找表进行选择.
#ifndef WAVEFORM_H
#define WAVEFORM_H
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
namespace WAVE {
class Waveform
{
public:
Waveform(std::string &s, int bits=8, int stopbits=1);
std::size_t bits_per_char() const { return 1 + bits_ + stop_; }
std::vector<bool> to_bits() const;
void graphics_line(std::ostream& out, const std::vector<bool>& bits, int linenum) const;
void bitlabel_line(std::ostream& out, const std::vector<bool>& bits) const;
friend std::ostream& operator<<(std::ostream& out, const Waveform& w) {
auto bits = w.to_bits();
for (int i=0; i < 3; ++i)
w.graphics_line(out, bits, i);
w.bitlabel_line(out, bits);
for (const auto &ch: w.data_) {
out
<< std::setw(2*w.bits_per_char()) << "0x" << std::hex
<< static_cast<unsigned>(ch & 0xff)
<< std::setw(2*w.bits_per_char()-2) << ' ';
}
return out;
}
private:
std::string data_;
int bits_;
int stop_;
};
}
#endif //WAVEFORM_H#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include "Waveform.h"
namespace WAVE {
Waveform::Waveform(std::string &s, int bits, int stopbits)
: data_(s), bits_(bits), stop_(stopbits)
{
}
std::vector<bool> Waveform::to_bits() const
{
std::vector<bool> bits;
bits.reserve(data_.size() * bits_per_char());
for (auto &ch : data_) {
bits.push_back(0); // start bit
for (int i=bits_, c=ch; i; --i) {
bits.push_back(c & 1);
c >>= 1;
}
for (int i=stop_; i; --i) {
bits.push_back(1); // stop bit
}
}
return bits;
}
void Waveform::graphics_line(std::ostream& out, const std::vector<bool>& bits, int linenum) const
{
static const char* graphic[3][4]{
// 00 01 10 11
{" ", "+---", "+ ", "+---"},
{" ", "| ", "| ", " "},
{"+---", "+ ", "+---", " "}
};
int last = 2; // assume previous bit was 1
for (const auto &b : bits) {
last |= b;
out << graphic[linenum][last];
last = (last << 1) & 0x3;
}
out << '\n';
}
void Waveform::bitlabel_line(std::ostream& out, const std::vector<bool>& bits) const
{
enum states { START, DATA, STOP } state = START;
int bitcount = bits_;
for (unsigned i=0; i < bits.size(); ++i) {
switch (state) {
case START:
out << (bits[i] ? " SE " : " S ");
state = DATA;
break;
case DATA:
out << (bits[i] ? " 1 " : " 0 ");
if (--bitcount == 0) {
bitcount = stop_;
state = STOP;
}
break;
case STOP:
out << (bits[i] ? " P " : " EP ");
if (--bitcount == 0) {
bitcount = bits_;
state = START;
}
break;
}
}
out << '\n';
}
}#include <iostream>
#include "Waveform.h"
using namespace std;
int main()
{
string msg{"ST"};
WAVE::Waveform wave = WAVE::Waveform(msg);
WAVE::Waveform wave2{wave};
cout << wave << endl;
cout << WAVE::Waveform(msg,7,1) << endl;
cout << WAVE::Waveform(msg,7,2) << endl;
auto bits = wave2.to_bits();
for (bool b : bits)
cout << b;
cout << endl;
}+ +---+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---
| | | | | | | | | | | | | | | |
+---+ +---+---+ +---+ +---+ +---+---+---+ +---+ +---+ +---+
S 1 1 0 0 1 0 1 0 P S 0 0 1 0 1 0 1 0 P
0x53 0x54
+ +---+---+ +---+ +---+---+ +---+ +---+ +---+---
| | | | | | | | | | | |
+---+ +---+---+ +---+ +---+---+---+ +---+ +---+
S 1 1 0 0 1 0 1 P S 0 0 1 0 1 0 1 P
0x53 0x54
+ +---+---+ +---+ +---+---+---+ +---+ +---+ +---+---+---
| | | | | | | | | | | |
+---+ +---+---+ +---+ +---+---+---+ +---+ +---+
S 1 1 0 0 1 0 1 P P S 0 0 1 0 1 0 1 P P
0x53 0x54
01100101010001010101https://codereview.stackexchange.com/questions/88148
复制相似问题