爱技术

 找回密码
 注册会员

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 1187|回复: 7
收起左侧

[其它] [Sieapi]gbprintf输出函数讨论和测试(结束)

[复制链接]
发表于 2008-2-6 02:59:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册会员 微信登录

x
     2月8日 总结
    提出这个函数时是由于wsprintf函数的不熟悉,也想为修改汉化程序提供了方便,通过阿冰和夜神的回帖,学到不少东西。
    了解了wsprintf的使用方法,虽然在输出中文上不直观,但也不复杂,而gbprintf在调用上方便,但问题不少,
    权衡利弊,决定放弃gbprintf啦,这贴子也算是一个学习笔记吧^_^
   
     2月6日
      先来一段新春感词,哈哈~
      随着ANSI(GB)的ElfPack的到来,越来越多的Elf程序用ASNI(GB)编码来开发,
大家的开发热情也越来越高涨,各位机油也将有越来越多的中文Elf程序使用^_^。
当然这要感谢很多走前面的先锋们,没有他们的辛勤工作,我下面要讨论的东西也无从谈起了。
在这里对各位前辈表示敬意,当然也有各位机油冒着死机的危险勇敢测试的功劳,呵呵。
春节快到啦,祝我们这个大家庭的每个人新春快乐,万事如意!下面进入正题:
     今天本来想把西机助手用GB编码改写,没想最后遇到一个问题:wsprintf函数最GB编码支持不是很好。

     这个阿冰谈到过:
原帖由 binghelingxi 于 2008-1-29 22:55 发表
问题出现。。。
wsprintf函数用起来还是有点问题。。。
如果这样使用:
wsprintf(ws, "如果");
这样就会是乱码。
而如果用:
wsprintf(ws,"%t" "如果")
这样就正常。

wsprintf(ws1, "你好!"));
wsprintf(ws2, "%t","你好!");
查看ws1->wsbody[0], ws2->wsbody[0]分别为6和3
ws1->wsbody里面直接为ANSI码。。。

直接输入中文需要加格式"%t"(我到现在都查不到"%t"是什么含义),否则它把字符串ASCII码处理(即单字节),显示出来就是乱码了。
最大的问题是它不支持下面方法

int num=10;
wsprintf(ws,"数值=%d",num);  //这样无法正常显示中文的

这个很常用,但是却不支持,够郁闷。。。不可能多定义几个WSHDR变量,把格式串分开放,然后把它接起来吧?
后来想着自己写一个gbprintf函数吧,能完完全全支持GB编码。。。查了不少资料,测试时死机n次,终于成功了o(∩_∩)o...哈哈
主要参考了c语言printf的源代码和gb2ws函数的源代码。下面是函数代码,供大家一起讨论和完善:
#include "stdarg.h"
#ifdef NEWSGOLD
#define CODEMAP_ADDR 0xA1568200  //-0xA157A24F
#else
#define CODEMAP_ADDR 0xA0FA0200
#endif
//保存中文GB编码字符到WSHDR
char *getgbch(WSHDR *ws,char *ch)
{
    unsigned short *codemap=(unsigned short *)CODEMAP_ADDR;
    unsigned char uc,uc2;
    uc=*ch++;
    if(uc <= 128)
    wsAppendChar(ws,uc);
    else
    {   
      uc2=*ch++;
      if(uc2 < 128)
        wsAppendChar(ws, uc2);
      else
        wsAppendChar(ws, codemap[(uc-129)*127+(uc2-128)]);
    }
    return ch;
}
//支持中文GB编码的gbprintf函数
int gbprintf(WSHDR *ws,const char *format,...)
{
  ws->wsbody[0] = 0;//清零
  char* chptr;
  char str[256];//保存输出内容
  char type[16];//保存输出格式
  int typepos=0;
  char *fmtptr=(char *)format;
  va_list ap;//不定参数变量
  va_start(ap,fmtptr);//不定参数开始
  while (*fmtptr!='\0') {
    if (*fmtptr == '%')//如果为百分号
    {
      type[typepos++]=*fmtptr++;//保存%,取下一个
      while(typepos!=0&&*fmtptr!='\0')
      {
        switch(*fmtptr)
        {
         case 's'://字符串
           type[typepos++]=*fmtptr++;
           type[typepos]='\0';
           sprintf(str,type,va_arg(ap,char*));
           chptr=str;
           while (*chptr!='\0')
           {
             chptr=getgbch(ws,chptr);
           }
           typepos=0;
           break;
         case 'c'://字符
           type[typepos++]=*fmtptr++;
           type[typepos]='\0';
           sprintf(str,type,va_arg(ap,char*));
           chptr=str;
           while (*chptr!='\0')
           {
             wsAppendChar(ws,*chptr++);
           }
           //chptr = va_arg(ap,char*);
           //getgbch(ws,chptr);
           typepos=0;
           break;
         case 'i':
         case 'd'://十进制整数
           type[typepos++]=*fmtptr++;
           type[typepos]='\0';
           sprintf(str,type,va_arg(ap,int));
           chptr=str;
           while (*chptr!='\0')
           {
             wsAppendChar(ws,*chptr++);
           }
           typepos=0;
           break;
         case 'u'://无符号整数
         case 'x'://小写十六进制整数
         case 'X'://大写十六进制整数
         case 'o'://八进制整数
           type[typepos++]=*fmtptr++;
           type[typepos]='\0';
           sprintf(str,type,va_arg(ap,unsigned int));
           chptr=str;
           while (*chptr!='\0')
           {
             wsAppendChar(ws,*chptr++);
           }
           typepos=0;
           break;
         case 'f'://浮点数
           type[typepos++]=*fmtptr++;
           type[typepos]='\0';
           sprintf(str,type,va_arg(ap,double));
           chptr=str;
           while (*chptr!='\0')
           {
             wsAppendChar(ws,*chptr++);
           }
           typepos=0;
           break;
         //支持的格式控制
         case '.':
         case '-':
         case '0':
         case '1':
         case '2':
         case '3':
         case '4':
         case '5':
         case '6':
         case '7':
         case '8':
         case '9':
            type[typepos++]=*fmtptr++;
            break;
         default://不满足直接输出,容错
            fmtptr=getgbch(ws,fmtptr);
            typepos=0;
        }//switch
      }//while
    }//if %
    else
    {
      fmtptr=getgbch(ws,fmtptr);
    }
  }
  va_end (ap);//参数结束
  return ws->wsbody[0];
}

