Vim配置

忙活了好几天,终于有点成果了嘻嘻,学习过程中最强烈的感觉就是Vim好好好强大...

一些常用的功能都已经配置OK,例如窗口管理,缓冲区管理,ctags、cscope插件提供的标签跳转,全能补全,自动补全,quickfix等

贴图如下:

.vimrc文件:

数组的不对称边界

 

/**
 * @file bsearch.c
 * @brief binary search,
 *        C Traps and Pitfalls, P132
 *        主题: 数组的不对称边界
 *        lower与higher是不对称边界的两头,即lower<=k<higher
 *        可以表示为[lower, higher)
 *        这样表示的效果:
 *        1. 取值范围的元素个数就是上界与下界之差
 *        2. 如果上界等于下界,那么取值范围为空
 *        3. 即使取值范围为空,上界也永远不可能小于下界
 *
 *        设mid = (lower+higher)/2
 *        若target小于下标为mid的元素,取higher=mid,表示mid是位于可能范围以外的最小下标
 *        若target大于下标为mid的元素,取lower=mid+1,表示mid+1是位于可能范围内的最小下标
 *        lower==higer的时候,表示可能范围为空,可判定target不存在
 *
 * @author simplyzhao
 * @version 0.0
 * @date 2009-05-05
 */


#include<stdio.h>
#include<stdlib.h>
/**
 * @brief 数组版本
 *
 * @param arr[]
 * @param length
 * @param target
 *
 * @return 返回指向目标元素的指针,不存在则返回NULL
 */

int *bsearch_arr(int arr[], int length, int target)
{
        int lower = 0;
        int higher = length;  /* 这里higher取的是length,而不是length-1 */
    int mid;

        while(lower < higher) {
                mid = (lower+higher)/2; /* 这里的除法运算可以替代为: (lower+higher)>>1, 当然前提是lower+higher非负 */
                if(arr[mid] > target)
                        higher = mid;
                else if(arr[mid] < target)
                        lower = mid+1;
                else
                        return arr+mid;
        }

        return NULL;
}

/**
 * @brief 指针版本
 *
 * @param arr
 * @param length
 * @param target
 *
 * @return
 */

int *bsearch_ptr(int *arr, int length, int target)
{
        int *lower = arr;
        /* 可以使用数组“溢界”元素的地址,这个地址可以用于赋值和比较,当然解引用肯定是非法的 */
        int *higher = arr+length;
        int *mid;

        while(lower < higher) {
                mid = lower + ((higher-lower) >> 1); /* 注意:这里指针不能进行相加运算 */
                if(*mid > target)
                        higher = mid;
                else if(*mid < target)
                        lower = mid+1;
                else
                        return mid;
        }

        return NULL;
}
 

 

 

可变参数的实现原理

 

/**
 * @brief 理解varargs.h的实现,虽然该头文件
 *        在GUN C库中已经被stdarg.h取代,但对于理解可变参数的实现
 *        以及参数传递机制还是非常有学习价值
 *
 *        参考 《C陷阱与缺陷》,附录
 * @date 2009-05-03
 */


#include<stdio.h>

typedef char *v_list;
#define v_dcl int v_alist;
#define v_start(list) list=(char *)&v_alist
#define v_end(list)
#define v_arg(list,mode) \
        ((mode *)(list+=sizeof(mode)))[-1]

/*
 * 假定:
 * 底层的C语言实现要求函数参数在内存中连续存储
 * 这样,但我们知道当前参数的地址,就能依次访问参数列表中的其他参
 */


void
test_arg(v_alist) v_dcl
{
    v_list ap;
        v_start(ap);

        char ch;
        printf("ap: %p\n", ap);
        /*
         * 陷阱
         * v_arg宏的第二个参数不能被指定为char, short, float
         * 因为char 和 short 参数将被转换为 int 类型, 而float 参数会被转换为 double
         */

        ch = v_arg(ap, int);
        printf("%c\n", ch);

        int i;
        printf("ap: %p\n", ap);
        i = v_arg(ap, int);
        printf("%d\n", i);

        double d;
        printf("ap: %p\n", ap);
        d = v_arg(ap, double);
        printf("%f\n", d);

        char *p;
        printf("ap: %p\n", ap);
        p = v_arg(ap, char *);
        printf("%s\n", p);

        v_end(ap);
}

int
main(int argc, char *argv[])
{
        char ch;
        int i;
        double d;
        char *p;
        ch = 'z';
        i = 1;
        d = 3.5;
        p = "simplyzhao";
        test_arg(ch, i, d, p);
        return 0;
}

 输出:

simplyzhao@Full-House:~$ gcc test.c
simplyzhao@Full-House:~$ ./a.out
ap: 0xbf8f8530
z
ap: 0xbf8f8534
1
ap: 0xbf8f8538
3.500000
ap: 0xbf8f8540
simplyzhao
 

ps.

发现stdarg.h头文件并不在/usr/include目录下,不知何解?

simplyzhao@Full-House:~$ locate stdarg.h
/usr/include/c++/4.3/tr1/stdarg.h
/usr/lib/gcc/i486-linux-gnu/4.3/include/stdarg.h
 

Vim 进阶学习

正所谓 ”磨刀不误砍柴工“

当初在Vim与Emacs之间选择了前者(话说当时我连它们是干嘛的都不知道就乱选了,可能就因为才斌用的是Emacs,我就选了Vim哈哈)

目前差不多已经用了半年,却还是只会使用用户手册里前几章的内容进行简单的移动和编辑,尽管一般写程序都已经使用Vim,不过可能只用到它千分之一的功能而已。

再不进阶学习下,就对不起这么强大的工具啦。

另外,昨天在网上找到了一个很不错的Vim教程,相当不错,记录在此:

easwy.com/blog/archives/advanced-vim-skills-catalog/

终于把APUE看完一遍

还是挺有成就感的,虽然只是把这本经典书看了一遍,书中的例子基本敲了一遍。

翻看之前的blog记录,在2月28日有一篇: 学习计划Unix-C,其中写着想看的几本关于Unix下C编程的书,原本打算是今年暑假看完的,没想到现在已经看的差不多了,还剩一本《C陷阱与缺陷》,目前正在看,很薄的一本书,都不敢看得太快,否则没几天又看完了嘻嘻。

当然,还仅限于把书看完的程度而已,与掌握相比还有相当大的距离。可以说,看完第一遍,只是对于一些基本的系统调用与函数有了感性的认识,真正想要掌握和灵活地运用,关键还是在于多实践,光看书却不实践,是没法真正提高水平的。

接下来,准备把APUE再仔细地翻看一遍,第一遍看的时候有很多地方有疑惑,对于某些章节特别是信号以及线程的内容还不能理解透彻,第二遍打算看得仔细点,速度放慢点,另外把每一章的课后习题也好好钻研钻研。

总之,继续努力吧,Fighting...

另外,要说大四有什么好的话,对于我来说,那就是有充足的时间来学习自己感兴趣的东西

我的大四,过得很充实...

ps.

前几天在写下载歌词的小程序时,突然发觉自己挺喜欢编程的呵呵。

想当初,从历史系转过来的时候,只是想着计算机系至少是个理科,并没有想到究竟自己喜不喜欢这个专业,现在看来,挺适合我的。

doxygen+VIM文档实用指南for C/C-liked Programmers

好文啊, 忍不住就又拷贝过来了呵呵

来源: blog.csdn.net/clarkZHUO/archive/2006/12/31/1471573.aspx

再次感谢原文作者,

 

摘要:

文档撰写是一项十分繁琐而且费力的工作,相信已经有很多人对此深感头痛。文档生成工具的出现最大限度地帮助程序员解决了这个问题,这些工具通常可以从程序源代码自动生成文档,大大方便了文档工作。这篇小东西主要介绍了如何用VIMdoxygen来快速生成注释,并用最少的额外劳动来完成专业水准的程序文档的过程。仅供参考,如有雷同,纯属巧合。 

关键字:

       doxygen vim doxygentoolkit chm dot lex CLanuageScanner

