在vim中使用正则表达式

元字符 说明
. 匹配任意一个字符
[abc] 匹配方括号中的任意一个字符。可以使用-表示字符范围,如[a-z0-9]匹配小写字母和阿拉伯数字。
[^abc] 在方括号内开头使用^符号,表示匹配除方括号中字符之外的任意字符。
\d 匹配数字,等同于[0-9]。
\D 匹配非数字,等同于[^0-9]。
\x 匹配十六进制数字,等同于[0-9A-Fa-f]。
\X 匹配非十六进制数字,等同于[^0-9A-Fa-f]。
\w 匹配单词字母,等同于[0-9A-Za-z]。
\W 匹配非单词字母,等同于[^0-9A-Za-z
]。
\t 匹配<TAB>字符。
\s 匹配空白字符,等同于[ /t]。
\S 匹配非空白字符,等同于[^ /t]。
\a 所有的字母字符. 等同于[a-zA-Z]
\l 小写字母 [a-z]
\L 非小写字母 [^a-z]
\u 大写字母 [A-Z]
\U 非大写字母 [^A-Z]

表示数量的元字符
元字符 说明

  • 匹配0-任意个
    + 匹配1-任意个
    \? 匹配0-1个
    {n,m} 匹配n-m个
    {n} 匹配n个
    {n,} 匹配n-任意个
    {,m} 匹配0-m个
    _. 匹配包含换行在内的所有字符
    {-} 表示前一个字符可出现零次或多次,但在整个正则表达式可以匹配成功的前提下,匹配的字符数越少越好
    \= 匹配一个可有可无的项
    _s 匹配空格或断行
    _[]

