西安 邮 电大学
实验名称
一、实验目的
1.了解计算机内部的字符处理与编码
2. 提高C语言编程能力
二、实验要求
编写一个程序,实现从文件中读取内容,并可以图形界面下显示文章
三、 实验内容
一.函数功能简介:
1.bool read_file(char s[]);
把对应路径文件中的内容读入字符串s中,成功则返回ture ,否则返回false
2.long get_adress(int x,int y,char *s);
遍历一遍s数组,把每行的第一个字符的地址存入adress数组中
3.void print_words(int x,int y,char *s,int colour,intcur);
输出字符:从cur行开始输出,输出PAGE_LINE行
4.DWORD WINAPI mouse(LPVOID l);
多线程函数,在程序运行过程中,一直保持运行状态,不断读取鼠标消息
5.void button_introduce();
作者信息按钮
6.void button_openfile();
打开文件按钮
7.void button();
包含5和6两个按钮
8. BeginBatchDraw();
开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
9, FlushBatchDraw();
这个函数用于执行未完成的绘制任务。
10. EndBatchDraw();
结束批量绘制,并执行未完成的绘制任务。
二.宏简介:
FONTSIZE: 字的放大倍数
WIDE: 每行字占的宽度
STARX: 文章左上角的X坐标
STARY: 文章左上角的Y坐标
SIZE_SCREEMX,SIZE_SCREEMY: 开创图形界面的大小
PAGE_LINE: 每页所显示的行数
三.全局变量介绍:
flag:是否单击了“打开文件”
flag1:是否单击了“作者介绍”
flag3:是否是第一次打开文件
char road[200]; :文件路径
char *adress[1000000];储存每行的第一个字符的地址
四.函数调用关系:
Main:
initgraph(SIZE_SCREEMX,SIZE_SCREEMY);
BeginBatchDraw();
introduce()
button();
button_introduce();
button_openfile();
CreateThread(NULL,0,mouse,NULL,0,NULL);
get_adress(STARX,STARY,s);
print_words(STARX,STARY,s,WHITE,0);
FlushBatchDraw();
EndBatchDraw();
closegraph();
五.主要函数说明
1.void print_words(int x,int y,char *s,int colour,intcur)
{
FILE*fp;
charbuffer[32]; //32字节的字模缓冲区
registeri,j,k; //寄存器变量
unsignedchar qh,wh;
unsignedlong location;
if((fp=fopen("hzk16","rb"))==NULL)//打开文件
{
printf("Can'topen hzk16!");
getch();
exit(0);
}
while(*s!=EOF)//读到文件尾
{
if(s==adress[cur+PAGE_LINE])break;//当显示完本页面,跳出循环
if(*s>0&&*s<160)
{
charch=s[0];
if(ch=='\n')//当遇到换行 ,进行换行操作
{
y+=16*FONTSIZE;
x=STARX;
}
else
{
if(ch=='')//当遇到空格,不用输出,x坐标右移
{
x+=8*FONTSIZE;
}
elseif(ch==9)//同理,遇到制表符,不输出,右移
{
x+=4*8*FONTSIZE;
}
else
{
outtextxy(x,y,ch);//正常ascall码字符输出
x+=8*FONTSIZE;
}
if(x>=WIDE)//当超过宽度,换行
{
y+=16*FONTSIZE;
x=STARX;
}
}
s+=1;//地址右移
}
else
{
if(*s==-1&&*(s+1)==0) //当遇到汉字的空格时,跳过
x+=16*FONTSIZE;
else
{
qh=*s-0xa0; //汉字第一个码数减去160
wh=*(s+1)-0xa0; //汉字第二个码数减去160
location=(94*(qh-1)+(wh-1))*32L;// 计算汉字字模在文件中的位置
fseek(fp,location,SEEK_SET); //在字模中找到相应汉字对应的字模数据位置
fread(buffer,1,32,fp); //从字模文件中读取数据
for(i=0;i<16;i++) //输出:16行,每行两个字节,每个字节8个二进制数,所以为16*16
for(j=0;j<2;j++)
for(k=0;k<8;k++)
if(((buffer[i*2+j]>>(7-k))&0x1)!=NULL)
fontsize(x+8*j+k,y+i,FONTSIZE,colour);
x+=16*FONTSIZE; //位置右移
}
s+=2; //地址右移
if(x>=WIDE) //换行操作
{
y+=16*FONTSIZE;
x=STARX;
}
}
}
}
2.long get_adress(int x,int y,char *s)
//该函数与print_words同理,只是不用输出,只把第一行的地址保存到adress数组中
if(x==STARX) //核心
{
adress[len]=s;
len++;
}
3.DWORD WINAPI mouse(LPVOID l)
{
MOUSEMSGm; // 定义鼠标消息
while(true)//死循环,不断获取
{
//获取一条鼠标消息
m= GetMouseMsg();
switch(m.uMsg)
{
caseWM_LBUTTONDOWN:
if(m.x>=10&&m.x<=80&&m.y>=10&&m.y<=35)
{
flag=1; //全局变量鼠标单击“打开文件”标记
cleardevice();
InputBox(road,100,"请输入文本文件路径:");//弹出输入框
cleardevice();
}
if(m.x>=110&&m.x<=180&&m.y>=10&&m.y<=35)
{
flag1=1;//全局变量鼠标单击“作者结束标记”
introduce();//介绍函数
FlushBatchDraw();
}
break;
}
}
}
来看源码:
#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<math.h>
#include<windows.h>
#define FONTSIZE 1
#define WIDE 800
#define STARX 70
#define STARY 50
#define SIZE_SCREEMX 1000
#define SIZE_SCREEMY 800
#define PAGE_LINE 40
DWORD WINAPI mouse(LPVOID l);
void button_introduce();
void button_openfile();
void button();
int flag=0,flag1=0,flag3=0;
char road[200];
char *adress[1000000];
bool read_file(char s[]);
void fontsize(int x,int y,int n,int colour);
void print_words(int x,int y,char *s,int colour,int cur);
long get_adress(int x,int y,char *s);
void introduce();
void main()
{
long len,cur=0;
int ch;
char s[100000];
initgraph(SIZE_SCREEMX,SIZE_SCREEMY);
BeginBatchDraw();
CreateThread(NULL,0,mouse,NULL,0,NULL);
loop:if (flag)
{
flag=0;
memset(s,0,sizeof(s));
memset(adress,0,sizeof(adress));
button();
}
else
{
button();
FlushBatchDraw();
if(!flag3) getch();
flag3=1;
}
if(flag1)
{
flag1=0;
cleardevice();
button();
FlushBatchDraw();
}
if(flag||flag1)
{
goto loop;
}
if(!read_file(s))
{
outtextxy(SIZE_SCREEMX/3,SIZE_SCREEMY/3,"该文件不存在!!");
getch();
cleardevice();
}
len=get_adress(STARX,STARY,s);
print_words(STARX,STARY,s,WHITE,0);
FlushBatchDraw();
do
{
ch=getch();
if(flag||flag1)
{
goto loop;
}
switch(ch)
{
case 'w':
if(cur>=1)
{
cur--;
}
cleardevice();
print_words(STARX,STARY,adress[cur],WHITE,cur);
button();
FlushBatchDraw();
break;
case 's':
if(cur<len-1)
{
cur++;
}
cleardevice();
print_words(STARX,STARY,adress[cur],WHITE,cur);
button();
FlushBatchDraw();
break;
case 'a':
if(cur>1+PAGE_LINE)
{
cur-=PAGE_LINE;
}
cleardevice();
print_words(STARX,STARY,adress[cur],WHITE,cur);
button();
FlushBatchDraw();
break;
case 'd':
if(cur<len-1-PAGE_LINE)
{
cur+=PAGE_LINE;
}
cleardevice();
print_words(STARX,STARY,adress[cur],WHITE,cur);
button();
FlushBatchDraw();
break;
default:
break;
}
}while(ch!='q');
cleardevice();
settextcolor(GREEN);
settextstyle(30, 0, _T("宋体"));
outtextxy(SIZE_SCREEMX/3,SIZE_SCREEMY/3,"press anykey to quit!");
FlushBatchDraw();
EndBatchDraw();
getch();
closegraph();
}
bool read_file(char s[])
{
FILE *fp;
int i=0;
fp=fopen(road,"rt");
if(fp==NULL)
{
printf("there is no such file!");
return false;
}
while((s[i]=fgetc(fp))!=EOF) i++;
fclose(fp);
return true;
}
// x,y为显示坐标,s为显示字符串,colour为颜色
void print_words(int x,int y,char *s,int colour,int cur)
{
FILE *fp;
char buffer[32]; //32字节的字模缓冲区
register i,j,k; //寄存器变量
unsigned char qh,wh;
unsigned long location;
if((fp=fopen("hzk16","rb"))==NULL)//打开文件
{
printf("Can't open hzk16!");
getch();
exit(0);
}
while(*s!=EOF)//读到文件尾
{
if(s==adress[cur+PAGE_LINE]) break;//当显示完本页面,跳出循环
if(*s>0&&*s<160)
{
char ch=s[0];
if(ch=='\n')//当遇到换行 ,进行换行操作
{
y+=16*FONTSIZE;
x=STARX;
}
else
{
if(ch==' ')//当遇到空格,不用输出,x坐标右移
{
x+=8*FONTSIZE;
}
else if(ch==9)//同理,遇到制表符,不输出,右移
{
x+=4*8*FONTSIZE;
}
else
{
outtextxy(x,y,ch);//正常ascall码字符输出
x+=8*FONTSIZE;
}
if(x>=WIDE)//当超过宽度,换行
{
y+=16*FONTSIZE;
x=STARX;
}
}
s+=1;//地址右移
}
else
{
if(*s==-1&&*(s+1)==0) //当遇到汉字的空格时,跳过
x+=16*FONTSIZE;
else
{
qh=*s-0xa0; //汉字第一个码数减去160
wh=*(s+1)-0xa0; //汉字第二个码数减去160
location=(94*(qh-1)+(wh-1))*32L; // 计算汉字字模在文件中的位置
fseek(fp,location,SEEK_SET); //在字模中找到相应汉字对应的字模数据位置
fread(buffer,1,32,fp); //从字模文件中读取数据
for(i=0;i<16;i++) //输出:16行,每行两个字节,每个字节8个二进制数,所以为16*16
for(j=0;j<2;j++)
for(k=0;k<8;k++)
if(((buffer[i*2+j]>>(7-k))&0x1)!=NULL)
fontsize(x+8*j+k,y+i,FONTSIZE,colour);
x+=16*FONTSIZE; //位置右移
}
s+=2; //地址右移
if(x>=WIDE) //换行操作
{
y+=16*FONTSIZE;
x=STARX;
}
}
}
}
long get_adress(int x,int y,char *s)
//该函数与print_words同理,只是不用输出,只把第一行的地址保存到adress数组中
{
long len=0;
while(*s!=EOF)
{
if(x==STARX) //核心
{
adress[len]=s;
len++;
}
if(*s>0&&*s<160)
{
char ch=*s;
if(ch=='\n')
{
y+=16*FONTSIZE;
x=STARX;
}
else
{
if(ch==' ')
{
x+=8*FONTSIZE;
}
else if(ch==9)
{
x+=4*8*FONTSIZE;
}
else
{
x+=8*FONTSIZE;
}
if(x>=WIDE)
{
y+=16*FONTSIZE;
x=STARX;
}
}
s+=1;
}
else
{
x+=16*FONTSIZE;
s+=2;
if(x>=WIDE)
{
y+=16*FONTSIZE;
x=STARX;
}
}
}
return len;
}
void introduce()
{
int x=SIZE_SCREEMX/3,y=SIZE_SCREEMY/4;
cleardevice();
outtextxy(x,y,"******************************************************");y+=18*FONTSIZE;
outtextxy(x,y,"** 文本显示器 ");y+=18*FONTSIZE;
outtextxy(x,y,"**作者:西安邮电大学卓越班字符处理小组 ");y+=18*FONTSIZE;
outtextxy(x,y,"**功能简介: ");y+=18*FONTSIZE;
outtextxy(x,y,"** 向上移动:w ");y+=18*FONTSIZE;
outtextxy(x,y,"** 向下移动:s ");y+=18*FONTSIZE;
outtextxy(x,y,"** 向上翻页:a ");y+=18*FONTSIZE;
outtextxy(x,y,"** 向下翻页:d ");y+=18*FONTSIZE;
outtextxy(x,y,"** 退出 :q ");y+=18*FONTSIZE;
outtextxy(x,y,"******************************************************");y+=18*FONTSIZE;
}
void button_openfile()
{
setlinecolor(WHITE);
setfillcolor(LIGHTGRAY);
fillrectangle(10,10,80,35);
settextcolor(GREEN);
outtextxy(15,15,"打开文件");
settextcolor(WHITE);
}
void button_introduce()
{
setlinecolor(WHITE);
setfillcolor(LIGHTGRAY);
fillrectangle(110,10,180,35);
settextcolor(LIGHTMAGENTA);
outtextxy(115,15,"作者简介");
settextcolor(WHITE);
}
void button()
{
button_openfile();
button_introduce();
}
void fontsize(int x,int y,int n,int colour)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
putpixel(x+i,y+j,colour);
}
DWORD WINAPI mouse(LPVOID l)
{
MOUSEMSG m; // 定义鼠标消息
while(true)//死循环,不断获取
{
// 获取一条鼠标消息
m = GetMouseMsg();
switch(m.uMsg)
{
case WM_LBUTTONDOWN:
if (m.x>=10&&m.x<=80&&m.y>=10&&m.y<=35)
{
flag=1; //全局变量鼠标单击“打开文件”标记
cleardevice();
InputBox(road,100,"请输入文本文件路径:");//弹出输入框
cleardevice();
}
if(m.x>=110&&m.x<=180&&m.y>=10&&m.y<=35)
{
flag1=1;//全局变量鼠标单击“作者结束标记”
introduce();//介绍函数
FlushBatchDraw();
}
break;
}
}
}