UTF-8编码数据在命令行终端编织成表格并输出
来源:互联网 发布:淘宝导购怎么做 编辑:程序博客网 时间:2024/06/04 01:31
UTF-8编码数据在命令行终端编织成表格并输出
1.简介
我最近在Fadore23操作系统上学习C语言,发现在学习数据结构与算法这方面知识的时候,数据域中常常都只有一个简单类型数据或者是一个字符串,这样纯学算法而不去考虑数据结构,学到最后觉得很空,因为算法的本质是去操作数据。后来突发奇想,想去实现一个类似于mysql一样的数据库,当然实现这样一个数据库对现阶段的我肯定是个遥远梦想,但是为了梦想总是得迈出步伐,而我的第一步就是对单表进行增、删、改、查。
众所周知,database都是有命令行终端进行操作的(sqlserver除外),那么数据以表格的形式在终端打印就成了我的第一个问题,为了后面的学习,我必须解决这个问题,通过了两天的努力,就有了今天的这篇博文,或许下面的代码效率低,也或许我的设计结构就不对,但是这是我的第一版,实现了自己的需求,后面我有了新的想法,我会不断的完善,或者重写。若您对我的代码有什么好的建议或者意见,请Email联系我。( Email: andensemail@163.com ) 对于您的关注我深表感激。
先上两张图看看^_^~
2.最需要解决的问题
Linux系统常用的是UTF-8编码,一个UTF-8的汉字在内存占用三个字节,而在终端打印时,它只占用二个字符的位置,那么表格的格式(各字段对齐)成了主要问题。
3.数据结构介绍
typedef struct table {
char *line;//字符串指针
struct table *pNext;//后续节点指针
} TABLE, *PTABLE;
将需要写在表格一行中的数据有规则的组合成一个字符串,放在动态内存中。然后创建一个TABLE节点Tnode,让Tnode.line指向字符串的首地址,而一张表格是由多行字符串组成的,那就用一个以TABLE 为节点的链表表示。 Tnode.pNext指向下一个行字符串。当需要将表格打印在终端时,只要遍历打印这个链表就行。
4.接口函数介绍( 我就写了三个 )
a. 打开一张表格
PTABLE OpenTable( char symble1, char symble2, char *tableName, char *tableTail, char **data );
char symble1: 这个符号用于画表格的外边框
char symble2: 这个符号用于画表格内行的分格,而列我用的是空白分格
char *tableName: 表格的名字
char *tableTail: 表格的尾行,用于写一些统计数据,本程序只实现了统计数据的个数,后面有需求时我再完善,统计数据用一个 ‘$’号,写在文本中。
chr **data: 这个就是要插入表格的数据,是一个字符串数组,长度任意,但最后一个字符指针指向 NULL
return : PTABLE数据类型的,是一个TABLE的指针。
使用: PTABLE pHead = NULL;//定义一个表的头指针
*data[10] = {
"学号 姓名 性别 年龄 年级 班级 语文成绩 数学成绩 英语成绩 总成绩",
"2008 王小晨 男 10 4 丙 95.5 100 98.5 294",
"2009 张胜 男 10 4 丙 94.5 99 97.5 291",
"2010 刘倩 女 10 4 丙 90.5 100 95.5 286",
"2011 Mary 女 10 4 甲 99.5 100 95.5 295",
NULL
};// 每个字段间可用 空格,逗号,问号,感叹号格开。
pHead = OpenTable( '*' , '-' , "成绩表" , "共计 $ 人" , data );//本函数的调用
b.在命令行终端打印表格
void PrintTable( PTABLE pHead );
PTABLE pHead: 是表指针,表格链表中每个节点都必须是 TABLE 类型的。
return void 此函数返回值为空,我们用的主要是这个函数的副作用遍历调用C语言的 I / O 库函数,在命令行终端打印。
使用:PrintTable( pHead );
c. 关闭一张表格
void CloseTable( PTABLE pHead );
PTABLE pHead: 是表指针,表格链表中每个节点都必须是 TABLE 类型的。
return void 此函数返回值为空,我们用的主要是这个函数的副作用,依次释放每个节点内动态分配的字符串空间与该节点的动态空间。
使用:CloseTable( pHead );
5.初始化配置文件
# define MALLOC( type, len ) (type*)malloc( sizeof(type) * len ) /*malloc预定义函数*/
# define TRUE 1 /* BOOL 真*/
# define FLASE 0 /* BOOL 假*/
# define PRE 15 /* 表格的前置空白数 */
# define COL 102 /* 表格的横向长度 */
# define DATACOL 11 /* 表格中最最大字段数 */
a. 后三个是表格的配置,可以根据自己的需求改变其值,也可以改变OpenTable函数,使这三个配置数据做为参数传入。
b. 表格没有列数限制,所有数据全部打印,数据量大的时候,需配置好终端。我后面会做一个有列数限制且带上下翻页的,我想这个主要问题在于缓存的设计。
6.代码
a.测试主函数
b.制表函数库
众所周知,database都是有命令行终端进行操作的(sqlserver除外),那么数据以表格的形式在终端打印就成了我的第一个问题,为了后面的学习,我必须解决这个问题,通过了两天的努力,就有了今天的这篇博文,或许下面的代码效率低,也或许我的设计结构就不对,但是这是我的第一版,实现了自己的需求,后面我有了新的想法,我会不断的完善,或者重写。若您对我的代码有什么好的建议或者意见,请Email联系我。( Email: andensemail@163.com ) 对于您的关注我深表感激。
先上两张图看看^_^~
2.最需要解决的问题
Linux系统常用的是UTF-8编码,一个UTF-8的汉字在内存占用三个字节,而在终端打印时,它只占用二个字符的位置,那么表格的格式(各字段对齐)成了主要问题。
3.数据结构介绍
typedef struct table {
char *line;//字符串指针
struct table *pNext;//后续节点指针
} TABLE, *PTABLE;
将需要写在表格一行中的数据有规则的组合成一个字符串,放在动态内存中。然后创建一个TABLE节点Tnode,让Tnode.line指向字符串的首地址,而一张表格是由多行字符串组成的,那就用一个以TABLE 为节点的链表表示。 Tnode.pNext指向下一个行字符串。当需要将表格打印在终端时,只要遍历打印这个链表就行。
4.接口函数介绍( 我就写了三个 )
a. 打开一张表格
PTABLE OpenTable( char symble1, char symble2, char *tableName, char *tableTail, char **data );
char symble1: 这个符号用于画表格的外边框
char symble2: 这个符号用于画表格内行的分格,而列我用的是空白分格
char *tableName: 表格的名字
char *tableTail: 表格的尾行,用于写一些统计数据,本程序只实现了统计数据的个数,后面有需求时我再完善,统计数据用一个 ‘$’号,写在文本中。
chr **data: 这个就是要插入表格的数据,是一个字符串数组,长度任意,但最后一个字符指针指向 NULL
return : PTABLE数据类型的,是一个TABLE的指针。
使用: PTABLE pHead = NULL;//定义一个表的头指针
*data[10] = {
"学号 姓名 性别 年龄 年级 班级 语文成绩 数学成绩 英语成绩 总成绩",
"2008 王小晨 男 10 4 丙 95.5 100 98.5 294",
"2009 张胜 男 10 4 丙 94.5 99 97.5 291",
"2010 刘倩 女 10 4 丙 90.5 100 95.5 286",
"2011 Mary 女 10 4 甲 99.5 100 95.5 295",
NULL
};// 每个字段间可用 空格,逗号,问号,感叹号格开。
pHead = OpenTable( '*' , '-' , "成绩表" , "共计 $ 人" , data );//本函数的调用
b.在命令行终端打印表格
void PrintTable( PTABLE pHead );
PTABLE pHead: 是表指针,表格链表中每个节点都必须是 TABLE 类型的。
return void 此函数返回值为空,我们用的主要是这个函数的副作用遍历调用C语言的 I / O 库函数,在命令行终端打印。
使用:PrintTable( pHead );
c. 关闭一张表格
void CloseTable( PTABLE pHead );
PTABLE pHead: 是表指针,表格链表中每个节点都必须是 TABLE 类型的。
return void 此函数返回值为空,我们用的主要是这个函数的副作用,依次释放每个节点内动态分配的字符串空间与该节点的动态空间。
使用:CloseTable( pHead );
5.初始化配置文件
# define MALLOC( type, len ) (type*)malloc( sizeof(type) * len ) /*malloc预定义函数*/
# define TRUE 1 /* BOOL 真*/
# define FLASE 0 /* BOOL 假*/
# define PRE 15 /* 表格的前置空白数 */
# define COL 102 /* 表格的横向长度 */
# define DATACOL 11 /* 表格中最最大字段数 */
a. 后三个是表格的配置,可以根据自己的需求改变其值,也可以改变OpenTable函数,使这三个配置数据做为参数传入。
b. 表格没有列数限制,所有数据全部打印,数据量大的时候,需配置好终端。我后面会做一个有列数限制且带上下翻页的,我想这个主要问题在于缓存的设计。
6.代码
a.测试主函数
/****************************************************************************************** * * * 测试主函数 * * * ******************************************************************************************/# include <stdio.h># include <stdlib.h># include <string.h># include "DrawTable.c"intmain( void ){PTABLE pHead1 = NULL,pHead2 = NULL, pHead3 = NULL; char *data1[10] = {"学号 姓名 性别 年龄 年级 班级 语文成绩 数学成绩 英语成绩 总成绩","2008 王小晨 男 10 4 丙 95.5 100 98.5 294","2009 张胜 男 10 4 丙 94.5 99 97.5 291","2010 刘倩 女 10 4 丙 90.5 100 95.5 286","2011 Mary 女 10 4 甲 99.5 100 95.5 295",NULL}; char *data2[10] = {"编号 名称 数量 单价 产地","1001011 流量计 1000 4584.3 中国广州","1001012 液位计 1500 3363.6 中国湖南 aabbcc","1001013 压力变送器 1200 758.9 中国上海","1001014 温度变送器 2300 543.2 中国山东",NULL};pHead1 = OpenTable('*','-',"成绩表","共计 $ 人" ,data1 );PrintTable( pHead1 );CloseTable( pHead1 );pHead1 = NULL;pHead2 = OpenTable('*','-',"这是一张产品清单","共计 $ 种" ,data2 );PrintTable( pHead2 );CloseTable( pHead2 );pHead2 = NULL;pHead3 = OpenTable('*','-',"公共信息","共计 $ 种" ,NULL );PrintTable( pHead3 );CloseTable( pHead3 );pHead3 = NULL;return EXIT_SUCCESS;}
b.制表函数库
/************************************************************************************************ * * *命令行终端上画表格函数库* * * ************************************************************************************************//* 预处理器可以移到自己的头文件或配置中 * */# define MALLOC( type, len ) (type*)malloc( sizeof(type) * len )# define TRUE 1# define FLASE 0# define PRE 15 /* 表格的前置空白数 */# define COL 102 /* 表格的横向长度 */# define DATACOL 11 /* 表格中最最大字段数 *//****************************************声明*************************************************//* 数据结构 */typedef struct table {char *line;//字符串指针struct table *pNext;//后续节点指针} TABLE,*PTABLE; /* 接口函数 */PTABLE OpenTable(char symble1, char symble2, char *tableName, char *tableTail, char **data );//打开一张表格void PrintTable( PTABLE pHead );//在stdout上打印一张表格void CloseTable( PTABLE pHead );//关闭一张表格/* 内部画图函数 */static PTABLE CreateTable();//创建一个表格static int DrawNull( PTABLE pHead, char symble ); //以symble字符画一条空心直线static int DrawLine( PTABLE pHead, char symble ); //以symble字符画一条实心直线static int DrawTitle( PTABLE pHead, char const *name, char symble );//画标题栏static int DrawData( PTABLE pHead, char **data, char symble );//填充并统计数据,第一行为导航static int DrawTail( PTABLE pHead, char *tableTail,int totleData, char symble);//画结尾统计行/* 内部功能函数 */static void AppendTable( PTABLE pHead, PTABLE new );//追加一个节点static void CopyData( char *line, char *data, int *dataPos );// 字符串格式化copystatic voidGetDataPos(char *buffer,int *dataPos , int offset );//在数据行中定位每个数据字段static void GetUtf8Length( char const *str, int *cnt );//utf-8编码的字符串统计/***********************************END**********************************************//*********************************接口函数*******************************************//* * Function: 打开一张表格 * symble1: 符号1,用于画表格的边框 * symble2: 符号2,用于画表格中的分割横线 * tableName: 表格名称,用于写入名称栏 * tableTail: 表格统计字符串的格式 * data: 表格中的数据,是一个字符串数组 * return: 返回一个表指针PTABLE,如果打开失败返回NULL * */PTABLEOpenTable( char symble1, char symble2, char *tableName, char *tableTail, char **data ){PTABLE pHead = NULL;pHead = CreateTable();//初始化一个头节点if( pHead != NULL ){int totalData = 0; //数据行统计器DrawLine( pHead, symble1); //画横线DrawTitle( pHead, tableName, symble2); //写表格名DrawLine( pHead, symble2); //画横线totalData = DrawData( pHead, data, symble1 ); //写数据DrawLine( pHead, symble2); //画横线DrawTail( pHead, tableTail,totalData, symble2); //画结尾统计DrawLine( pHead, symble1); //画横线}return pHead;}/* * Function: 在标准输出打印表格 * pHead: 表格指针 * return: void * */voidPrintTable( PTABLE pHead ){//链表拥有头节点,头节点中无数据,故跳过while( pHead = pHead->pNext, pHead != NULL )printf( "%s\n", pHead->line );}/* * Function: 关闭一个表格( 释放所有动态分配的指针 ) * pHead: 表格指针 * return: void * */voidCloseTable( PTABLE pHead ){PTABLE p;//临时指针指向当前节点,当前节点指针前移,释放临时指针所指节点中所有的动态内存while( p = pHead, p != NULL){pHead = pHead->pNext;free( p->line);p->line = NULL;//拴野指针free( p );p = NULL;//拴野指针}}/***********************************END**********************************************//*********************************内部画图函数*******************************************//* * Function:创建一个表格 (分配一个头节点) * return:PTABLE 失败则返回NULL * * */static PTABLECreateTable(){PTABLE pHead;//动态分配一个节点pHead = MALLOC( TABLE , 1 );if( pHead != NULL){//该节点不包涵任何数据pHead->line = NULL;pHead->pNext = NULL;}return pHead;}/* function: 画一条空心直线 if( symbel == '*' ) line = " * *\0" * pHead: 表格指针. * symble: 制线符号,用symble这个字符为表格画两端. * return: TRUE 画线成功, FLASE 画线失败,且释放了相应内存. * */static intDrawNull( PTABLE pHead , char symble ){//定义新节点空间并为其分配内存PTABLE new; new = MALLOC( TABLE, 1 );if( new != NULL ){//为新节点分配字符串内存new->line = MALLOC( char, PRE+COL);// PRE 表格前的空格数, COL表格行的长度if( new->line != NULL ){//画空心直线 ( 两头有字符,中间是空格,结尾加上NUL )memset( new->line, 32, PRE+COL );// PRE+COL个字符全部画成空格memset( new->line+PRE, (int)symble, 1 );//第一个位置画上符号memset( new->line+PRE+COL-2, (int)symble, 1 );//倒数第二个位置画上符号memset( new->line+PRE+COL-1, 0 , 1 );//倒数第一个位置写入NUL,标致字符串结束 /*当style == '*'时 行的表达:| * *\0| *///追加new->pNext = NULL;//这步也可以放到追加函数中去AppendTable( pHead, new );return TRUE;//这是函数唯一正确的出口}//字符串内存分配失败时,释放节点的内存-----------拒绝内存泄漏,拴住野指针free( new );new = NULL; //拴住野指针return FLASE;}return FLASE;}/* * Function: 画一条实心直线 if(symble == '*') line = " *********************************\0" * pHead: 表格指针. * symble: 制表符号,用symble这个字符为表格画直线. * return TRUE 画线成功, FLASE 画线失败,且释放了相应内存. */static intDrawLine( PTABLE pHead, char symble ){//定义新节点并分配内存空间PTABLE new;new = MALLOC( TABLE, 1 );if( new != NULL ){//分配字符指针内存空间new->line = MALLOC( char, PRE+COL );if( new->line != NULL ){//画出字符串memset( new->line, 32, PRE+COL ); //字符串清空memset( new->line+PRE, (int)symble, COL-1 ); //画线memset( new->line+PRE+COL-1, 0, 1 );//加NUL字符//追加节点new->pNext = NULL;AppendTable( pHead, new );return TRUE;}//拒绝内存泄漏,拴住野指针free( new );new=NULL;return FLASE;}return FLASE;/*若有不清楚之处,参考DrawNull() 函数讲解*/}/* * Function: 画标题栏 if( symble == '-') line = " - TABLENAME -\0" * pHead: 表格指针 * name: 标题内容指针 * symble: 表格符号 * return TRUE 画线成功, FLASE 画线失败,且释放了相应内存. * */static int DrawTitle( PTABLE pHead, char const *name, char symble ){//定义新节点指针并分配动态内存PTABLE new;new = MALLOC( TABLE, 1 );if( new != NULL ){//统计utf8汉字的长度int cnt[5];//定义字符串统计数组memset( cnt, 0, sizeof(int) * 5 );//清空字符串统计数组GetUtf8Length( name, cnt );//统计字符串中utf-8编码字符的个数。/* 一个汉字以utf-8编码占3个字节。 * 一个汉字在终端显示,占2个字符的大小。 * 也就是说,一个汉字在内存中占了3个字符的位置,在终端打印时却只占用2个字符的大小。 * 问题:英文字符串与中文字符,让其文字个数一样,但是在终端显示长度却不一样,汉字短,刚好短汉字的个数个字符。 * PRE+COL+cnt[3], 故分配内存时就要加上被汉字多占的字符数,也就是加上汉字的个数。 * */new->line = MALLOC( char, PRE+COL+cnt[3] );if( new->line != NULL ){//居中定位int len,pos;len = strlen( name );pos = ( COL - len + cnt[3] - 1 ) / 2;//画线memset( new->line, 32, PRE+COL+cnt[3] );memset( new->line+PRE, (int)symble, 1 );memcpy( new->line+PRE+pos, name, len );//把标题字符串复制到,新字符串的居中位置//这里还可以用 strncpy 函数, 有长度了就不要用 strcpy 函数,strcpy函数会复制 NUL字符memset( new->line+PRE+COL+cnt[3] - 2, (int)symble, 1 );memset( new->line+PRE+COL+cnt[3] - 1, 0, 1 );//追加new->pNext = NULL;AppendTable( pHead, new );return TRUE;}//拒绝内存泄漏,拴住野指针free( new );new = NULL;return FLASE;}return FLASE;}/* * Function:添加并统计数据 * if( symble = '*' ) " PTABLE: * xxx xxx xxxxx xx xxx xxxx *\0" * * xx xx xxx xxx xx xx *\0" * * xxxx x xxxx xx x xxxx *\0" *. * . *. * pHead: 表格指针 * data: 数据,以字符串数组存储的数据。 * symble: 制表符号 * return: 统计的数据数,以行为单位. * */static int DrawData( PTABLE pHead, char **data, char symble ){int totalData = 0; // 数据计数器//用导航计算每个字段的定位点,整张表每条数据的每个字段的定位点都一样int dataPos[DATACOL];//定位点数组, DATACOL为最大字段数char buffer[COL];// strtok会破坏原字符串,所以要用一个缓存来解决这个问题if( data != NULL && *data != NULL){//数据不为空strcpy( buffer, *data );//数据写入缓存GetDataPos( buffer, dataPos, 3 );//获取字段定位点数据dataPos[1] += 1;//第一个字段定位点要存放制表符号,所以定位点得右移,让出这个位置}else{DrawNull( pHead,symble );DrawNull( pHead,symble );DrawTitle( pHead,"您还没有添加数据呢^_^",symble );DrawNull( pHead,symble );DrawNull( pHead,symble );return totalData;}//循环追加数据行while( data != NULL && *data != NULL ){//定义新节点指针并分配动态内存PTABLE new = NULL;new = MALLOC( TABLE, 1 );if( new != NULL ){//统计汉字数量int cnt[5];memset( cnt, 0, sizeof(int) * 5 );GetUtf8Length( *data, cnt );//为字符串分配动态内存new->line = MALLOC( char, PRE + COL + cnt[3]);//DrawTitle函数中的有详解if( new->line != NULL ){//画数据行memset( new->line, 32, PRE+COL+cnt[3] );memset( new->line+PRE, (int)symble, 1 );strcpy( buffer, *data);// strtok会破坏原字符串,所以要用一个缓存来解决这个问题// 在每个字段定位点上,写入每个字段CopyData( new->line, buffer, dataPos );memset( new->line+PRE+COL+cnt[3]-2, (int)symble, 1 );memset( new->line+PRE+COL+cnt[3]-1, 0, 1 );//追加new->pNext = NULL;AppendTable( pHead, new );data++;//指向下一个字符串指针。totalData++;//统计加1continue;}free( new );new = NULL;continue;}continue;}return --totalData;//导航栏纳入统计}/* Function: 画结尾统计行 if( strcmp( tableTail, "共计 $ 人")) * line = " * 共计 totalData 人 *\0"; * pHead: 表格指针 * tableTail: 统计风格 * totalData: 数据统计个数 * symble: 制表符号 * return TRUE 画线成功, FLASE 画线失败,且释放了相应内存. * */static int DrawTail( PTABLE pHead, char *tableTail, int totalData, char symble){//将整数保存为字符串并计算长度char str[5];int numLen;sprintf( str, "%d", totalData );numLen = strlen( str );//以$分解tableTail为2个字符串并计算各长度char pre[100], tail[100];int lenP, lenT;sscanf( tableTail, "%s $ %s", pre, tail );lenP = strlen( pre );lenT = strlen( tail );//tableTail的汉字统计int cnt[5];memset( cnt, 0, sizeof(int) * 5 );GetUtf8Length( tableTail, cnt);//定义新节点指针并分配动态内存PTABLE new;new = MALLOC( TABLE, 1 );if( new != NULL ){//为字符串分配动态内存new->line = MALLOC( char, (PRE+COL+cnt[3]) );if( new->line != NULL){//画统计行memset( new->line, 32, (PRE+COL+cnt[3]) );memset( new->line+PRE,(int)symble, 1 );memcpy( new->line+PRE+COL-18,pre, lenP );memcpy( new->line+PRE+COL-18+lenP+2,str, numLen );memcpy( new->line+PRE+COL-18+lenP+numLen+4,tail, lenT );memset( new->line+PRE+COL+cnt[3]-2,(int)symble, 1 );memset( new->line+PRE+COL+cnt[3]-1,0, 1 );//追加数据new->pNext = NULL;AppendTable( pHead, new );return TRUE;}//拒绝内存泄漏,拴住野指针free( new );return FLASE;}return FLASE;}/**************************************内部功能函数 *****************************************//* Function:追加一个节点 * phead: 表格指针 * new: 新的节点指针 * return void * */static voidAppendTable( PTABLE pHead , PTABLE new ){//寻找表格的最后一个节点while( pHead->pNext != NULL )pHead = pHead->pNext;pHead->pNext = new;//注: new->pNext = NULL 这向工作在创建new节点时完成。return;}/* * Function: 分配插入位置 * buffer: 导航字符串指针 * dataPos: 统计位置数组指针 * offset: 数据写入时的向右偏移量 如*data 偏移0个字节,* data 偏移1个字节,* data偏移2个字节.... * return void * */static voidGetDataPos(char *buffer,int *dataPos, int offset ){//以 token 里的字符分解字符串 buffer, 统计字段数量int i;char *tmp;char token[] = "/ ,!?|-";for( i=0, tmp = strtok( buffer, token ); tmp !=NULL && i < DATACOL-1; tmp = strtok( NULL, token) )i++; dataPos[0] = i;//dataPos[1] 存放字段数量, dataPos[1]存放第一个字段的定位,dataPos[2].....//将ave平分i份,得到每份的长度int ave;ave = COL / i; //数据行的长度平分给i个字段,由于不一点完全整除,可能最后一个会长一点。//所有字段定位写入for( i = 1; i <= dataPos[0]; i++ )dataPos[i] = PRE + ave * (i-1) + offset;// 该字段位置 = 前置空白 + 平均值 * 第几个字段 + 偏移量 return;}/* * Function: 将数据写入表格已分配了好的空间 * *line: 已分配好的字符串空间 * *data: 被写入的数据 * *dataPos: 每行所有字段的定位 * return: void * */voidCopyData( char *line, char *data, int *dataPos ){//分解数据字符串,将其写入subData字符指针数组char *subData[DATACOL];//字段(字符)数组char token[] = " ,/!?";int i;//字段计数器for( i=0, subData[i] = strtok( data, token); i < dataPos[0] && subData[i] != NULL; subData[i] = strtok(NULL,token) )i++;//subData数组必须以NULL结尾if( subData[i] != NULL )subData[i] = NULL;//字符串指针数组以null结尾//统计本条数据中,每个字段中文的个数,存放在pcnt数组中int pcnt[DATACOL];int cnt[5];memset( pcnt, 0, sizeof(int) * DATACOL );//置0for( i = 1; i <= dataPos[0]; i++ ){// pcnt 与 dataPos 一致,数据从 1 开始写cnt[3] = 0;//汉字计数器清零GetUtf8Length( subData[i-1], cnt );pcnt[i] = cnt[3];}pcnt[0] = 0;//由于pcnt用于加法运算,写上这一行更安全。//数据写入int j, pos, len;for( i = 1; i <= dataPos[0]; i++ ){//数据行中,有了汉字后,计算其实际定位for( j = i - 1, pos = 0; j > 0; j-- )pos +=pcnt[j];//当前字段前面所有字段中汉字的总和 len = strlen( subData[i-1] );strncpy( line+dataPos[i]+pos, subData[i-1], len );//复制数据}return;}/* * Function: utf-8字符串统计函数 * str: 字符串指针 * cnt: 统计数组指针 * return void * */static void GetUtf8Length( char const *str, int *cnt ){//memset( cnt, 0 ,sizeof(int) * 5 );//我的其它博文中有讲解while( *str != '\0' ){if( *str & 1<<7 ){if( *str & 1<<6 ){if( *str & 1<<5 ){if( *str & 1<<4){cnt[4]++, cnt[0]++, str += 4;/* 11110xxx*/continue;}cnt[3]++, cnt[0]++, str += 3;/* 1110xxxx*/continue;}cnt[2]++, cnt[0]++, str += 2;/* 110xxxxx*/continue;}}cnt[1]++, cnt[0]++, str += 1;/*0xxxxxxx*/continue;}}/********************************************END*****************************************//***********************************解除预定义, 让项目更安全*********************************/# undef MALLOC # undef TURE # undef FLASE # undef PRE # undef COL # undef DATACOL /**************************************END OF FILE***************************************/
Writer: Anden Email: andensemail@163.com Time: 2016.04.04
1 0
- UTF-8编码数据在命令行终端编织成表格并输出
- MySQL中UTF-8编码的数据在CMD命令行显示乱码解决方案
- 解决MySQL中UTF-8编码的数据在命令行显示乱码
- 解决MySQL中UTF-8编码的数据在命令行显示乱码
- 【编】编码知识:Unicode和UTF-8
- 在UTF-8的locale终端下的VIM中打开GBK文件,并转换
- javascript/微信小程序中将String进行Base64编码并UTF-8格式输出
- 字符编码知识:Unicode、UTF-8、ASCII、GB2312等编
- 终端模拟软件xshell设置编码方式UTF-8
- 修改Windows10 命令终端cmd的编码为UTF-8
- 在MFC中用CStdioFile对象输出utf-8和ansi编码的文本
- UTF-8编码表
- 命令行cmd显示中文(使用UTF-8编码集)
- Win10 修改cmd命令行窗口UTF-8编码
- 使用UTF-8的编码只输出表头,没有输出数据时,出现乱码;当有数据输出时,则不会乱码。
- 使用jquery以jsonp方式在gbk页面请求utf-8编码的数据
- MySql中UTF-8编码的数据在CMD窗口显示乱码的解决方法
- linux下获取在终端中输出的数据
- 四大编辑器 -- Sublime, Atom, VS Code和Notepad++
- Java十进制转二进制,递归算法
- 关于sublime text3 的package control
- ARP与RARP详细解析
- UVa 1673 str2int
- UTF-8编码数据在命令行终端编织成表格并输出
- Android Studio 1.5.1 JNI 编程
- jboss tomcat 配置https请求方式
- 腾讯笔试题总结
- UDEV SCSI Rules Configuration for ASM in Oracle Linux 5, 6 and 7
- JQuery日期插件datepicker的使用
- Tomcat配置参数详解
- oracle job
- SQLite 命令