📄 unit1.cpp
字号:
也会提供提取字模的工具.出于商业目的,这些厂家和个人不会给
用户提供源代码,用户只能使用而不能学习和修改源码,会感到有些
遗憾.
2.初学者因为好奇,想多了解一点这方面的知识,而教科书里面说的不是
很详细(这些雕虫小技,谁写啊),这个程序会满足你对点阵字库方面的
好奇心和求知的愿望。
3.大学里很多学生对c语言不感兴趣,原因大都是:a.教科书太死板b.
教师照本宣科.c.大家理论学的多,实践太少.d.不知道究竟用c语言来
干什么.其中最后一条是最多的,况且我们从小到大的考试制度,对于
科教兴国产生了越来越大的制约,学习的目的渐渐的演变成位考试而
学习,这正是教育的悲哀,也是我的悲哀(我大学c语言考试不及格,
终生的遗憾啊).这里发点牢骚了.分析这个程序可以帮助你温习你
本来已掌握的c语言知识,我用了很多没用的句子,大家可以分析一下,
哪些是不必要的,本程序包括了那些方面的知识,为什么会这样. 这正
是我的最大的初衷.
4.本程序在Borland C++ 3.0里编译,C++Buile或Vc++里字长不一样
可能需要修改,我没试过.
5.我这个人很好相处的,欢迎大家和我交朋友.
--------------------------------------------------------------------
*/
void hanzi_view();
void jmain() // access command-line arguments
{
int argc;
char i;
char* argv[20];
FILE *fp1,*fp2;
union word0
{
unsigned long int ll;
struct bytes0
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
}st0;
}un0;
union word
{
unsigned int ab;
struct bytes
{
unsigned char a;
unsigned char b;
}st;
}un;
unsigned char ch;
unsigned int m;
//start
clrscr();
//--------------------------------------------------------------------------
//可以通过对argv[1],argv[2]赋值,指出读取的源文件的名称、创建的目标文件的名称
//argv[1]="FILE1.TXT";//source file
//argv[2]="FILE12.TXT";//create new file
//--------------------------------------------------------------------------
/* if (argc!=3) // test number of arguments
{
//命令行参数包括少于3个
Form1->Memo1->Text="The paramers is < 3 \n"+char(13)+char(10);
Form1->Memo1->Text=Form1->Memo1->Text+"USAGE: HZK12.EXE FILE1.TXT FILE12.TXT) \n"+char(13)+char(10);
Form1->Memo1->Text=Form1->Memo1->Text+ "Use FILE1.TXT and FILE12.TXT{y/n}? \n"+char(13)+char(10);
ch=getch();
if(ch=='y'||ch=='Y')
{
argv[1]="FILE1.TXT"; //source file
argv[2]="FILE12.TXT"; //create new file
}
else
return;
}
*/
argv[1]="FILE1.TXT"; //source file
argv[2]="FILE12.TXT"; //create new file
if((fp1=fopen(argv[1],"rb"))==NULL)
{
cout<<"Read FILE1.TXT error !\n"; //FILE1.TXT文件不存在或读取文件错误
cout<<"Press any key to exit!";
getch();
return;
}
if((fp2=fopen(argv[2],"rb"))==NULL) //FILE12.TXT不存在则创建新文件FILE12.TXT
{
if((fp2=fopen(argv[2],"wb"))==NULL) //建立新文件错误
{
cout<<"Creat FILE12.TXT error!\n";
cout<<"Press any key to exit!";
getch();
return;
}
}
else
{
cout<<"The FILE12.TXT already exist!\n";
cout<<"Do you want to delete the target file(y/n)?"<<endl;
ch=getch();
if(ch=='y'||ch=='Y')
{
if((fp2=fopen(argv[2],"wb"))==NULL)
{
cout<<"The FILE12.TXT open error!\n";
cout<<"Press any key to exit!";
getch();
return;
}
}
else
{
cout<<"Please rename FILE12.TXT !\n";
cout<<"Press any key to exit!\n";
getch();
return;
}
}
clrscr();
//---------------------------------------------------------------------
cout<<"需要C51 or ASM 格式?\nPlease input 'c' or 'a' \n";
ch=getch();
clrscr();
/* if(ch=='c'||ch=='C')
cout<<"the data is C51\n";
else
cout<<"the data is ASM\n";
*/
if(k1!=1)
cout<<"the data is C51\n";
else
cout<<"the data is ASM\n";
//=================================================================================
//写入汉字内码表
un.st.a=fgetc(fp1);
fputs("//说明:从 FILE1.TXT 获取汉字内码(任意自造汉字库),从UCDOS文件 HZK12 获取汉字对应点阵",fp2);
fprintf(fp2,"%c%c",0x0d,0x0a);
// if(ch=='c'||ch=='C')
if(k1!=1) //写入C51格式的汉字内码表
{
fprintf(fp2,"//汉字内码表:");
fprintf(fp2,"%c%c",0x0d,0x0a);
fprintf(fp2,"uchar code hznm [ ][ 2] = {");
fprintf(fp2,"%c%c",0x0d,0x0a);
int i=0;
int j=0;
for(;!feof(fp1);i++)
{
if(!(i%120))
{
fprintf(fp2,"\"");
j++;
}
fputc(un.st.a,fp2);
un.st.a=fgetc(fp1);
if((i%120)==119)
{
fprintf(fp2,"\"%c%c",0x0d,0x0a);
}
}
fprintf(fp2,"\"};");
fprintf(fp2,"%c%c",0x0d,0x0a);
if(!(i%120))
{
fprintf(fp2,"//每行60个汉字,共%d行 ",j,(i%120)/2);
fprintf(fp2,"总计%d*%d=%d个汉字 测试累加值为 %d",j,60,(j*60),i/2);
}
else
{
fprintf(fp2,"//最后一行除外每行60个汉字,共%d行,最后一行%d个汉字 ",j,(i%120)/2);
fprintf(fp2,"总计(%d*%d)+%d=%d个汉字 测试累加值为 %d",j-1,60,(i%120)/2,((j-1)*60)+(i%120)/2,i/2);
}
fprintf(fp2,"%c%c",0x0d,0x0a);
}
else //写入汇编语言格式的汉字内码
{
fprintf(fp2,";汉字内码表,每行最多8个汉字:");
fprintf(fp2,"%c%c",0x0d,0x0a);
fprintf(fp2,"hznm_addr:");
unsigned int i=0;//总共多少字节汉字
unsigned int j=0;//第几行
int t;//统计最后一行汉字个数
do
{
if(!(i%16))
{
t=0;
fprintf(fp2,"%c%cDB 0%0.2XH",0x0d,0x0a,un.st.a);
j++;
}
else if((i%16)==15)
{
fprintf(fp2,"0%0.2XH;",un.st.a);
fseek(fp1,-16L,1); //文件指针往前移动16字节
for(int k=0;k<16;k++)
fputc(fgetc(fp1),fp2); //把刚才写入的8个汉字注释出来
un.st.a=fgetc(fp1);
i++;
t++;
if(feof(fp1))
break;
else
continue;
}
else
{
fprintf(fp2,"0%0.2XH",un.st.a);
}
un.st.a=fgetc(fp1);
i++;
t++;
if(!feof(fp1))
{
fprintf(fp2,",");
}
if(feof(fp1))
{
long ll0=0;
ll0=t;
fprintf(fp2,";");
fseek(fp1,-ll0,1);
for(int k=0;k<t;k++)
fputc(fgetc(fp1),fp2); //把最后一行汉字注释出来
break;
}
}while(1);
fprintf(fp2,"%c%c",0x0d,0x0a);
if(!(i%16))
{
fprintf(fp2,"//共%d行,每行8个汉字 ",j);
fprintf(fp2,"总计(%d*%d)=%d个汉字 测试累加值为 %d",j,8,(j*8),i/2);
}
else
{
fprintf(fp2,"//共%d行,最后一行除外每行8个汉字,最后一行%d个汉字 ",j,(i%16)/2);
fprintf(fp2,"总计(%d*%d)+%d=%d个汉字 测试累加值为 %d",j-1,8,(i%16)/2,((j-1)*8)+(i%16)/2,i/2);
}
fprintf(fp2,"%c%c",0x0d,0x0a);
}
fprintf(fp2,"%c%c",0x0d,0x0a);
//===========================================================================================
//写入汉字内码表对应的点阵表
m=0;//最大限制值
fseek(fp1,0,0); //文件指针指向开头第1字节
un.st.b=fgetc(fp1); //取汉字的第一个字节
un.st.a=fgetc(fp1); //取汉字的第二个字节
if(ch=='c'||ch=='C') //C51格式的点阵数据
{
fprintf(fp2,"//汉字内码表对应点阵,每行1个汉字24字节:");
fprintf(fp2,"%c%c",0x0d,0x0a);
fprintf(fp2,"uchar code hzdz [ ][%d] = {",HZDZ_LEN);
fprintf(fp2,"%c%c",0x0d,0x0a);
while(1)
{
if(feof(fp1))
{
cout<<"\nThe FILE1.TXT have finished!\n";
break; //点阵提取结束
}
un0.ll=gethzdz(un.ab); //取该汉字的24字节点阵数据
m++;
if(un0.ll==0xb020) //读HZK12文件到结尾,返回一个数作为标志
break; //'啊'的内码-0xA1A1=0xB040
//------------------------------------------------
//hanzi_view(); //查看24字节汉字点阵的外形是不是刚才读取的汉字
//------------------------------------------------
//将这个汉字的点阵数据写入目标文件
fgetc(fp1); //注意fp加1了,后面需要fseek(fp1,-1L,1);
for(int i=0;i<(HZDZ_LEN-1);i++)
{
fprintf(fp2,"0x%.2x%c",hzdz[i],',');
//if(i==12)
// fprintf(fp2,"%c%c",0x0d,0x0a);
}
if(feof(fp1)) //这个判断必需上一句fgetc(fp1);
{
fprintf(fp2,"0x%.2x}",hzdz[i]); //结束时数据尾不需要有逗号了
}
else
fprintf(fp2,"0x%.2x%c",hzdz[i],',');
fprintf(fp2,"%c%c",0x0d,0x0a);
///-------------------------------------------
//view 观察
Form1->Memo1->Text=printf("\ntotal m = %d\n",m);
Form1->Memo1->Text=printf("\nposition = %x",un0.st0.d);
Form1->Memo1->Text=printf("%x",un0.st0.c);
Form1->Memo1->Text=printf("%x",un0.st0.b);
Form1->Memo1->Text=printf("%0.2xH BYTE\n = 32*((FIRST-0xA1)*94+(SECOND-0xA1))\n",un0.st0.a);
cout<<"\ncontinue(y/n)?\n";
//ch=getch();
//if(ch=='n'||ch=='N')
// break;
//--------------------------------------------------------------------------
if(m>=7000) //限制最多提取7000个汉字,比国标还多,够了吧?国标只有6000多个
{
fprintf(fp2,"不会吧,你的汉字库比国标还大?\n");
break; //如果汉字库没有错,根本不会从这里退出
}
fseek(fp1,-1L,1); //这里要减去1,因为前面有fgetc(fp1);
un.st.b=fgetc(fp1); //取汉字内码第1字节
un.st.a=fgetc(fp1); //取汉字内码第2字节
}
}
else //汇编格式的点阵数据
{
fprintf(fp2,";汉字内码表对应点阵,每行1个汉字(24字节)");
fprintf(fp2,"%c%c",0x0d,0x0a);
fprintf(fp2,"hzdz_addr:");
fprintf(fp2,"%c%c",0x0d,0x0a);
while(1)
{
if(feof(fp1)) //检测FILE1.TXT文件是否结束
{
cout<<"\nThe FILE1.TXT have finished!\n";
break; //点阵提取结束
}
un0.ll=gethzdz(un.ab); //取该汉字的24字节点阵数据
m++;
if(un0.ll==0xb020) //读HZK12文件到结尾,返回一个数作为标志
break; //'啊'的内码-0xA1A1=0xB040
//------------------------------------------------
//hanzi_view(); //查看24字节汉字点阵的外形对照读取的汉字
//------------------------------------------------
//将这个汉字的点阵数据写入文件
for(int i=0;i<HZDZ_LEN;)
{
if(!i)
fputs("DB ",fp2);
fprintf(fp2,"0%.2xH%c",hzdz[i],',');
i++;
fprintf(fp2,"0%.2xH",hzdz[i]);
i++;
if(i<(HZDZ_LEN-1))
fputc(',',fp2);
}
fprintf(fp2,"%c%c",0x0d,0x0a);//回车
///-------------------------------------------
//view 观察
printf("\ntotal m = %d \n",m);
printf("\nposition = %x",un0.st0.d);
printf("%x",un0.st0.c);
printf("%x",un0.st0.b);
printf("%xH BYTE\n = 32*((FIRST-0xA1)*94+(SECOND-0xA1))\n",un0.st0.a);
cout<<"\ncontinue(y/n)?\n";
//ch=getch();
//if(ch=='n'||ch=='N')
// break;
//--------------------------------------------------------------------------
if(m>=7000) //限制最多提取7000个汉字,比国标还多,够了吧?国标只有6000多个
{
fprintf(fp2,"不会吧,你的汉字库比国标还大?\n");
break; //如果汉字库没有错,根本不会从这里退出
}
un.st.b=fgetc(fp1); //取汉字内码第1字节
un.st.a=fgetc(fp1); //取汉字内码第2字节
}
}
fclose(fp1);
fclose(fp2);
cout<<"\nPress any key to exit "<<endl;
getch();
return;
}
//===================================================================================================
/*
函数功能:计算获取汉字内码对应的24字节的点阵数据
计算公式:该汉字在点阵字库HZK12里存放的位置=([汉字的第1字节-0xA1]*94+[汉字的第2字节-0xA1])*24 字节
同样, 该汉字在点阵字库HZK16里存放的位置=([汉字的第1字节-0xA1]*94+[汉字的第2字节-0xA1])*32 字节
明白了吧? 16*16点阵每个汉字需要(16*16)/8=32字节空间,12*12点阵每个汉字需要(12*16)/8=24字节的空间,每
行有4个点是没有用的,即每行第2个字节有4位无点阵数据,实际上每个汉字可以压缩成(12*12)/8=18字节.
*/
unsigned long gethzdz(unsigned int n)
{
FILE *fp;
static unsigned long m=0xb020;
unsigned long j,k; //如何定义可以实现最小的内存占用?
char i;
union word
{
unsigned int ab;
struct bytes
{
unsigned char a;
unsigned char b;
}st;
}un;
//***********************************
//start
if((fp=fopen("HZK12","rb"))==NULL)
// if((fp=fopen("HZK16","rb"))==NULL)
{
cout<<"Read HZK16 error !\n";
cout<<"Press any key to exit!";
getch();
return m ;
}
//************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -