将C++代码转换为HTML

【网通】点击此处下载源程序及EXE文件            【电信、网通】点击此处下载源程序与EXE文件

【下载说明】

1、单击上面这个地址,打开下载页面。

2、点普通下载--等待30秒--点“下载”按钮--保存

点击此处查看原文


介绍

Cpphtml 是将你的C++代码转换为HTML页面的类库.如果你有一个C++文件, 比如是myprogram.cpp, 然后你想将它放到自己的网站上, 那么你就可以使用Cpphtml来完成这个工作,Cpphtml会将其转换为HTML并附带所有的注释、关键字和预处理的高亮显示。Cpphtml将会将所有的输出指向cout,因此如果你想要创建一个HTML文件的话,你可以重定向至一个文件就可以了。

C:\>cpphtml myprogram.cpp >myprogram.htm

Cpphtml会将所有的Tab键变成4个空格。如果你想要Tab的大小是8个空格的话,你可以在命令行上指定Tab的大小。

C:\>cpphtml myprogram.cpp 8 >myprogram.htm

HTML代码包含一个<style>元素,它会包含注释、关键字和预处理器的风格。因此,如果你想要改变关键字的颜色的话,没有必要使用搜索-替换的操作。比如,如果你想要所有的关键字是粗体,只需要改变.keyword风格就可以了,如下:

.keyword{color:rgb(0,0,255);font-weight:bold}

很简单。

我测试过DinkumwareSTL文件、Cpphtml的源文件和一个较大的Microsoft CPP文件。结果很不错。Cpphtml使用Borland c++ 5.5命令行来编译的:bcc32 cpphtml.cpp

浏览代码

#include<fstream>
#include<string>
#include<ctype.h>

如果没有指定Tab大小的话,Cpphtml默认是用4个空格替换所有的Tab键的。如果你想要默认的Tab大小是8个空格的话,改变_TABSIZE宏为8即可。

#define _TABSIZE    4
using namespace std;
 
int tabsize = _TABSIZE;

Token是一个代表代码块的类。一个Token会有注释、预处理命令、关键字和代码。不包含注释、预处理命令和关键字的部分都叫做代码。注意他们不是设置或获取方法:因为operator>> operator<< Token类的友类,这些我们都不需要.

class token {
public:
    token() : _what(code) {}
protected:
    enum type {code, comment, pp, keyword};
    string _str;
    type _what;
    friend istream& operator>>(istream&, token&);
    friend ostream& operator<<(ostream&, const token&);
};

函数iskeyword() 返回true 如果字符串 s是一个C++关键字的话如果不是,返回false。可能你不认识其中的一些关键字,比如and。那些不需要所有ASCII字符的编程者可能会用到。但是,我还没见过有这样关键字的代码。

bool iskeyword(const string& s)
{
    static const char* keywords[] = {
        "and",
        "and_eq",
        "asm",
        "auto",
        "bitand",
        "bitor",
        "bool",
        "break",
        "case",
        "catch",
        "char",
        "class",
        "compl",
        "const",
        "const_cast",
        "continue",
        "default",
        "delete",
        "do",
        "double",
        "dynamic_cast",
        "else",
        "enum",
        "explicit",
        "export",
        "extern",
        "false",
        "float",
        "for",
        "friend",
        "goto",
        "if",
        "inline",
        "int",
        "long",
        "mutable",
        "namespace",
        "new",
        "not",
        "not_eq",
        "operator",
        "or",
        "or_eq",
        "private",
        "protected",
        "public",
        "register",
        "reinterpret_cast",
        "return",
        "short",
        "signed",
        "sizeof",
        "static",
        "static_cast",
        "struct",
        "switch",
        "template",
        "this",
        "throw",
        "true",
        "try",
        "typedef",
        "typeid",
        "typename",
        "union",
        "unsigned",
        "using",
        "virtual",
        "void",
        "volatile",
        "wchar_t",
        "while",
        "xor",
        "xor_eq"
    };
 
    for (int i = 0; i < sizeof(keywords) / sizeof(char*); i++)
        if (string(keywords[i]) == s)
            return true;
 
    return false;
}

函数containspp() 返回true 如果字符串 s 包含预处理命令.一个Token类型pp 可以包含一个形如 "#...define"的预处理命令,因此, 我们必须找到它的子字符串。.

bool containspp(const string& s)
{
    static const char* pptokens[] = {
        "define",
        "elif",
        "else",
        "endif",
        "error",
        "if",
        "ifdef",
        "ifndef",
        "include",
        "line",
        "pragma",
        "undef"
    };
 
    for (int i = 0; i < sizeof(pptokens) / sizeof(char*); i++)
        if (s.find(pptokens[i]) != string::npos)
            return true;
 
    return false;
}

Operator>> 从输入流中获取Token.它识别 "//" "/*...*/"注释, 形如"#...define"的预处理命令,和关键字.为了避免字符串中的关键字被高亮,也识别常量字符串。