元字符 说明
* 匹配 * 字符。
. 匹配 . 字符。
\/ 匹配 / 字符。
\/ 匹配 / 字符。
[ 匹配 [ 字符。

表示位置的符号
元字符 说明
$ 匹配行尾
^ 匹配行首
\< 匹配单词词首
\> 匹配单词词尾

替换变量
在正规表达式中使用 ( 和 ) 符号括起正规表达式,即可在后面使用\1、\2等变量来访问 ( 和 ) 中的内容。

懒惰模式
{-n,m} 与{n,m}一样,尽可能少次数地重复
{-} 匹配它前面的项一次或0次, 尽可能地少
| “或”操作符
\& 并列

函数式
:s/替换字符串/\=函数式
在函数式中可以使用 submatch(1)、submatch(2) 等来引用 \1、\2 等的内容,而submatch(0)可以引用匹配的整个内容。

与Perl正则表达式的区别 ?
元字符的区别
Vim语法 Perl语法 含义
+ + 1-任意个
\? ? 0-1个
{n,m} {n,m} n-m个
(和) (和) 分组

在vim下使用DoxygenToolkit进行自动注释

doxygen是一个文档生成器,其工作机制是利用注释中的有效信息来自动生成文档。而DoxygenToolkit是vim下一款能够自动生成doxygen可以识别的注释的插件。
它会根据配置自动生成注释,主要是license注释、文件注释、函数及类注释。
下载地址:http://www.vim.org/scripts/script.php?script_id=987

修改.vimrc的配置,加入自己对Doxygen的配置
let g:DoxygenToolkit_authorName=”longchangjin <admin@longchangjin.cn>”
let g:DoxygenToolkit_briefTag_funcName=”yes”
let g:doxygen_enhanced_color=1

运行vim 在命令行输入命令即可
DoxAuthor:将文件名,作者,时间等
DoxLic: license注释
Dox: 函数及类注释

也可做一个按键映射,就不用每次都输入命令了。

如果想自定义注释信息,可以修改DoxygenToolkit.vim文件。

VIM配对符号(surrouding)处理插件

在写程序时有许多的配对符号如:(), [], {}, “”, ‘’。vim-surround就是一款插件可以快速处理这些配对符号的。
下载地址:https://github.com/tpope/vim-surround

下载安装好后就可以使用了,下面是一个示例:

“Hello world!” 按下 cs”‘ 后变为 ‘Hello world!’
再按下 cs’<q>变为 <q>Hello world!</q>
再按下 cst” 变为 “Hello world!”
再按下 ds” 则删除掉两端的引号,变为 Hello world!
现在将光标移到“”Hello”上,按下 ysiw] 变为 [Hello] world!

surround常用快捷键:
Normal mode
ds - 删除配对符号
cs - 修改配对符号
ys - 增加配对符号
yss - 对该行增加配对符号

Visual mode
S - 增加配对符号,并新增一行

Insert mode
<CTRL-s> - 增加配对
<CTRL-s><CTRL-s> - 增加配对符号并新增一行
<CTRL-g>s - 同<CTRL-s>
<CTRL-g>S - 同<CTRL-s><CTRL-s>

pentadactyl使用笔记

pentadactyl是firefox下的一款vim按键的插件。对于习惯了vim的人来说这个是非常方便的。

pentadactyl的默认按键跟vim差不多,而且也可以自行修改。 pentadactyl的配置文件在windows下是_pentadactylrc,在linux下是.pentadactylrc。如果不存在可以在firefox直接执行命令:mkp,就会生成~/.pentadactyl目录和一个空的~/.pentadactylrc文件。

然后就可以直接编辑这个文件了,编辑完成后再重启一下firefox即可。以下是我在网上找到的一些配置内容,仅供参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"1.0
loadplugins '\.(js|penta)$'
group user

" vim: set ft=pentadactyl:

map J <C-d>
map K <C-u>
" 修改Ctrl快捷键
noremap <C-c> <C-v><C-c>
noremap <C-a> <C-v><C-a>
cnoremap <C-c> <C-v><C-c>
cnoremap <C-v> <C-v><C-v>
cnoremap <C-x> <C-v><C-x>
inoremap <C-a> <C-v><C-a>
inoremap <C-c> <C-v><C-c>
inoremap <C-v> <C-v><C-v>
inoremap <C-x> <C-v><C-x>
inoremap <C-z> <C-v><C-z>
inoremap <C-y> <C-v><C-y>

" 在Gmail和Greader中屏蔽Vimperator
autocmd LocationChange .* :js modes.passAllKeys = /mail\.google\.com/.test(buffer.URL) || /google\.com\/reader\//.test(buffer.URL)

" 在有无菜单、地址栏之间切换:
map <C-Up> :se go=mnT<CR>
map <C-Down> :se go=s<CR>:

使用VIM管理git

之前看到在emacs下有管理git的插件,于是就想在vim下也有类似的没。网上搜了下,找到了Git-Vim,可以在VIM下管理git。
项目地址为: http://github.com/motemen/git-vim

安装了之后就可以直接在vim里输入命令管理git了,如:GitStatus就是git status,快捷键是<Leader>gs。(<Leader>默认为\,你也可以自己修改)

更多的用法可以看它的README

Bash常用快捷键

编辑命令

Ctrl + a :移到命令行首
Ctrl + e :移到命令行尾
Ctrl + f :按字符前移(右向)
Ctrl + b :按字符后移(左向)
Alt + f :按单词前移(右向)
Alt + b :按单词后移(左向)
Ctrl + xx:在命令行首和光标之间移动
Ctrl + u :从光标处删除至命令行首
Ctrl + k :从光标处删除至命令行尾
Ctrl + w :从光标处删除至字首
Alt + d :从光标处删除至字尾
Ctrl + d :删除光标处的字符
Ctrl + h :删除光标前的字符
Ctrl + y :粘贴至光标后
Alt + c :从光标处更改为首字母大写的单词
Alt + u :从光标处更改为全部大写的单词
Alt + l :从光标处更改为全部小写的单词
Ctrl + t :交换光标处和之前的字符
Alt + t :交换光标处和之前的单词
Alt + Backspace:与 Ctrl + w 相同类似,分隔符有些差别 [感谢 rezilla 指正]

重新执行命令

Ctrl + r:逆向搜索命令历史
Ctrl + g:从历史搜索模式退出
Ctrl + p:历史中的上一条命令
Ctrl + n:历史中的下一条命令
Alt + .:使用上一条命令的最后一个参数

控制命令

Ctrl + l:清屏
Ctrl + o:执行当前命令,并选择上一条命令
Ctrl + s:阻止屏幕输出
Ctrl + q:允许屏幕输出
Ctrl + c:终止命令
Ctrl + z:挂起命令

Bang (!) 命令

!!:执行上一条命令
!blah:执行最近的以 blah 开头的命令,如 !ls
!blah:p:仅打印输出,而不执行
!$:上一条命令的最后一个参数,与 Alt + . 相同
!$:p:打印输出 !$ 的内容
!*:上一条命令的所有参数
!*:p:打印输出 !* 的内容
^blah:删除上一条命令中的 blah
^blah^foo:将上一条命令中的 blah 替换为 foo
^blah^foo^:将上一条命令中所有的 blah 都替换为 foo

以上介绍的大多数 Bash 快捷键仅当在 emacs 编辑模式时有效,若你将 Bash 配置为 vi 编辑模式,那将遵循 vi 的按键绑定。通过 set -o emacs 将Bash设置为emacs模式,通过set -o vi 奖Bash设置为vi模式。Bash 默认为 emacs 编辑模式。
更多可以参考以下网址:
http://www.bigsmoke.us/readline/shortcuts
http://www.huangwei.me/bash_emacs.html

firefox全键盘操作:Pentadactyl

今天在网上淘到了一个很好的软件,Pentadactyl。

Pentadactyl是Vimperator的一个分支 。Vimperator 是让 Firefox 拥有模式、纯键盘操作、等 Vim 风格的强大扩展。

插件下载地址:https://addons.mozilla.org/en-US/firefox/addon/pentadactyl/

安装完后就可以像操作vim一样使用firefox了,这对于熟悉vim的人来说很方便,基本上不用再使用鼠标了。

基本的操作有
open:打开网页
tabopen:在新标签中打开网页
d:关闭当前标签
u:撤消关闭标签
y:复制当前网址
p:打开复制的网址
gt:切换标签

…………

更多的操作可以使用F1来看帮助。

[转载]GObject 学习笔记:GObject 的子类继承

在文档 [1] 中,我们构造了一个 KbBibtex 类,其构造过程看似挺复杂,但实际上只需要动手尝试一下,即可明白 GObject 子类化的各项步骤的意义与作用。许多事物之所以被认为复杂,是因为大家在观望。

本文沿用文档 [1] 中的那个 KbBibtex 示例,学习如何对其进行子类化,构造新类,即面向对象程序设计方法中类的继承。

文献有很多种类

写过论文的人都知道,参考文献的形式有许多种类,例如期刊论文、技术报告、专著等,并非所有的文献格式都能表示文档 [1] 所给出的 KbBibtex 对象属性,即:

1
2
3
4
5
6
7
typedef struct _KbBibtexPrivate KbBibtexPrivate;
struct _KbBibtexPrivate {
GString *title;
GString *author;
GString *publisher;
guint year;
};

对于期刊论文而言,也许我们期望的数据结构是:

1
2
3
4
5
6
7
8
9
10
11
typedef struct _KbBibtexPrivate KbBibtexPrivate;
struct _KbBibtexPrivate {
GString *title;
GString *author;
GString *journal;
GString *volume;
GString *number;
GString *pages;
guint year;
GString *publisher;
};

对于技术报告,需求又要变成:

1
2
3
4
5
6
7
typedef struct _KbBibtexPrivate KbBibtexPrivate;
struct _KbBibtexPrivate {
GString *title;
GString *author;
GString *institution;
guint year;
};

这样的变化非常之多。因此,设计一个“万能”的 KbBibtex 类,使之可以表示任何文献类型,看上去会很美好。

类的继承

因为期刊论文这种对象只比文档 [1] 中的 KbBibtex 对象多出 4 个属性,即 journal、volume、number、pages,其他属性皆与 KbBibtex 对象相同。

在程序猿的职业生涯中也许不断听到这样的警告:Don’t Repeat Yourself(不要重复)!所以面向对象程序设计方法会告诉我们,既然 KbBibtex 对象已经拥有了一部分期刊论文对象所需要的属性,后者与前者都属于 KbBibtex 类(因为它们都是文献类型),那么只需设计一个期刊论文类,让它可以继承 KbBibtex 类的所以所拥有的一切,那么就可以不用 DRY 了。

那么怎么来实现?和 GObject 子类化过程相似,只需建立一个 kb-article.h 头文件,与继承相关的代码如下:

1
2
3
4
5
6
7
8
9
10
11
#include "kb-bibtex.h"

typedef struct _KbArticle KbArticle;
struct _KbArticle {
KbBibtex parent;
};

typedef struct _KbArticleClass KbArticleClass;
struct _KbArticleClass {
KbBibtexClass parent_class;
};

然后,再建立一个 kb-article.c 源文件,其中与继承相关的代码如下:

1
G_DEFINE_TYPE (KbArticle, kb_article, KB_TYPE_BIBTEX);

另外,KbBibtex 对象的 kb_bibtex_printf 方法也需要被 KbArticle 对象继承,这只需在 kb_article_printf 函数中调用 kb_bibtex_printf 即可实现,例如:

1
2
3
4
5
6
7
8
void
kb_article_printf (KbArticle *self)
{
kb_bibtex_printf (&self->parent);

/* 剩下代码是 KbArticle 对象的 kb_article_printf 方法的具体实现 */
... ...
}

当然,kb-article.h 和 kb-article.c 中剩余代码需要类似文档 [1] 中实现 KbBibtex 类那样去实现 KbArticle 类。这部分代码,我希望你能动手去尝试一下。下面,我仅给出测试 KbArticle 类的 main.c 源文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "kb-article.h"

int
main (void)
{
g_type_init ();

KbArticle *entry = g_object_new (KB_TYPE_ARTICLE,
"title", "Breaking paragraphs into lines",
"author", "Knuth, D.E. and Plass, M.F.",
"publisher", "Wiley Online Library",
"journal", "Software: Practice and Experience",
"volume", "11",
"number", "11",
"year", 1981,
"pages", "1119-1184",
NULL);
kb_article_printf (entry);

g_object_unref (entry);
return 0;
}

测试结果表明,一切尽在掌握之中:

1
2
3
4
5
6
7
8
9
$ ./test
Title: Breaking paragraphs into lines
Author: Knuth, D.E. and Plass, M.F.
Publisher: Wiley Online Library
Year: 1981
Journal: Software: Practice and Experience
Volume: 11
Number: 11
Pages: 1119-1184

继承真的很美好?

通过类的继承来实现一部分的代码复用真的是很惬意。但是,《C 专家编程》一书的作者却不这么认为,为了说明类的继承通常很难解决现实问题,他运用了一个比喻,将程序比作一本书,并将程序库比作一个图书馆。当你基于一个程序库去写你个人的程序之时,好比你在利用图书馆中的藏书去写你个人的书,显然你不可能很轻松的在那些藏书中复印一部分拼凑出一本书。

就本文开头所举的例子而言,就无法通过继承文档 [1] 所设计的 KbBibtex 类来建立技术报告类,因为技术报告对象是没有 publisher 属性的。

也许你会说,那是 KbBibtex 类设计的太烂了。嗯,我承认这一点,但是你不可能要求别人在设计程序库时候知道你想要什么,就像你不能去抱怨为什么图书馆里的藏书怎么不是为你写书而准备的一样。

基类设计的失误,对于它的所有子类是一场巨大的灾难。要避免这种灾难,还是认真考虑自己所要解决的问题吧。其实很多问题都可以不需要使用继承便可以很好的解决,还有许多问题不需要继承很多的层次也可以很好的解决。

对于本文的问题,不采用继承的实现会更好。比如我们可以这样来改造 KbBibtex 类:

将 Bibtex 文献所有格式的属性都设为 KbBibtex 的类属性
为 Bibtex 对象拥有一个链表或数组之类的线性表容器,或者效率更高的 Hash 表容器(GLib 库均已提供),容器的第一个单元存储 Bibtex 对象对应的文献类型,其他单元则存储文献的属性。
在 kb_bibtex_set_property 与 kb_bibtex_get_property 函数中,实现 Bibtex 类属性与 Bibtex 对象属性的数据交换。

仅此而已。

如果说继承是美好的,那么平坦一些会更美好。如果你不愿意选择平坦,那么可以选择接口(Interface),这是下一篇文档的主题。

~ End ~

原文出处:http://garfileo.is-programmer.com

[转载]GObject 学习笔记:温故而知新

也许很多人将孔子所说的“温故而知新”理解为:温习学过的知识,从中获得新的领悟。但是,我更倾向于另一种解释:温习学过的知识,继续学习新的知识。本文借助一个更加平易和现实的示例用以温习文档 [1-3] 中的 GObject 知识,并进一步学习类与对象的方法。

Bibtex 文献类的设计,代号Kill Bill

这个才是本文的主题。我们将此次行动(或者称为项目也可)命名为“Kill Bill”,缩写“Kb”,其中并无深意,只是因为我正在看这部电影。

1. 类的声明

建立 kb-bibtex.h 头文件,以 GObject 类作为基类,声明 KbBibtex 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef KB_BIBTEX_H
#define KB_BIBTEX_H

#include <glib-object.h>

#define KB_TYPE_BIBTEX (kb_bibtex_get_type ())

#define KB_BIBTEX(object) \
G_TYPE_CHECK_INSTANCE_CAST ((object), KB_TYPE_BIBTEX, KbBibtex)

typedef struct _KbBibtex KbBibtex;
struct _KbBibtex {
GObject parent;
};

typedef struct _KbBibtexClass KbBibtexClass;
struct _KbBibtexClass {
GObjectClass parent_class;
};

GType kb_bibtex_get_type (void);

#endif

2. 类型注册

建立 kb-bibtex.c 源文件,对 KbBibtex 类进行定义,首先向 GObject 库的类型系统注册 KbBibtex 类型,使之成为 GObject 库认可的一类公民:

1
2
3
#include "kb-bibtex.h"

G_DEFINE_TYPE (KbBibtex, kb_bibtex, G_TYPE_OBJECT);

3. 对象的私有属性

在此,必须要澄清两个概念,它们在文档 [1-3] 中的描述有些混淆:

首先是对象属性,它指代隶属于实例结构体的数据,文档 [2] 主要讲述的是对象属性的隐藏。
其次是类属性,它指代隶属于类结构体的数据,可被所有的对象所共享,在文档 [3] 中我们利用了这一点,实现了通过类属性来访问对象属性。

下面定义 KbBibtex 对象的私有属性:

1
2
3
4
5
6
7
8
9
10
#define KB_BIBTEX_GET_PRIVATE(object) (\
G_TYPE_INSTANCE_GET_PRIVATE ((object), KB_TYPE_BIBTEX, KbBibtexPrivate))

typedef struct _KbBibtexPrivate KbBibtexPrivate;
struct _KbBibtexPrivate {
GString *title;
GString *author;
GString *publisher;
guint year;
};

4. 类结构体与实例结构体的构造函数(初始化函数)

在 KbBibtex 类结构体构造函数中安装对象的私有属性:

1
2
3
4
5
6
static void
kb_bibtex_class_init (KbBibtexClass *klass)
{
g_type_class_add_private (klass,
sizeof (KbBibtexPrivate));
}

kb_bibtex_class_init 参数名之所以使用 klass 而不是 class,是因为 class 是 c++ 语言的关键字,如果使用 class,那么 KbBibtex 类如是被 C++ 程序调用,那么程序编译时就杯具了。

KbBibtex 实例结构体的构造函数则什么也不做:

1
2
3
4
static void
kb_bibtex_init (KbBibtex *self)
{
}

因为我们打算采用文档 [3] 中的方式,通过类属性来访问对象属性。
5. 对象私有属性的外部访问

首先要实现类属性与对象属性之间的映射,即 kb_bibtex_set_property 与 kb_bibtex_get_property 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
static void
kb_bibtex_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
KbBibtex *self = KB_BIBTEX (object);
KbBibtexPrivate *priv = KB_BIBTEX_GET_PRIVATE (self);

switch (property_id) {
case PROPERTY_TITLE:
if (priv->title)
g_string_free (priv->title, TRUE);
priv->title = g_string_new (g_value_get_string (value));
break;
case PROPERTY_AUTHOR:
if (priv->author)
g_string_free (priv->author, TRUE);
priv->author = g_string_new (g_value_get_string (value));
break;
case PROPERTY_PUBLISHER:
if (priv->publisher)
g_string_free (priv->publisher, TRUE);
priv->publisher = g_string_new (g_value_get_string (value));
break;
case PROPERTY_YEAR:
priv->year = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}

static void
kb_bibtex_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
KbBibtex *self = KB_BIBTEX (object);
KbBibtexPrivate *priv = KB_BIBTEX_GET_PRIVATE (self);
GString *similar = NULL;

switch (property_id) {
case PROPERTY_TITLE:
g_value_set_string (value, priv->title->str);
break;
case PROPERTY_AUTHOR:
g_value_set_string (value, priv->author->str);
break;
case PROPERTY_PUBLISHER:
g_value_set_string (value, priv->publisher->str);
break;
case PROPERTY_YEAR:
g_value_set_uint (value, priv->year);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}

为了是上述代码能够工作,需要在 kb-bibtex.c 文件中定义 KbBibtex 各个类属性的 ID:

1
2
3
4
5
6
7
8
enum PROPERTY_BIBTEX {
PROPERTY_0,
PROPERTY_TITLE,
PROPERTY_AUTHOR,
PROPERTY_PUBLISHER,
PROPERTY_YEAR,
N_PROPERTIES
};

注意,enum 类型中,第一个成员 PROPERTY_0 仅仅是个占位符,它不会被使用,而最后一个成员 N_PROPERTIES 则用于表示类属性的个数,它在向类中安装属性的时候可以用到,详见下文。

6. 类属性的构造与安装

一旦完成了 KbBibtex 类属性与 KbBibtex 对象属性之间的映射,即 kb_bibtex_set_property 与 kb_bibtex_get_property 函数,那么便可以在 KbBibtex 类结构体构造函数中使用 GObject 类的 setter 与 getter 指针指向它们:

1
2
3
4
5
6
7
8
9
static void
kb_bibtex_class_init (KbBibtexClass *klass)
{
g_type_class_add_private (klass, sizeof (KbBibtexPrivate));

GObjectClass *base_class = G_OBJECT_CLASS (klass);
base_class->set_property = kb_bibtex_set_property;
base_class->get_property = kb_bibtex_get_property;
/* 未完 */

然后,构造类属性,与文档 [3] 有所区别,本文采用的是 ParamSpec 类型的指针数组,一遍在类属性构造完毕后,使用 g_object_class_install_properties 函数一并安装到类结构体中,而不是像文档 [3] 那样使用 g_object_class_install_property 函数一个一个的安装。

类属性的构造代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* 接上面的代码 */
GParamSpec *properties[N_PROPERTIES] = {NULL,};
properties[PROPERTY_TITLE] =
g_param_spec_string ("title",
"Title",
"Bibliography title",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_AUTHOR] =
g_param_spec_string ("author",
"Author",
"Bibliography author",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_PUBLISHER] =
g_param_spec_string ("publisher",
"Publisher",
"Bibliography Publisher",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_YEAR] =
g_param_spec_uint ("year",
"Year",
"Bibliography year",
0,
G_MAXUINT,
0,
G_PARAM_READWRITE);
/* 未完 */

最后,安装类属性:

1
2
3
/* 接上面代码 */
g_object_class_install_properties (base_class, N_PROPERTIES, properties);
}