说明:
使用方法和wsprintf一样,参数一样:__swi   __arm   int wsprintf (WSHDR *,const char*format,...);
接下来还希望实现一个像gbprintf(WSHDR *,char *str)的函数,估计不难,实现之后就不用这样了:wsprintf(ws2, "%t","你好!")。
目前支持的格式串:[0-9]  '.'  '-' %i %d %u %s %c %f %x %X %o
还不支持:'#' '*' 等等(有好想法可以自己编写控制格式^_^)
欢迎大家一起讨论,测试,完善它,弄成个标准,将大大方便GB编码程序的开发。之后可以最为API函数加到sieapi.h里面去。
现在已经是大年三十啦,过年回比较忙了,过年前完成一项工作,挺开心,好啦,睡觉啦,大家过年过得开心!!


[ 本帖最后由 DaiKangaroo 于 2008-2-8 23:17 编辑 ]
发表于 2008-2-6 12:32:06 | 显示全部楼层
看这事情不小*赶紧手机登陆来瞧瞧*
首先还是要感谢楼主的努力*
其次说一下个人看法*我认为原有的wsprintf已经够用了*我认为其实%t已经够用了*它相当于虚你成为LGP的效果*然后由esi处理*其实国外的俄文也是这样实现的*
稍微麻烦一点*
int num;
wsprintf(ws,"%t%d","序号为",num);
所以如果考虑作为一个swilib函数的必要性不大
不过加入到sieapi或独立为一个头文件也确实不错*会带来挺大的方便
回复 支持 反对

使用道具 举报

发表于 2008-2-6 13:09:18 | 显示全部楼层
可能第一种按WS处理了......所以当然是不会成为中文了................
现在也不会方便到哪里去,只是少了个%t,但是通常很多时候一些中文是要多次利用的,还不是那个样子..............
回复 支持 反对

使用道具 举报

发表于 2008-2-6 13:15:45 | 显示全部楼层
::/\fns ::/\fns ::/\fns 什么来的~~~~~~~~~~``

评分

参与人数 1金钱数 -50 贡献分 -1 收起 理由
8226175 -50 -1 如果理解错了可以更正

查看全部评分

回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-2-6 13:28:19 | 显示全部楼层
int num;
wsprintf(ws,"%t%d","序号为",num);
呵呵,原来可以这样的啊,没想到。
确实是没必要加入swilib函数的,我的考虑也是做为SieApi就可以的啦,我改一下标题,不要误会了。。。

想了一下,可以把getgbch函数用gb2ws来实现,就不用写这个函数了,还有gbprintf(WSHDR *,char *str)这个也不用实现了,本身就已经支持了
gbprintf用sprintf来实现的,理论上sprintf能支持的格式串,gbprintf都能实现。
其实我当初是考虑到这种情况:
int year,month,day,week;
wsprintf(ws,"%t%d%t%d%t%d%t%d","今天是",year,"年",month,"月",day,"日周",week);
gbprintf(ws,"今天是%d年%d月%d日周%d",year,month,day,week);
很明显,gbprintf方便很多,而且符合编程习惯。。。呵呵

[ 本帖最后由 DaiKangaroo 于 2008-2-6 13:34 编辑 ]
回复 支持 反对

使用道具 举报

发表于 2008-2-6 16:06:14 | 显示全部楼层

回复 5# 的帖子

这里十分汗,
时间日期的表达我通常是用最简方式
gb2ws这个函数就只能用一次(elfloader),其他地方都没有什么用的了,假如改为格式化输出还是有点用处的.但是好像相对多了一步

题外话
在CFG_STR_GB的使用好像有点问题,snprintf中CFG_STR_GB是不能正常使用的............
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-2-8 23:02:01 | 显示全部楼层
多谢阿冰对wsprintf的解释和夜神的提醒^_^
这个函数确实会方便一些,但是却有不少代价,似乎会多一次转换?效率不好。
或许还有一些无法预知的错误。
写这个函数之前没考虑太多东西,这次算是学习啦
wsprintf函数输出中文的写法虽然有些不直观,但效率和可靠性有保证,呵呵
gbprintf函数也就到这里啦~
接下来继续学习~
to 阿冰:能解释下ESI的原理么?
回复 支持 反对

使用道具 举报

发表于 2008-2-9 11:22:18 | 显示全部楼层

回复 7# 的帖子


                               
登录/注册后可看大图


ESI原理我也不大清楚啊。。。

ELFOADER对ESI进行了拓展。。。本来手机只能使用内置的语言包。。。而我们对他拓展之后就可以使用我们自己的字符了。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员 微信登录

本版积分规则

小黑屋|Archiver|手机版|爱技术 ( 沪ICP备08115260号-3 )

GMT+8, 2025-6-3 09:02

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表