ACL_VSTRING --字符串操做的法寶

1、概述app

  當咱們在使用C++、JAVA、.NET等面嚮對象語言甚至象PHP等腳本程序編寫字符串處理程序,以爲字符串處理是如此的簡單,但當用C編寫字符串處理程序時,用得最多多是諸如:snprintf 、strchr、strcat等標準C函數,但若遇到字符串緩衝區須要動態變化時,就不得很少作一些工做來作內存從新分配的事情,嗯,好繁瑣的工做。而POSTFIX代碼裏有一個很是好用的字符串處理函數庫:基於VSTRING結構的字符串處理函數集合,ACL做者將該函數集移植至ACL工程中(從新命名爲ACL_VSTRING,沒辦法,C語言沒有象C++那樣的命名空間)並使該庫能夠運行在多個平臺上(UNIX、WIN32等),同時增長了一些經常使用的功能。本文就介紹一下ACL_VSTRING函數庫的使用。函數

 

2、經常使用函數接口.net

一、建立與釋放指針

/**
 * 動態分配一個 ACL_VSTRING 對象並指定內部緩衝區的初始化大小
 * @param len {size_t} 初始時緩衝區大小
 * @return {ACL_VSTRING*} 新分配的 ACL_VSTRING 對象
 */
ACL_API ACL_VSTRING *acl_vstring_alloc(size_t len);

/**
 * 釋放由 acl_vstring_alloc 動態分配的 ACL_VSTRING 對象
 * @param vp {ACL_VSTRING*}
 * @return {ACL_VSTRING*} 永遠爲 NULL,因此沒必要關心返回值
 */
ACL_API ACL_VSTRING *acl_vstring_free(ACL_VSTRING *vp);

 二、字符串拷貝及添加code

/**
 * 拷貝字符串
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} 源字符串
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_strcpy(ACL_VSTRING *vp, const char *src);

/**
 * 附加拷貝字符串
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} 源字符串
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_strcat(ACL_VSTRING *vp, const char *src);

/**
 * 向緩衝區按格式方式添加數據
 * @param vp {ACL_VSTRING*}
 * @param format {const char*} 格式化字符串
 * @param ... 變參序列
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_sprintf(ACL_VSTRING *vp, const char *format,...);

/**
 * 以附加方式向緩衝區按格式方式添加數據
 * @param vp {ACL_VSTRING*}
 * @param format {const char*} 格式化字符串
 * @param ... 變參序列
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_sprintf_append(ACL_VSTRING *vp, const char *format,...);

/**
 * 按規定格式添加數據
 * @param vp {ACL_VSTRING*}
 * @param format {const char*}
 * @param ap {va_list}
 * @return {ACL_VSTRING*} 與 vp 相同
 * @see acl_vstring_sprintf
 */
ACL_API ACL_VSTRING *acl_vstring_vsprintf(ACL_VSTRING *vp, const char *format, va_list ap);

/**
 * 按規定格式向尾部添加數據
 * @param vp {ACL_VSTRING*}
 * @param format {const char*}
 * @param ap {va_list}
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_vsprintf_append(ACL_VSTRING *vp, const char *format, va_list ap);

  其中,acl_vstring_strcpy 功能與 strcpy 類似,但 acl_vstring_strcpy 不會產生內存溢出問題,由於ACL_VSTRING內存是自動調整的;acl_vstring_strcat 與 strcat 功能類似,但效率卻要比 strcat 高,由於 strcat 須要先從字符串頭移到字符串尾後纔開始添加,而且還可能產生內存越界問題,而 acl_vstring_strcat 內部直接在 ACL_VSTRING 的字符串尾部添加(得益於ACL_VSTRING的內部結構的指針成員),因此效率更高,同時也不存在內存非法越界的問題;acl_vstring_sprintf 與 snprintf 功能相似;acl_vstring_sprintf_append 是對 acl_vstring_sprintf 函數功能的一種擴充;acl_vstring_vsprintf 與 vsnprintf 相似,acl_vstring_vsprintf_append 是對 acl_vstring_vsprintf 的功能擴展。orm

  除了以上專門針對字符串的一些拷貝、添加功能外,ACL_VSTRING還支持非字符串數據的拷貝、添加,接口以下:對象

/**
 * 拷貝內存區
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} 源數據地址
 * @param len {size_t} 源數據長度
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_memcpy(ACL_VSTRING *vp, const char *src, size_t len);

/**
 * 拷貝內存區
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} 源數據地址
 * @param len {size_t} 源數據長度
 * @return {ACL_VSTRING*} 與 vp 相同
 */