使用 KbBibtex 类

建立 main.c 源文件,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "kb-bibtex.h"

int
main (void)
{
g_type_init ();

KbBibtex *entry = g_object_new (KB_TYPE_BIBTEX,
"title", "The {\\TeX}Book",
"author", "Knuth, D. E.",
"publisher", "Addison-Wesley Professional",
"year", 1984,
NULL);

gchar *title, *author, *publisher;
guint year;

g_object_get (G_OBJECT (entry),
"title", &title,
"author", &author,
"publisher", &publisher,
"year", &year,
NULL);

g_printf (" Title: %s\n"
" Author: %s\n"
"Publisher: %s\n"
" Year: %d\n", title, author, publisher, year);

g_free (title);
g_free (author);
g_free (publisher);

g_object_unref (entry);
return 0;
}

编译这个程序的命令为:
$ gcc $(pkg-config –cflags –libs gobject-2.0) kb-bibtex.c main.c -o test
程序运行结果:
$ ./test
Title: The {\TeX}Book
Author: Knuth, D. E.
Publisher: Addison-Wesley Professional
Year: 1984

为类和对象添加方法

在面向对象程序设计方法中,类和对象皆由“属性”与“方法“构成。文档 [1-3] 所讲的均是基于 GObject 子类化的数据抽象与封装,而未有涉及到类和对象的方法。其实,这样说并不正确,因为我们已经接触到了 GObject 子类的类结构体与实例结构体的构造函数,它们分别是类的方法和对象的方法。