istream& operator>>(istream& is, token& t)
{
    t._str = "", t._what = token::code;
    int c = is.get();
    switch (c) {
        case '/':
            c = is.get();
            if (c == '*') {
                t._str = "/*";
                t._what = token::comment;
                while (1) {
                    c = is.get();
                    if (c == EOF)
                        return is.unget(), is.clear(), is;
                    if (c == '/') {
                        if (t._str.length() > 2 &&
                            t._str[t._str.length() - 1] == '*') {
                            return t._str += '/', is;
                        }
                    }
                    t._str += (char)c;
                }
            } else if (c == '/') {
                t._str = "//";
                t._what = token::comment;
                c = is.get();
                while (c != '\n' && c != EOF) {
                    t._str += (char)c;
                    c = is.get();
                }
                if (c == '\n') {
                    t._str += '\n';
                }
                return is;
            }
            t._str = '/';
            return is.unget(), is.clear(), is;
        case '#':
            t._str = '#';
            c = is.get();
            while (strchr(" \r\n\t", c)) {
                t._str += (char)c;
                c = is.get();
            }
            if (c == EOF)
                return is.unget(), is.clear(), is;
            while (strchr("abcdefghijklmnopqrstuvwxyz", c)) {
                t._str += (char)c;
                c = is.get();
            }
            is.unget(), is.clear();
            if (containspp(t._str))
                t._what = token::pp;
            return is;
        case '\'':
        case '"': {
            char q = (char)c;
            t._str = q;
            while (1) {
                c = is.get();
                if (c == EOF)
                    return is.unget(), is.clear(), is;
                if (c == q) {
                    if (t._str.length() >= 2) {
                        if (!(t._str[t._str.length() - 1] == '\\' &&
                            t._str[t._str.length() - 2] != '\\'))
                            return t._str += q, is;
                    } else {
                        return t._str += q, is;
                    }
                }
                t._str += (char)c;                
            }
        }
        case 'a':
        case 'b':
        case 'c':
        case 'd':
        case 'e':
        case 'f':
        case 'g':
        case 'i':
        case 'l':
        case 'm':
        case 'n':
        case 'o':
        case 'p':
        case 'r':
        case 's':
        case 't':
        case 'u':
        case 'v':
        case 'w':
        case 'x':
            t._str += (char)c;
            c = is.get();
            while (isalpha(c) || isdigit(c) || c == '_') {
                t._str += (char)c;
                c = is.get();
            }
            is.unget(), is.clear();
            if (iskeyword(t._str))
                t._what = token::keyword;
            return is;
        case EOF:
            return is;
        default:
            t._str += (char)c;
            c = is.get();
            while (c != '/' && c != '#' && !strchr("abcdefgilmnoprstuvwx", c) &&
                c != '\'' && c != '"' && c != EOF) {
                t._str += (char)c;
                c = is.get();
            }
            is.unget(), is.clear();
            return is;
    }
}

函数html() 替换字符串s里的字符 '&', '<', '>' '"',使用它们在HTML里面同等的字符,并且使用空格来替换Tab

string html(const string& s)
{
    string s1;
    string::size_type i;
    for (i = 0; i < s.length(); i++) {
        switch (s[i]) {
            case '&':
                s1 += "&";
                break;
            case '<':
                s1 += "<";
                break;
            case '>':
                s1 += ">";
                break;
            case '"':
                s1 += """;
                break;
            case '\t':
                s1.append(tabsize, ' ');
                break;
            default:
                s1 += s[i];
        }
    }
    return s1;
}

Operator<< 将一个Token输出至输出流.代码也很直接.

 Collapse | Copy Code

ostream& operator<<(ostream& os, const token& t)
{
    if (t._what == token::code)
        cout << html(t._str);
    else if (t._what == token::comment)
        cout << "<span class=comment>" << html(t._str) << "</span>";
    else if (t._what == token::keyword)
        cout << "<span class=keyword>" << html(t._str) << "</span>";
    else if (t._what == token::pp)
        cout << "<span class=pp>" << html(t._str) << "</span>";
    else
        cout << html(t._str);
    return os;
}

这是Cpphtml的进入点。所有的代码将会被包装在<pre>元素里面。通过重载operator>> operator<<,while会很简短.所有的输出都被送到cout.

int main(int argc, char **argv)
{
    if (argc != 2 && argc != 3) {
        cout << "usage: cpphtml file [tab size]" << endl;
        return 0;
    }
    ifstream is(argv[1]);
    if (!is.good()) {
        cerr << "bad input file" << endl;
        return -1;
    }
    if (argc == 3) {
        tabsize = atoi(argv[2]);
        if (tabsize <= 0)
            tabsize = _TABSIZE;
    }
    cout << "<html>" << endl 
      << "<head>" << endl 
      << "<style>" << endl;
    cout << ".keyword{color:rgb(0,0,255);}" << endl;
    cout << ".comment{color:rgb(0,128,0);}" << endl;
    cout << ".pp{color:rgb(0,0,255);}" << endl;
    cout << "</style>" << endl << "<body>" << endl;
    cout << "<pre style=\"font-family:courier;font-size:10pt\">";
    token t;
    while (is >> t) {
        cout << t;
    }
    cout << "</pre>" << "</body>" 
         << endl << "</html>" << endl;
    return 0;
}

 

【更多阅读】

  1. [译]使用OpenXML更新Word文档中的表格
  2. [原]ManageStartUpApps:C#操作注册表来读取和修改开机启动项
  3. [原]C#读取CSDN博客的文章名称及地址
  4. [译]使用OpenXML更新Word文档中的表格
  5. [原]WMICodeCreator:C#产生WMI代码的工具
  6. [原]使用Excel的VBA来读取和修改bmp位图像素数据
  7. [原]Baidu:C#利用百度来搜索网页、图片、视频等等
  8. [原]Cls_Ini.cls:VB写的操作ini配置文件的类
  9. [原]QQHelper:QQ大家来找茬 辅助工具 外挂
  10. [译]使用WM_COPYDATA消息在C++和C#程序之间互传数据

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值