使用getopt()进行命令行处理

 

#include <unistd.h>
extern char *optarg;
// 初始化值为1, 下一次调用getopt时, 从optind存储的位置重新开始检查选项
extern int optind;
// 初始化值为1, 当opterr=0时, getopt不向stderr输出错误信息
extern int opterr;
// 当命令行选项字符不包括在optstring中或者选项缺少必要的参数时
// 该选项存储在optopt中,getopt返回'?'
extern int optopt;
                                   
int getopt(int argc, char * const argv[], const char *optstring);

 

getaddrinfo函数

 

今天在看完APUE第16章:网络IPC:套接字后,就开始编写书中的示例代码,结果出现了问题:

调用getaddrinfo函数时,返回错误:Servname not supported for ai_socktype,觉得很费解,就直接google之,发现下面这篇好文,不仅解决了问题,还使我更加理解了如何使用getaddrinfo来编写服务器/客户端程序

 

原文地址:blog.csdn.net/andyxie407/archive/2007/06/30/1672325.aspx

有这样一个C/S程序,server提供一个叫做ruptime的服务,功能是当有客户端连接时调用uptime程序,并将结果发送到client。可是现在的问题是,这个服务系统本来是没有的,所以调用getaddrinfo的时候会返回如下错误:

代码:
Servname not supported for ai_socktype

我觉得可能是需要编辑/etc/service文件把自己这个服务加进去.

 

个人认为,这个问题就是对getaddrinfo函数的应用和理解,下面帖子的内容基本上是对Advanced Programming in linux Environment这本书里的16-6等几个程序的解释,刚开始对getaddrinfo这个函数和编辑/etc/service等不了解,所会有以上的问题存在。下面是资料。

bumpy:~/tmp$ gcc a.c
bumpy:~/tmp$ ./a.out <==== 没有改/etc/services 前
getaddrinfo error: Servname not supported for ai_socktype
bumpy:~/tmp$ vi a.c
bumpy:~/tmp$ sudo vi /etc/services <==== 添加ruptimed 4000/tcp到合适的位置(你的服务里没有别的是4000吧)
bumpy:~/tmp$ ./a.out
OK

google code 与 svn

这几天试用了google code的项目托管功能,体验了subversion这个版本管理工具。

开始,还以为project hosting就是个简单的文件上传之类的服务呢...汗

"Project Hosting on Google Code provides a free collaborative development environment for open source projects. Each project comes with its own

member controls, Subversion repository, issue tracker, wiki pages, and downloads section. Our project hosting service is simple, fast, reliable, and

scalable, so that you can focus on your own open source development."

                                                                                                                                                                          -----Google 'support' project

主要是想记录下Subversion(svn)的使用方法,由于是第一次接触(其实,在Visual Studio里使用过类似的,不过是图形界面的),还是花了点时间来学习基本使用命令的,主要是参考svnbook:

需要理解的两个重要概念是:

  • 版本库
  • 工作拷贝

常用命令(客户端):

svn help (subcommand): 帮助

svn import: 导入数据到版本库

svn checkout: 签出,创建本地工作拷贝

svn update: 更新工作拷贝

svn commit: 提交

修改:

svn add

svn delete

svn copy

svn move

检验修改:

svn status

svn diff

svn revert: 取消修改

svn resolved: 解决冲突

 

建立mysql C开发环境

参考: feizf.blogbus.com/logs/30689586.html

命令:

#安装开发包

sudo apt-get install libmysqlclient15-dev

相关mysql头文件和库文件安装在/usr/include/mysql/和/usr/lib/mysql目录

编译操作数据库的C源文件命令是:

gcc demo.c  -I /usr/include/mysql -L /usr/lib/mysql  -lmysqlclient  -o demo

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

测试开发环境是否搭建好的代码:

 

#include<stdio.h>
#include<stdlib.h>
#include<mysql.h>

/*
 * compile command:
 * gcc test.c -I /usr/include/mysql -L /usr/lib/mysql -lmysqlclient -o test
 */

int main()
{
        MYSQL mysql;
        mysql_init(&mysql);
       
        return 0;
}