ACL_API ACL_VSTRING *acl_vstring_memcat(ACL_VSTRING *vp, const char *src, size_t len);
 

 三、字符串查找接口

/**
 * 查找某個字符
 * @param vp {ACL_VSTRING*}
 * @param ch {int} 要查找的字符
 * @return {char*} 目標字符所在位置的地址, 若是未查到則返回 NULL, 注:該返回地址是不能
 *  被單獨釋放的,由於其由 ACL_VSTRING 對象統一進行管理
 */
ACL_API char *acl_vstring_memchr(ACL_VSTRING *vp, int ch);

/**
 * 查找某個字符串,字符串大小寫敏感
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} 要查找的字符
 * @return {char*} 目標字符所在位置的地址, 若是未查到則返回 NULL, 注:該返回地址是不能
 *  被單獨釋放的,由於其由 ACL_VSTRING 對象統一進行管理
 */
ACL_API char *acl_vstring_strstr(ACL_VSTRING *vp, const char *needle);

/**
 * 查找某個字符串,忽略字符串大小寫
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} 要查找的字符
 * @return {char*} 目標字符所在位置的地址, 若是未查到則返回 NULL, 注:該返回地址是不能
 *  被單獨釋放的,由於其由 ACL_VSTRING 對象統一進行管理
 */
ACL_API char *acl_vstring_strcasestr(ACL_VSTRING *vp, const char *needle);

/**
 * 從後向前查找字符串,字符串大小寫敏感
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} 要查找的字符
 * @return {char*} 目標字符所在位置的地址, 若是未查到則返回 NULL, 注:該返回地址是不能
 *  被單獨釋放的,由於其由 ACL_VSTRING 對象統一進行管理
 */
ACL_API char *acl_vstring_rstrstr(ACL_VSTRING *vp, const char *needle);

/**
 * 從後向前查找字符串,字符串大小寫不敏感
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} 要查找的字符
 * @return {char*} 目標字符所在位置的地址, 若是未查到則返回 NULL, 注:該返回地址是不能
 *  被單獨釋放的,由於其由 ACL_VSTRING 對象統一進行管理
 */
ACL_API char *acl_vstring_rstrcasestr(ACL_VSTRING *vp, const char *needle);

   這些字符串查找函數要比標準C的查找函數功能更爲強大。內存

  此外,ACL_VSTRING還提供了一些方便使用的宏,以下:開發

四、經常使用宏

/**
 * 取得當前 ACL_VSTRING 數據存儲地址
 * @param vp {ACL_VSTRING*}
 * @return {char*}
 */
#define acl_vstring_str(vp)		((char *) (vp)->vbuf.data)

/**
 * 取得當前 ACL_VSTRING 的數據偏移指針位置
 * @param vp {ACL_VSTRING*}
 * @return {char*}
 */
#define acl_vstring_end(vp)		((char *) (vp)->vbuf.ptr)

/**
 * 取得當前 ACL_VSTRING 所存儲的數據的長度
 * @param vp {ACL_VSTRING*}
 * @return {int}
 */
#define ACL_VSTRING_LEN(vp)		(size_t) ((vp)->vbuf.ptr - (vp)->vbuf.data)

/**
 * 將 ACL_VSTRING 的數據偏移指針位置置 0
 * @param vp {ACL_VSTRING*}
 */
#define ACL_VSTRING_TERMINATE(vp)	{ if ((vp)->vbuf.cnt <= 0) \
					ACL_VSTRING_SPACE((vp),1); \
				 	 *(vp)->vbuf.ptr = 0; }

/**
 * 重置 ACL_VSTRING 內部緩衝區
 * @param vp {ACL_VSTRING*}
 */
#define ACL_VSTRING_RESET(vp)		{ (vp)->vbuf.ptr = (vp)->vbuf.data; \
					  (vp)->vbuf.cnt = (vp)->vbuf.len; }

/**
 * 添加一個字符至 ACL_VSTRING 緩衝區
 * @param vp {ACL_VSTRING*}
 * @param ch {int} 字符
 */
#define	ACL_VSTRING_ADDCH(vp, ch)	ACL_VBUF_PUT(&(vp)->vbuf, ch)

   固然,除了以上經常使用函數及宏外,還有一些其它的函數及宏,請參考 lib_acl/include/stdlib/acl_vstring.h。

3、舉例

#include "lib_acl.h"

static void end(void)
{
#ifdef ACL_MS_WINDOWS
	getchar();
#endif
}

#define	STR	acl_vstring_str

// 字符串查找,大小寫敏感

static void string_find(ACL_VSTRING *vp, const char *needle)
{
	char *ptr;

	ptr = acl_vstring_strstr(vp, needle);
	if (ptr)
		printf(">>>acl_vstring_strstr: find %s from %s, ptr: %s\r\n", needle, STR(vp), ptr);
	else
		printf(">>>acl_vstring_strstr: not find %s from %s\r\n", needle, STR(vp));
}

// 字符串查找,大小寫不敏感

static void string_case_find(ACL_VSTRING *vp, const char *needle)
{
	char *ptr;

	ptr = acl_vstring_strcasestr(vp, needle);
	if (ptr)
		printf(">>>acl_vstring_strcasestr: find %s from %s, ptr: %s\r\n", needle, STR(vp), ptr);
	else
		printf(">>>acl_vstring_strcasestr: not find %s from %s\r\n", needle, STR(vp));
}

// 從尾部向前查找字符串,大小寫敏感

static void string_rfind(ACL_VSTRING *vp, const char *needle)
{
	char *ptr;

	ptr = acl_vstring_rstrstr(vp, needle);
	if (ptr)
		printf(">>>acl_vstring_rstrstr: find %s from %s, ptr: %s\r\n", needle, STR(vp), ptr);
	else
		printf(">>>acl_vstring_rstrstr: not find %s from %s\r\n", needle, STR(vp));
}

// 從尾部向前查找字符串,大小寫不敏感

static void string_case_rfind(ACL_VSTRING *vp, const char *needle)
{
	char *ptr;

	ptr = acl_vstring_rstrcasestr(vp, needle);
	if (ptr)
		printf(">>>acl_vstring_rstrcasestr: find %s from %s, ptr: %s\r\n", needle, STR(vp), ptr);
	else
		printf(">>>acl_vstring_rstrcasestr: not find %s from %s\r\n", needle, STR(vp));
}

// 須要查找的字符串表

static char *needle_tab[] = {
	"h",
	"el",
	"o",
	"e",
	"l",
	"lo",
	"he",
	"He",
	"hello",
	"hel",
	"Hel",
	"helo",
	NULL
};

