C指针原理(39)-GLIB

一、简述与配置

GLib是一个跨平台的、用C语言编写的库,起初是GTK+的一部分,但到了GTK+第二版,开发者决定把跟图形界面无关的代码分开,这些代码于是就组装成了GLib。因为GLib具有跨平台特性,所以用它编写的程序可以无需进行大幅度修改就可以在其他程序上编译和运行。

glib库是Linux平台下最常用的C语言函数库,它具有很好的可移植性和实用性。

glib是Gtk +库和Gnome的基础。glib可以在多个平台下使用,比如Linux、Unix、Windows等。glib为许多标准的、常用的C语言结构提供了相应的替代物。

如果在程序中要使用到glib库中的函数,则应该包含glib.h头文件(在gtk.h和gnome.h头文件中已经包含了glib.h了)

1、Freebsd中安装glib

cd /usr/ports/devel/glib20

portsnap fetch extract

Looking up portsnap.FreeBSD.org mirrors… 7 mirrors found.

Fetching snapshot tag from isc.portsnap.freebsd.org… done.

Fetching snapshot metadata… done.

Updating from Fri Dec 6 11:20:31 CST 2013 to Mon Dec 23 21:23:19 CST 2013.

Fetching 4 metadata patches… done.

Applying metadata patches… done.

Fetching 4 metadata files… gunzip: (stdin): unexpected end of file

metadata is corrupt.

root@dp:/usr/ports/devel/glib20 # ls

Makefile distinfo files pkg-descr pkg-plist

root@dp:/usr/ports/devel/glib20 # make install clean

===> License LGPL20 accepted by the user

===> Found saved configuration for glib-2.36.3

===> Fetching all distfiles required by glib-2.36.3 for building

===> Extracting for glib-2.36.3

=> SHA256 Checksum OK for gnome2/glib-2.36.3.tar.xz.

===> Patching for glib-2.36.3

===> glib-2.36.3 depends on package: libtool>=2.4 - found

===> Applying FreeBSD patches for glib-2.36.3

2、windows下配置与安装

3、测试:

Linux/unix下测试,以freebsd为例

首先看一下下面这个程序,在编辑器中输入下面程序,程序首先创建20个1-100以内的随机数,并显示在屏幕,然后计算30000000次累加,并输出计算用的时间。

#include

int main(int argc, char *argv[])

{

GRand *rand;

GTimer *timer;

gint n;

gint i, j;

gint x = 0;

rand = g_rand_new(); //创建随机数对象

for(n=0; n<20; n++)

{ //产生随机数并显示出来

g_print("%d\t",g_rand_int_range(rand,1,100));

}

g_print("\n");

g_rand_free(rand); //释放随机数对象

//创建计时器

timer = g_timer_new();

g_timer_start(timer);//开始计时

for(i=0; i<10000; i++)

for(j=0; j<3000; j++)

x++;//累计

g_timer_stop(timer);//计时结束

//输出计时结果

g_print("%ld\tall:%.2f seconds was used!\n",x,g_timer_elapsed(timer,NULL));

}

编译

dp@dp:~/gliblearn % gcc pkg-config --cflags --libs glib-2.0 gthread-2.0 a.c -o mytest

最后执行:

dp@dp:~/gliblearn % ./mytest

96 24 52 87 52 16 62 17 78 62 76 6 33 53 87 3 40 69 20 33

30000000 all:0.08 seconds was used!

dp@dp:~/gliblearn %

二、21点游戏

1、游戏规则:

随机抽取1-11个数字,每次玩家和电脑各抽1次,玩家和电脑可以宣布不再抽数字,所有数字之和超过21点者输,在21点以内,大者胜利。

(1)欢迎玩家

使用gchar字符型来存储玩家姓名。

typedef char gchar;

编写代码如下:

#include

#include

#include

int main(int argc, char *argv[]){

setlocale(LC_ALL,"");

gchar gamename[10];

g_print(“您叫什么名字?\n”);

scanf("%s",&gamename);

g_print(“欢迎您,%s,这里是21点游戏\n”,gamename);

return 0;

}

dp@dp:~/gliblearn % gcc pkg-config --cflags --libs glib-2.0 gthread-2.0 1.c -o mytest

dp@dp:~/gliblearn % ./mytest

您叫什么名字?

joan

欢迎您,joan,这里是21点游戏!

dp@dp:~/gliblearn %

(2)引入随机数

使用glib的随机数函数产生随机数

gamerand = g_rand_new();

rndnumber=g_rand_int_range(gamerand,1,11);

程序如下:

#include

#include

#include

int main(int argc, char *argv[]){

setlocale(LC_ALL,"");

GRand *gamerand;

gchar gamename[10];

g_print(“您叫什么名字?\n”);

scanf("%s",&gamename);

g_print(“欢迎您,%s,这里是21点游戏\n”,gamename);

g_print("%s,请按键抽数字!\n",gamename);

getchar();

getchar();

gint rndnumber;

gamerand = g_rand_new();

rndnumber=g_rand_int_range(gamerand,1,11);

g_print("%s,您抽到的是:%d\n",gamename,rndnumber);

g_rand_free(gamerand);

return 0;

}

dp@dp:~/gliblearn % ./mytest

您叫什么名字?

joan

欢迎您,joan,这里是21点游戏

joan,请按键抽数字!

joan,您抽到的是:3

dp@dp:~/gliblearn %

(3)轮流抽数判断输赢

使用逻辑型变量类型gboolean,定义如下:

typedef gint gboolean;

A standard boolean type. Variables of this type should only contain the value TRUE or FALSE.

代码如下:

dp@dp:~/gliblearn % cat 21dian.c

#include

#include

#include

int main(int argc, char *argv[]){

setlocale(LC_ALL,"");

GRand *gamerand;

gchar gamename[10];

g_print(“您叫什么名字?\n”);

scanf("%s",&gamename);

g_print(“欢迎您,%s,这里是21点游戏\n”,gamename);

setbuf(stdin,NULL);

gint key=0;

gint rndnumber;

gint man_number,comp_number;

gint man_count=0,comp_count=0;

gboolean man_end=FALSE,comp_end=FALSE;

gboolean gameover=FALSE;

gamerand = g_rand_new();

do{

if (!man_end){

g_print("%s,按Y/y键抽数字,按其它键表示不再抽数字!\n",gamename);

key=getchar();

getchar();

//玩家抽数字

if (key==‘y’||key==‘Y’){

rndnumber=g_rand_int_range(gamerand,1,11);

man_number=rndnumber;

man_count+=man_number;

g_print("%s,您抽到的是:%d\n",gamename,man_number);

}else

{

g_print(“玩家放弃抽数!\n”,comp_number);

man_end=TRUE;

}

    }

//电脑抽数字

if (comp_count<=17){

rndnumber=g_rand_int_range(gamerand,1,11);

comp_number=rndnumber;

comp_count+=comp_number;

g_print(“电脑抽到的是:%d\n”,comp_number);

}else

{

g_print(“电脑放弃抽数!\n”,comp_number);

comp_end=TRUE;

}

if ((man_count>21 && comp_count>21)||(man_count21 && comp_count21)){

g_print(“平手,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

gameover=TRUE;

}

else if (man_count>21 && comp_count<=21) {

g_print(“电脑赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

gameover=TRUE;

}

else if (man_count<=21 && comp_count>21) {

g_print(“玩家赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

break;

}else if (man_end && comp_end){

man_count>comp_count?g_print(“玩家赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count):g_print(“电脑赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

     gameover=TRUE; 

}else

{

g_print("\n$$$$ 本 轮 结 束 , 电 脑 本轮结束,电脑%d点,%s %d点 ,$$$$\n",comp_count,gamename,man_count);

}

}while(!gameover);

g_rand_free(gamerand);

return 0;

}

编译执行:

dp@dp:~/gliblearn % gcc pkg-config --cflags --libs glib-2.0 gthread-2.0 21dian.c -o 21dian

dp@dp:~/gliblearn % ./21dian

您叫什么名字?

joan

欢迎您,joan,这里是21点游戏

joan,按Y/y键抽数字,按其它键表示不再抽数字!

y

joan,您抽到的是:7

电脑抽到的是:10

$$$$ 本 轮 结 束 , 电 脑 10 点 , j o a n 7 点 本轮结束,电脑10点,joan 7点 ,10joan7$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

Y

joan,您抽到的是:1

电脑抽到的是:9

$$$$ 本 轮 结 束 , 电 脑 19 点 , j o a n 8 点 本轮结束,电脑19点,joan 8点 ,19joan8$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

Y

joan,您抽到的是:10

电脑放弃抽数!

$$$$ 本 轮 结 束 , 电 脑 19 点 , j o a n 18 点 本轮结束,电脑19点,joan 18点 ,19joan18$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

Y

joan,您抽到的是:7

电脑放弃抽数!

电脑赢了,电脑19点,joan 25点

dp@dp:~/gliblearn % ./21dian

您叫什么名字?

joan

欢迎您,joan,这里是21点游戏

joan,按Y/y键抽数字,按其它键表示不再抽数字!

y

joan,您抽到的是:2

电脑抽到的是:8

$$$$ 本 轮 结 束 , 电 脑 8 点 , j o a n 2 点 本轮结束,电脑8点,joan 2点 ,8joan2$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

y

joan,您抽到的是:2

电脑抽到的是:3

$$$$ 本 轮 结 束 , 电 脑 11 点 , j o a n 4 点 本轮结束,电脑11点,joan 4点 ,11joan4$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

y

joan,您抽到的是:5

电脑抽到的是:5

$$$$ 本 轮 结 束 , 电 脑 16 点 , j o a n 9 点 本轮结束,电脑16点,joan 9点 ,16joan9$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

y

joan,您抽到的是:2

电脑抽到的是:9

玩家赢了,电脑25点,joan 11点

dp@dp:~/gliblearn %

三、Glib的数据类型及标准宏

1、GLib数据类型

类型                描述

gboolean

由于c语言没有提供布尔数据类型,所以Glib提供了gboolean,可以设置为TRUE或FALSE。

gchar (guchar)

和标准C的char(unsigned char)类型一致。

gconstpointer

一个指向常量的无类型指针。这种指针指向的数据不能改变。因此,它通常用于函数原型,表明这个函数不会改变该指针指向的数据。

gdouble

与标准C的double类型一致。取值范围从-G_MAXDOUBLE到G_MAXDOUBEL。G_MINDOUBLE指的是gdouble可以储存的最小正数。

gfloat

与标准C的float类型一致。可能的的取值范围从-G_MAXFLOAT到G_MAXFLOAT。G_MINFLOAT指的是gfloat可以储存的最小正数。

gint (guint)

和标准C的int(unsigned int)类型一致。有符号的gint类型的值必须在G_MININT到G_MAXINT的范围内。guint的最大值为G_MAXUINT.

gint8 (guint8)

被设计为在所有平台上都为8位的有符号和无符号整型。gint8的取值范围为-128到127(G_MININT8到G_MAXINT8),guint8的取值范围为0到255(G_MAXUINT8)。

gint16 (guint16)

被设计为在所有平台上都为16位的有符号和无符号整型。gint16取值范围为-32768到32767(G_MININT16到G_MAXINT16),guint16的取值范围为0到65535(G_MAXUINT16)。

gint32 (guint32)

被 设计为在所有平台上都为32位的有符号和无符号整型。gint32取值范围为-2,147,483,648到 2,147,483,647(G_MININT32到G_MAXINT32),guint32的取值范围为0到 4,294,967,295(G_MAXUINT32)。

gint64 (guint64)

被设计为在所有平台上都为64位的有符号和无符号整型。gint64取值范围为-263次方到263-1(G_MININT64到G_MAXINT64),guint64的取值范围为0到2^64-1(G_MAXUINT64)。

glong (gulong)

和标准C的long(unsigned long)类型一致。glong的取值范围从G_MINLONG到G_MAXLONG。gulong的最大值为G_MAXULONG.

gpointer

一个定义为void的无类型指针。只是为了看上去比标准的void好看。

gshort(gushort)

和标准C的short(unsigned short)类型一致。glong的取值范围从G_MINSHORT到G_MAXSHORT。gushort的最大值为G_MAXUSHORT。

gsize(gssize)

无符号和有符号的32位整型。在许多数据结构中用来代表大小。gsize被定义为unsigned int,gssize被定义为signed int。

2、标准Glib宏

宏                                           描述

ABS(a)

返回a的绝对值。这个宏只是简单的返回去掉符号的负数,对正数不进行任何操作。

CLAMP(a,low,high)

确认a是否在low和high之间。如果a不再low和high之间,将会返回与low和high之间与a比较接近的那个。否则返回a。

G_DIR_SEPARATOR G_DIR_SEPARATOR_S

在UNIX系统中,目录用斜杠(/)来分隔,在Windows系统中,用的是反斜杠(),G_DIR_SEPARATOR以字符类型返回一个适当的分隔符,而G_DIR_SEPARATOR_S返回的是一个字符串。

GINT_TO_POINTER(i) GPOINTER_TO_INT§

将一个gpointer转换成一个整数,或将一个整数转换成一个gpointer。整数中只有32位将会被储存。你一定要避免对占用空间超过32位的整数使用这些宏。记住你不能在整数中储存指针,这些宏仅仅是允许你以指针的形式储存整数。

GSIZE_TO_POINTER(s) GPOINTER_TO_SIZE§

把gsize转换成gpointer或者把gpointer转换成gsize。如果想把gsize的值从指针转换回来,它事先必须已经通过GSIZE_TO_POINTER()被储存为指针,请参见GINT_TO_POINTER()。

GUINT_TO_POINTER(u) GPOINTER_TO_UINT§

把一个无符号整数转换成gpointer,或者把gpointer转换成无符号整数。如果想把整数从指针转换回来,它事先必须已经通过GUINT_TO_POINTER()被储存为指针,请参见GINT_TOOPOINTER()。

G_OS_WIN32 G_OS_BEOS G_OS_UNIX

这三个宏允许你定义只能运行在特定平台的代码。只有和用户使用的操作系统一致的那个宏会被定义,所以你可以用#ifdef GOS*来写只能用于用户的平台的代码。

G_STRUCT_MEMBER_P(struct_p, offset)

返回一个指向在结构体内偏移量为offset的成员的无类型指针,偏移量必须在struct_p的范围之内。

G_STRUCT_OFFSET(type, member)

返回一个成员在结构体内的偏移量。type指明结构体的类型。

MIN(a, b) MAX(a, b)

计算两个a和b中的最小值和最大值。

TRUE 和 FALSE

FALSE被定义为0,TRUE为FALSE的逻辑非。这两个值被gboolean所使用。

四、改造21点游戏

1、引入字符串类型

GString结构包含了三个成员:保存字符串当前状态的C字符串,除了结束符的字符串长度,和为字符串当前分配的内存数量。如果字符串增加到超出分配的内存长度,GString会自动为其分配更多内存。

    typedef struct

    {

        gchar *str;

        gsize len;

        gsize allocated_len;

    } GString;

        四、改造21点游戏 

1、引入字符串类型

GString结构包含了三个成员:保存字符串当前状态的C字符串,除了结束符的字符串长度,和为字符串当前分配的内存数量。如果字符串增加到超出分配的内存长度,GString会自动为其分配更多内存。

    typedef struct

    {

        gchar *str;

        gsize len;

        gsize allocated_len;

    } GString;

在玩家和电脑抽数后,仅显示本次抽到的数字,需要在每次抽取后显示所有的数字,使用Gstring完成含有多个数字的字符串的动态生成。创建一个新GString的一种方式是利用g_string_new(),使用g_string_append_printf(),它将附加格式化的字符串到GString的结尾,并保持当前内容不变。

dp@dp:~/gliblearn % cat 21dian.c

#include

#include

#include

//code:[email protected]

//date:2014-01-26

//未经作者书面许可,请勿用于任何用途

int main(int argc, char *argv[]){

setlocale(LC_ALL,"");

GString *man_list;

GString *comp_list;

man_list=g_string_new("玩家抽到的数字: ");

comp_list=g_string_new("电脑抽到的数字: ");

GRand *gamerand;

gchar gamename[10];

    g_print("您叫什么名字?\n");

scanf("%s",&gamename);

g_print(“欢迎您,%s,这里是21点游戏\n”,gamename);

setbuf(stdin,NULL);

gint key=0;

gint rndnumber;

gint man_number,comp_number;

gint man_count=0,comp_count=0;

gboolean man_end=FALSE,comp_end=FALSE;

gboolean gameover=FALSE;

gamerand = g_rand_new();

do{

if (!man_end){

g_print("%s,按Y/y键抽数字,按其它键表示不再抽数字!\n",gamename);

key=getchar();

getchar();

//玩家抽数字

if (key==‘y’||key==‘Y’){

rndnumber=g_rand_int_range(gamerand,1,11);

man_number=rndnumber;

man_count+=man_number;

g_string_append_printf(man_list,"%d ",man_number);

g_print("%s,您抽到的是:%d\n",gamename,man_number);

}else

{

g_print(“玩家放弃抽数!\n”,comp_number);

man_end=TRUE;

}

    }

//电脑抽数字

if (comp_count<=17){

rndnumber=g_rand_int_range(gamerand,1,11);

comp_number=rndnumber;

comp_count+=comp_number;

g_string_append_printf(comp_list,"%d ",comp_number);

g_print(“电脑抽到的是:%d\n”,comp_number);

}else

{

g_print(“电脑放弃抽数!\n”,comp_number);

comp_end=TRUE;

}

g_print("$$$$ 本 轮 结 束 , 双 方 明 细 本轮结束,双方明细 ,$$$$\n");

g_print("%s\n",man_list->str);

g_print("%s\n",comp_list->str);

if ((man_count>21 && comp_count>21)||(man_count<=21 && comp_count<=21 && man_count==comp_count && man_end &&comp_end)){

g_print(“平手,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

gameover=TRUE;

}

else if ((man_count>21 && comp_count<=21)||(man_count<21 && comp_count==21)) {

g_print(“电脑赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

gameover=TRUE;

}

else if ((man_count<=21 && comp_count>21) ||(man_count==21 && comp_count<21)) {

g_print(“玩家赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

gameover=TRUE;

}

else if (man_end && comp_end){

man_count>comp_count?g_print(“玩家赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count):g_print(“电脑赢了,电脑%d点,%s %d点\n”,comp_count,gamename,man_count);

     gameover=TRUE; 

}

else

{

g_print("\n$$$$ 电 脑 电脑%d点,%s %d点 $$$$\n",comp_count,gamename,man_count);

}

}while(!gameover);

g_string_free(man_list,TRUE);

g_string_free(comp_list,TRUE);

g_rand_free(gamerand);

return 0;

}

dp@dp:~/gliblearn % ./21dian

您叫什么名字?

joan

欢迎您,joan,这里是21点游戏

joan,按Y/y键抽数字,按其它键表示不再抽数字!

y

joan,您抽到的是:8

电脑抽到的是:8

$$$$ 本 轮 结 束 , 双 方 明 细 本轮结束,双方明细 ,$$$$

玩家抽到的数字: 8

电脑抽到的数字: 8

$$$$ 电 脑 8 点 , j o a n 8 点 电脑8点,joan 8点 8joan8$$$$

joan,按Y/y键抽数字,按其它键表示不再抽数字!

n

玩家放弃抽数!

电脑抽到的是:1

$$$$ 本 轮 结 束 , 双 方 明 细 本轮结束,双方明细 ,$$$$

玩家抽到的数字: 8

电脑抽到的数字: 8 1

$$$$ 电 脑 9 点 , j o a n 8 点 电脑9点,joan 8点 9joan8$$$$

电脑抽到的是:7

$$$$ 本 轮 结 束 , 双 方 明 细 本轮结束,双方明细 ,$$$$

玩家抽到的数字: 8

电脑抽到的数字: 8 1 7

$$$$ 电 脑 16 点 , j o a n 8 点 电脑16点,joan 8点 16joan8$$$$

电脑抽到的是:2

$$$$ 本 轮 结 束 , 双 方 明 细 本轮结束,双方明细 ,$$$$

玩家抽到的数字: 8

电脑抽到的数字: 8 1 7 2

$$$$ 电 脑 18 点 , j o a n 8 点 电脑18点,joan 8点 18joan8$$$$

电脑放弃抽数!

$$$$ 本 轮 结 束 , 双 方 明 细 本轮结束,双方明细 ,$$$$

玩家抽到的数字: 8

电脑抽到的数字: 8 1 7 2

电脑赢了,电脑18点,joan 8点

你可能感兴趣的:(设计与架构)