1. 程式人生 > >[HTTP]_[C/C++]_[HTML特殊字元轉義成正常字元]

[HTTP]_[C/C++]_[HTML特殊字元轉義成正常字元]

場景:

1.在沒有HTML庫時(誰有好的html庫介紹下,C/C++的?tinyXML?),以SAX方式解析HTML時,會讀入特殊字元,這時候需要轉義成正常字元才能使用。

2.耗時,4-6小時(被打擾)。

3.replace雖然挺好,但是會迴圈整個字串執行替換,效率應該沒有一次過替換高.

  #include <algorithm>
  void replace( iterator start, iterator end, const TYPE& old_value, const TYPE& new_value );

4.所有轉義字元的網址:


檔案1:test_htmlescape.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <assert.h>

using namespace std;

int IsLittleEndian()
{
    int x = 1;
    if (*(char*) &x == 1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void HtmEscapeEntityCodeToUnicode(const char* entity_code,char* html_char)
{
    int decimal_value = atoi(entity_code);
    char* uchari = (char*)&decimal_value;
    if(IsLittleEndian())
    {
        html_char[0] = uchari[0] & 0xFF;
        html_char[1] = uchari[1] & 0xFF;
    }else
    {
        html_char[0] = uchari[1] & 0xFF;
        html_char[1] = uchari[0] & 0xFF;
    }
}

void OneUnicode2UTF8(const char* unicode_char,size_t unicode_char_length,
            char* utf_char)
{
    //unicode: 0x192->110010010 ,utf8:0xC692->1100011010010010
    int value = 0;
    memcpy(&value,unicode_char,unicode_char_length);
    
    if (value >= 0x0000 && value <= 0x007F)  
    {  
        utf_char[0] = unicode_char[0];
    }  
    else if (value >= 0x0080 && value <= 0x07FF)  
    {  
        utf_char[0] = ((value >> 6) | 0xC0);
        utf_char[1] = ((value & 0x3F) | 0x80);
    }  
    else if (value >= 0x0800 && value <= 0xFFFF)  
    {  
        utf_char[0] = ((value >> 12) | 0xE0);
        utf_char[1] = ((value >> 6 & 0x3F) | 0x80);
        utf_char[2] = ((value & 0x3F) | 0x80);
    }
    else if (value >= 0x10000 && value <= 0x10FFFF)  
    {  
        utf_char[0] = (value >> 18 | 0xF0);
        utf_char[1] = ((value >> 12 & 0x3F) | 0x80);
        utf_char[2] = ((value >> 6 & 0x3F) | 0x80);
        utf_char[3] = ((value & 0x3F) | 0x80);
    }
    else
    {
        cerr << "value too big." << endl; 
        assert(0);
    }
}

static const char* kEntityNameToEntityCodeMap[] = 
{
    "oelig","339","amp","38","rArr","8658","fnof","402"
};
//1.這裡可以優化的餘地很大.
const char* HtmEscapeEntityNameToEntityCode(const char* entity_name)
{
    static size_t length = sizeof(kEntityNameToEntityCodeMap)/sizeof(char*);
    for(size_t i = 0; i < length; i+=2)
    {
        if(!strcmp(entity_name,kEntityNameToEntityCodeMap[i]))
        {
            return kEntityNameToEntityCodeMap[i+1];
        }
    }
    return NULL;
}

string UnescapeUTFHTMLContent(const char* str)
{
    string temp;
    
    char* pos_amp = NULL;
    char* pos_semicolon = (char*)str;
    const char* start_amp = str;

    int entity_length = 0;
    char entity_code[5];
    const int kMaxEntityLength = 4;

    char entity_name[20];
    const int kMaxEntityNameLength = 18;
    
    char unicode[3];
    char utf8[4];

    while(true)
    {
        if(!start_amp || !(*start_amp))
        {
            break;
        }
        pos_amp = strchr(start_amp,'&');
        if(!pos_amp)
        {
            temp.append(start_amp);
            break;
        }
        int pos_no = pos_amp - pos_semicolon;
        if(pos_no > 0)
        {
            temp.append(start_amp,pos_no);
            start_amp = pos_amp;
        }

        char* pos_amp1 = pos_amp+1;
        if(!pos_amp1 || !(*pos_amp1))
        {
            string t2(start_amp);
            temp.append(start_amp);
            break;
        }

        if(isalpha(*pos_amp1))
        {
            pos_semicolon = strchr(pos_amp1,';');
            if(pos_semicolon)
            {
                //呼叫 HtmEscapeEntityNameToEntityCode
                memset(entity_name,0,sizeof(entity_name));
                entity_length = ((pos_semicolon - pos_amp1) > 
                    kMaxEntityNameLength)?kMaxEntityNameLength:
                    (pos_semicolon - pos_amp1);
                strncpy(entity_name,pos_amp1,entity_length);
                const char* entity_code_c = 
                    HtmEscapeEntityNameToEntityCode(entity_name);
                if(entity_code_c)
                {
                    memset(unicode,0,sizeof(unicode));
                    memset(utf8,0,sizeof(utf8));
                    HtmEscapeEntityCodeToUnicode(entity_code_c,unicode);
                    OneUnicode2UTF8(unicode,2,utf8);
                    temp.append(utf8);
                }else
                {
                    temp.append(entity_name);
                }
                //1.entity_name轉換為entity_code之後再轉換為utf8字元.
                start_amp = pos_semicolon + 1;
                pos_semicolon+=1;
            }else
            {
                start_amp = pos_amp1;
            }
        }else if(*pos_amp1 =='#')
        {
            char* pos_digit = (pos_amp1+1);
            if(!pos_digit)
            {
                break;
            }
            
            if(isdigit(*pos_digit))
            {
                //1.需要判斷數值小於10000.
                pos_semicolon = strchr(start_amp,';');
                if(pos_semicolon)
                {
                    memset(entity_code,0,sizeof(entity_code));
                    entity_length = ((pos_semicolon - pos_digit) > 
                        kMaxEntityLength)?kMaxEntityLength:
                        (pos_semicolon - pos_digit);
                    strncpy(entity_code,pos_digit,entity_length);
                    memset(unicode,0,sizeof(unicode));
                    memset(utf8,0,sizeof(utf8));
                    HtmEscapeEntityCodeToUnicode(entity_code,unicode);
                    OneUnicode2UTF8(unicode,2,utf8);
                    temp.append(utf8);

                    start_amp = pos_semicolon + 1;
                    pos_semicolon+=1;
                }else
                {
                    start_amp = pos_digit;
                }
            }
        }else
        {
            string sa(start_amp,pos_amp1 - start_amp);
            temp.append(sa);
            start_amp = pos_amp1;
        }
    }
    return temp;
}

int main(int argc, char *argv[])
{
    printf("Hello, world\n");
    
    string str;
    const char *html_str = "&#918;abcd&#917;hello&#169;<a>&#8658;&rArr;"
    "&fnof;&#8230;</a>"
    "asfas&#8225;dfe&#933;&Psi;&#937;<img>n&#8595;n&sdot;n&#969;mmm</img>1jh";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "str: " << str << endl;

    html_str = "<td>&amp;#8736;</td>";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "str: " << str << endl;

    html_str = "<td>&amp;#8736;</td>;;#8736;";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "str: " << str << endl;

    html_str = "<td>&amp;#8736;</td>;&amp;";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "str: " << str << endl;

    html_str = "<td>&amp;#8736;</td>;&amp";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "str: " << str << endl;

    html_str = "<td>&amp;#8736;</td>;&";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "str1: " << str << endl;

    html_str = "ab";
    str = UnescapeUTFHTMLContent(html_str);
    cout << "ab: " << str << endl;
    return 0;
}


str: ΖabcdΕhello©<a>⇒⇒ƒ…</a>asfas‡dfeΥPsiΩ<img>n↓nsdotnωmmm</img>1jh
str: <td>&#8736;</td>
str: <td>&#8736;</td>;;#8736;
str: <td>&#8736;</td>;&
str: <td>&#8736;</td>;amp
str1: <td>&#8736;</td>;&
ab: ab



相關推薦

[HTTP]_[C/C++]_[HTML特殊字元轉義正常字元]

場景: 1.在沒有HTML庫時(誰有好的html庫介紹下,C/C++的?tinyXML?),以SAX方式解析HTML時,會讀入特殊字元,這時候需要轉義成正常字元才能使用。 2.耗時,4-6小時(被打擾)。 3.replace雖然挺好,但是會迴圈整個字串執行替換,效率應該沒

jQuery中將特殊字元轉義html標籤和反轉

在專案中新增富文字編輯器時,發現了儲存的資料最終顯示時是以 這種方式顯示 我再去控制檯輸出顯示下資料發現是已經將字元轉義成特殊字元了 哈哈哈哈哈哈&lt;div&gt;啦啦啦啦啦&lt;/div&gt; 所以此資料放入div中時html不能解析為

將字串中的字元替換指定字元c

C 全部替換字串裡某個字元或者某個子串 /*將字串中某個字元全部替換為另一個字元*/  #include<stdio.h>  #include<stdlib.h>  #include<string.h>  intsubstitude(ch

html 實體編碼轉換字元

今天遇到件很噁心的事,某國外歌詞網站提供的歌詞在原始檔裡使用“&#數字;”格式的編碼表示abcd....原來小菜我實在才疏學淺不知此為何物,於是利用八零後特有的搜尋引擎控,搜之。片刻得解,此乃html實體編碼。平時我們見的&nbsp;是html的實體字元,其實在後面還對應一個實體編碼。編碼

C++Primer_Chap17_標準庫特殊設施_List03_正則表示式_筆記

  正則表示式(regular expression)是一種描述字元序列的方法,是一種及其強大的計算工具。C++正則表示式庫(RE庫)定義在標頭檔案regex中,包含多個元件: 正則表示式庫元件 regex 表示有一個正則

C++Primer_Chap17_標準庫特殊設施_List02_bitset型別_筆記

  定義在標頭檔案bitset中的bitset類使位運算的使用更為容器,並且能夠處理超過最長整型型別大小的位集合。 #include <bitset> 定義和初始化bitset   當我們定義一個bitset時,需要宣告它包含多少個二進位制位。 bit

C++Primer_Chap17_標準庫特殊設施_List01_tuple型別_筆記

  tuple是類似pair的模板。不同tuple型別的成員型別可以不同,但一個tuple可以有任一數量的成員。每個確定的tuple型別的成員數目是固定的。但一個tuple型別的成員數目可以與另一個tuple型別不同。   當我們希望將一些資料組合成單一物件,但又不

C語言_刪除字元函式

  編寫一個函式del().用於從給定字串中刪除一部分。傳輸三個引數,一個待刪除字串,一個刪除起始位置(從0開始),一個刪除長度. 分析:        已經知道陣列(sum),刪除位置(del),刪除長度(len)         char 字串的長度的結束會加上‘\0’

[C/C++標準庫]_[初級]_[使用正則表示式過濾Windows檔名中的非法字元]

場景 1.Windows和macOS的檔名有自己的命名規則, 特別是Windows的檔名限制了不允許使用的特殊字元. 在使用這些檔名新建檔案時會建立失敗. 說明 1.在前面的文章裡在Windo

[C/C++]_[字串處理]_[過濾出HTML標籤的屬性值]

typedef struct ElementAttribute ElementAttribute; struct ElementAttribute { const char* name; con

[C/C++]_[0基礎]_[static_cast,reinterpret_cast,dynimic_cast的使用場景和差別]

輸出 type class 可能 pen rgs make 在那 char 場景:1. C++的對象差別於C的原因是他們能夠有繼承關系, 方法有重載, 覆蓋關系等, 他們的對象內存數據結構因此也比較復雜.2. 非常多情況下我們須要一個父類來存儲子類的指針對象進行通用方法

C/C++使用libcurl庫發送http請求(get和post可以用於請求html信息,也可以請求xml和json等串)

網絡連接 get 編譯 eas views vs2015 return tar linux C++要實現http網絡連接,需要借助第三方庫,libcurl使用起來還是很方便的 環境:win32 + vs2015 如果要在Linux下使用,基本同理 1,下載

c基礎_筆記_1

python clu std printf 定義變量 blog include num port 定義變量 int i; 也可以 int i,num; 賦值,c必須先定義變量再賦值 num = 0; 循環for for(i=1; i<=0; i++) { prin

c語言_文件操作_FILE結構體小解釋

hold 輸出 def 系統 span fopen 大小 round typedef 參考文檔來自:https://www.cnblogs.com/haore147/p/3648395.html 我們通過fopen返回一個文件指針(指向FILE結構體的指針)來進行文件操作。

C++框架_之Qt的窗口部件系統的詳解-上

同時 窗體 包含 鼠標 對象模型 種類 動態分配內存 對話框 狀態 C++框架_之Qt的窗口部件系統的詳解-上 第一部分概述 第一次建立helloworld程序時,曾看到Qt Creator提供的默認基類只有QMainWindow、QWidget和QDialog三種。是的,

『Python CoolBook』C擴展庫_其六_C語言中調用Python代碼

callable 什麽 跟著 來講 cpp iat mst 轉化 gcc 一、C語言運行pyfun的PyObject對象 思路是在C語言中提供實參,傳給python函數: 獲取py函數對象(PyObject),函數參數(C類型) 獲取GIL(PyGILState_

『Python CoolBook』C擴展庫_其六_線程

正在 args adsi 控制 數組 代碼 and begin extend GIL操作 想讓C擴展代碼和Python解釋器中的其他進程一起正確的執行, 那麽你就需要去釋放並重新獲取全局解釋器鎖(GIL)。 在Python接口封裝中去釋放並重新獲取全局解釋器鎖(GIL)

程序清單2.1_first.c程序_C Primer Plus》P15

C Primer Plus// first.cpp : 定義控制臺應用程序的入口點。 // /* 時間:2018年05月29日 22:49:40 代碼:程序清單2.1_first.c程序_《C Primer Plus》P15 目的:進一步了解 printf()函數,定義變量與賦值 及

程序清單2.4_nogood.c_程序_C Primer Plus》P26

C Primer Plus// nogood.cpp : 定義控制臺應用程序的入口點。 // /* 時間:2018年05月31日 21:02:59 代碼:程序清單2.4_nogood.c_程序_《C Primer Plus》P26 目的:認識代碼的基本錯誤_花括號/聲明/註釋/分號 *

程序清單2.5_stillbad.c_程序_C Primer Plus》P27

C Primer Plus// stillbad.cpp : 定義控制臺應用程序的入口點。 // /* stillbad.c -- 修正了語法錯誤的程序 */ /* 時間:2018年05月31日 21:51:51 代碼:程序清單2.5_stillbad.c_程序_《C Primer Plus》