int main(int argc acl_unused, char *argv[] acl_unused)
{
	ACL_VSTRING *vp = acl_vstring_alloc(256);  // 分配 ACL_VSTRING對象
	char *ptr;
	int   i;

	// 字符串拷貝
	acl_vstring_strcpy(vp, "你們好,中國人民,Hi你們好, Hello World! 中國人民銀行!");

	printf(">>>%s\r\n", acl_vstring_str(vp));
	ptr = acl_vstring_strstr(vp, "Hello");  // 查詢字符串,區分大小寫
	if (ptr)
		printf(">>ok, find it, ptr = %s\r\n", ptr);
	else
		printf(">>error, no find it\r\n");

	ptr = acl_vstring_strcasestr(vp, "WORLD");  // 查詢字符串,不區分大小寫
	if (ptr)
		printf(">>ok, find it, ptr = %s\r\n", ptr);
	else
		printf(">>error, no find it\r\n");

	ptr = acl_vstring_strstr(vp, "中國");
	if (ptr)
		printf(">>ok, find it, ptr = %s\r\n", ptr);
	else
		printf(">>error, no find it\r\n");

	ptr = acl_vstring_strcasestr(vp, "Hi你們好");
	if (ptr)
		printf(">>ok, find it, ptr = %s\r\n", ptr);
	else
		printf(">>error, no find it\r\n");

	ptr = acl_vstring_memchr(vp, 'W');  // 查詢某個字符
	if (ptr)
		printf(">>ok, find it, ptr = %s\r\n", ptr);
	else
		printf(">>error, no find it\r\n");

	acl_vstring_strcpy(vp, "hello");  // 字符串拷貝
	ptr = acl_vstring_strstr(vp, "h");  // 字符串查找
	if (ptr)
		printf(">>>find it, ptr: %s\r\n", ptr);
	else
		printf(">>>not find it\r\n");

	printf("\r\n------------------------------------------------------------\r\n");
	for (i = 0; needle_tab[i]; i++) {
		string_rfind(vp, needle_tab[i]);
	}

	printf("\r\n------------------------------------------------------------\r\n");
	for (i = 0; needle_tab[i]; i++) {
		string_case_rfind(vp, needle_tab[i]);
	}

	printf("\r\n------------------------------------------------------------\r\n");
	for (i = 0; needle_tab[i]; i++) {
		string_find(vp, needle_tab[i]);
	}

	printf("\r\n------------------------------------------------------------\r\n");
	for (i = 0; needle_tab[i]; i++) {
		string_case_find(vp, needle_tab[i]);
	}

	printf("\r\n------------------------------------------------------------\r\n");
	const char *s1 = "hello world", *s2 = "WOrld", *s3 = "world";

	printf("strrncasecmp: %s %s %s, n: %d\n", s1,
		strrncasecmp(s1, s2, strlen(s2)) == 0 ? "==" : "!=", s2, (int) strlen(s2));
	printf("strrncasecmp: %s %s %s, n: %d\n", s1,
		strrncasecmp(s1, s2, strlen(s2) + 1) == 0 ? "==" : "!=", s2, (int) strlen(s2) + 1);

	s1 = "www.hexun.com";
	s2 = ".hexun.com";
	printf("strrncasecmp: %s %s %s, n: %d\n", s1,
		strrncasecmp(s1, s2, strlen(s2)) == 0 ? "==" : "!=", s2, (int) strlen(s2));

	printf("\r\n------------------------------------------------------------\r\n");
	printf("strrncmp: %s %s %s, n: %d\n", s1, strrncmp(s1, s2, strlen(s2)) == 0 ? "==" : "!=", s2, (int) strlen(s2));
	printf("strrncmp: %s %s %s, n: 3\n", s1, strrncmp(s1, s2, 3) == 0 ? "==" : "!=", s2);
	printf("strrncmp: %s %s %s, n: %d\n", s1, strrncmp(s1, s3, strlen(s3)) == 0 ? "==" : "!=", s3, (int) strlen(s3));
	printf("strrncmp: %s %s %s, n: %d\n", s1, strrncmp(s1, s3, strlen(s3) + 1) == 0 ? "==" : "!=",
		s3, (int) strlen(s3) + 1);

	// 帶格式寫字符串
	acl_vstring_sprintf(vp, "max long long int: %llu", (unsigned long long int) -1);
	printf("%s\n", acl_vstring_str(vp));

	// 釋放 ACL_VSTRING對象
	
	acl_vstring_free(vp);

	end();
	return (0);
}

 

4、小結

  ACL_VSTRING強大易用的功能足可使你編寫常見的字符串應用例子,使你省去了諸如內存從新分配等雜事,一方面提升了開發效率,另外一方面減小了出錯機率。

  ACL庫下載地址: http://acl.sourceforge.net

 

      我的微博:http://weibo.com/zsxxsz

相關文章
相關標籤/搜索