类的方法,形式如下:

返回值
函数名 (参数, …)
{

}

对象的方法,形式如下:

返回值
函数名 (参数, …)
{

}

#@¥%……开玩笑呢吧?这两种方法有什么区别?它们不就是普通的 C 函数么?

嗯,你以为呢?就是普通的 C 函数。

下面为 KbBibtex 类增加一个对象方法,这个函数的功能是可以在终端输出文献信息。

首先,在 kb-bibtex.h 头文件的底部增加函数声明:

1
2
/* 对象的方法 */
void kb_bibtex_printf (KbBibtex *self);

然后在 kb-bibtex.c 源文件中实现该函数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void
kb_bibtex_printf (KbBibtex *self)
{
gchar *title, *author, *publisher;
guint year;

g_object_get (G_OBJECT (self),
"title", &title,
"author", &author,
"publisher", &publisher,
"year", &year,
NULL);

g_printf (" Title: %s\n"
" Author: %s\n"
"Publisher: %s\n"
" Year: %d\n", title, author, publisher, year);

g_free (title);
g_free (author);
g_free (publisher);
}

这样,main.c 源文件便可以被简化为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "kb-bibtex.h"

int
main (void)
{
g_type_init ();

KbBibtex *entry = g_object_new (KB_TYPE_BIBTEX,
"title", "The {\\TeX}Book",
"author", "Knuth, D. E.",
"publisher", "Addison-Wesley Professional",
"year", 1984,
NULL);

kb_bibtex_printf (entry);

g_object_unref (entry);
return 0;
}

~ End ~

原文出处:http://garfileo.is-programmer.com