c++模板實(shí)現(xiàn)詞表解析

經(jīng)過簡化的需求如下:

請(qǐng)?jiān)O(shè)計(jì)并實(shí)現(xiàn)一個(gè)通用的詞表解析讀取工具類(一個(gè)或者幾個(gè)class/struct組成),
解析并讀取如下形式的詞表:
<col1>\t<col2>\t...\t<coln>
每一行都是一條記錄奕坟,每一列可能的類型包括
int
float
char *
uint32_t
uint64_t
其他用戶自定義類型
每一列的數(shù)據(jù)中均不包含\t字符祥款,每一行以\n結(jié)尾。
1對(duì)于非用戶自定義類型月杉,封裝解析行為刃跛;用戶自定義類型,調(diào)用用戶給出的parse函數(shù)(從string翻譯成用戶struct)完成
2 用戶能通過某些形式苛萎,定制這個(gè)詞表的結(jié)構(gòu)桨昙,指明每一列的類型是什么
3 用戶能逐行讀取這個(gè)詞表的信息,即按序讀取每一行腌歉,然后能解析出這一行中的每一列內(nèi)容
4 API設(shè)計(jì)友好蛙酪,做到自解釋
5 代碼的可讀性和可維護(hù)性好

程序一共由5個(gè)文件組成,3個(gè)頭文件翘盖,2個(gè)實(shí)現(xiàn)文件,如下:

1 build_in.h

#ifndef  __BUILD_IN_H_
#define  __BUILD_IN_H_
#include <stdint.h>
namespace parse
{
    //int type
    int parse(const char* str, int* result);
    //char* type
    int parse(const char* str, char* result);
    int parse(const char* str, float* result);
    int parse(const char* str, uint32_t* result);
    int parse(const char* str, uint64_t* result);
}

2 build_in.cpp

#include <stdio.h>
#include <stdint.h>
#include "build_in.h"
namespace parse
{
    //int type
    int parse(const char* str, int* result)
    {
        int ret = 0;
    
        if (NULL != str)
        {
            if (1 != sscanf(str, "%d", result))
            {
                ret = 1; 
            }
        }
    
        else
        {
            ret = 1;
        }
    
        return ret;
    }
    
    //char* type
    int parse(const char* str, char* result)
    {
        int ret = 0;
    
        if (NULL != str && NULL != result)
        {
            const char* start_str = str;
            char* result_str = result;
    
            while ('\t' != *start_str 
                    && '\n' != *start_str 
                    && '\0' != *start_str
                    && ',' != *start_str)
            {
                *result_str++ = *start_str++;
            }
    
            *result_str = '\0';
        }
    
        else
        {
            ret = 1;
        }
    
        return ret; 
    }
}

3 parser.h

#ifndef  __PARSER_H_
#define  __PARSER_H_
#include "build_in.h"
#include "user.h"
#include <stdio.h>
#include <iostream>
namespace parse
{
    class Parser
    {
        static const int MAX_COLUMN = 1024;
    
        const char* column_[MAX_COLUMN];
        int column_num_;
        
        public:
        Parser()
        {
            memset(this, '\0', sizeof(*this));
        }

        int parse_line(const char* line, const int column_num) 
        {
            int ret = 0;
            column_num_ = column_num;

            do
            {
                if (NULL == line || column_num <= 0)
                {
                    ret = 1;
                    break;
                }
                int index = 0;
                for (int i = 0; '\n' != line[i]; i++)
                {
                    if (0 == i)
                    {
                        column_[index++] = &line[i];
                        //printf("%s\n", column_[0]);
                    }
                    else if ('\t' == line[i])
                    {
                        column_[index++] = &line[i+1];
                        //printf("%s\n", column_[index-1]);
                    }
                }
                if (column_num != index)
                {
                    ret = 1;
                    break;
                }
            } while(0);
            return ret;
        };
    
        template<class T>
        int get_column(const int index, T* result)
        {
            int ret = 0;
    
            if (index < column_num_)
            {
                ret = parse(column_[index], result);
            }
    
            else
            {
                ret = 1;
            }
    
            return ret;
        }    
    };
}

4 user.h

#ifndef  __USER_H_
#define  __USER_H_
#include <stdio.h>
namespace parse
{
    //example
    typedef struct MyStruct
    {
        int a;
        int b;
        int c;
    }MyStruct;
    
    int parse(const char* str, MyStruct* result);
}

5 user.cpp

#include "user.h"
namespace parse
{
    //對(duì)于用戶類型桂塞,請(qǐng)自定義解析實(shí)現(xiàn)
    int parse(const char* str, MyStruct* result)
    {
        sscanf(str, "%d %d %d", &result->a, &result->b, &result->c);
    
        return 0;
    } 
}

核心的代碼在parser.h中,主要通過模板和函數(shù)重載來完成一種編譯期的多態(tài)行為馍驯。
調(diào)用實(shí)例如下:

#include "parser.h"
#include <stdio.h>
#include <iostream>
using namespace parse;

char* test1 = "abcdef\t123\t3.9\t456\tyiyg\n";
char* test2 = "abcdef\t3:4,5,6\t3.9\t456\tyiyg\t4:1,2,3,4\n";
char* test3 = "abcdef\t123\t3.9\t456\tyiyg\t22 33 44\n";

void test();

void test()
{
    Parser test;
    test.parse_line(test1, 5);
    int x;
    test.get_column(3, &x);
    char* y = new char[20];
    test.get_column(4, y);
    float z;
    test.get_column(2, &z);
    printf("%d, %s, %f\n", x, y, z);
    test.parse_line(test3, 6);
    
    MyStruct my_struct;
    test.get_column(5, &my_struct);
    printf("%d %d %d\n", my_struct.a, my_struct.b, my_struct.c);
}

邏輯相對(duì)比較清晰阁危,就不過多解釋了。
(原文時(shí)間2014-2-20)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末汰瘫,一起剝皮案震驚了整個(gè)濱河市狂打,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌混弥,老刑警劉巖趴乡,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝗拿,居然都是意外死亡晾捏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門哀托,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粟瞬,“玉大人,你說我怎么就攤上這事萤捆∪蛊罚” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵俗或,是天一觀的道長市怎。 經(jīng)常有香客問我,道長辛慰,這世上最難降的妖魔是什么区匠? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮帅腌,結(jié)果婚禮上驰弄,老公的妹妹穿的比我還像新娘。我一直安慰自己速客,他們只是感情好戚篙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著溺职,像睡著了一般岔擂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浪耘,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天乱灵,我揣著相機(jī)與錄音,去河邊找鬼七冲。 笑死痛倚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澜躺。 我是一名探鬼主播蝉稳,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼苗踪!你這毒婦竟也來了颠区?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤通铲,失蹤者是張志新(化名)和其女友劉穎毕莱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颅夺,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朋截,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吧黄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片部服。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拗慨,靈堂內(nèi)的尸體忽然破棺而出廓八,到底是詐尸還是另有隱情奉芦,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布剧蹂,位于F島的核電站声功,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宠叼。R本人自食惡果不足惜先巴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望冒冬。 院中可真熱鬧伸蚯,春花似錦、人聲如沸简烤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乐埠。三九已至抗斤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丈咐,已是汗流浹背瑞眼。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棵逊,地道東北人伤疙。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像辆影,于是被迫代替她去往敵國和親徒像。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容