Archive for the Category » C / Erlang / Lua «

CN Erlounge III归来,收获颇丰

上周末去上海参加了CN Erlounge III的会,收获颇丰,见识了几位业内低调的高人,佩服佩服! 更让让我深知自己学识之浅薄,学海无涯,路漫漫!

继续学习和实践提高中,希望能尽快出些有价值的成果来!

此次上海之行,恰逢鄙人之生日,与几位老朋友相聚一堂,甚是欢心,加上Apple的生日也在这期间,可谓喜事连连,皆大欢喜,虽然天气冷了点儿,心里还是很热乎的!

Category: C / Erlang / Lua  Tags:  5 Comments

Joe Armstrong真的是天才

这么简洁漂亮的语法都能创造出来,真的服了,着迷啊着迷!

double([H|T]) -> [2*H|double(T)];
double([])    -> [].

> double([1,2,3,4]).
[2,4,6,8]

add_one([H|T]) -> [H+1|add_one(T)];
add_one([])    -> [].

map(F, [H|T]) -> [F(H)|map(F, T)];
map(F, [])    -> [].

double(L)  -> map(fun(X) -> 2*X end, L).
add_one(L) -> map(fun(X) -> 1 + X end, L).

闭关修炼

受到mryufeng/coderplay等牛人影响,痛下决心闭关修炼面向未来的 FP 技术, 无一中文书籍&文档,顺便考验考验自己的大学英语水平。

活到老、学到老!

用C语言操作MySQL数据库,进行连接、插入、修改、删除等操作

  很多人用到MySQL来开发一些项目,有时为了性能,我们会直接用C语言来开发相关的模块,尤其在我们的web应用中,虽然PHP、JSP等脚本均提供了MySQL的接口,但是显然直接使用C语言具有更好的安全性和性能,Michael以前用PHP开发的多个项目中就使用了C语言编写的这类接口,然后再编译到php里面,供php脚本直接使用,这方面的话题就不多说了,下面主要说一下在Linux下如何用C语言连接MySQL数据库,并且读取里面的数据返回,同时如何进行编译。

  这里的大部分代码参考了MySQL发行包里面的.c源文件,大家也可以去里面找找相关的代码,下面这段代码实现了连接到本地MySQL服务器上9tmd_bbs_utf8数据库,从数据表tbb_user中根据输入的userid取得该用户的用户名并打印输出到终端。

#if defined(_WIN32) || defined(_WIN64)  //为了支持windows平台上的编译
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "mysql.h"  //我的机器上该文件在/usr/local/include/mysql下
 
//定义数据库操作的宏,也可以不定义留着后面直接写进代码
#define SELECT_QUERY "select username from tbb_user where userid = %d"
 
int main(int argc, char **argv) //char **argv 相当于 char *argv[]
{
    
MYSQL mysql,*sock;    //定义数据库连接的句柄,它被用于几乎所有的MySQL函数
    
MYSQL_RES *res;       //查询结果集,结构类型
    
MYSQL_FIELD *fd ;     //包含字段信息的结构
    
MYSQL_ROW row ;       //存放一行查询结果的字符串数组
    
char  qbuf[160];      //存放查询sql语句字符串
    
    
if (argc != 2) {  //检查输入参数
        
fprintf(stderr,"usage : mysql_select <userid>\n\n");
        
exit(1);
    
}
    
    
mysql_init(&mysql);
    
if (!(sock = mysql_real_connect(&mysql,"localhost","dbuser","dbpwd","9tmd_bbs_utf8",0,NULL,0))) {
        
fprintf(stderr,"Couldn't connect to engine!\n%s\n\n",mysql_error(&mysql));
        
perror("");
        
exit(1);
    
}
    
    
sprintf(qbuf,SELECT_QUERY,atoi(argv[1]));
    
if(mysql_query(sock,qbuf)) {
        
fprintf(stderr,"Query failed (%s)\n",mysql_error(sock));
        
exit(1);
    
}
    
    
if (!(res=mysql_store_result(sock))) {
        
fprintf(stderr,"Couldn't get result from %s\n", mysql_error(sock));
        
exit(1);
    
}
    
    
printf("number of fields returned: %d\n",mysql_num_fields(res));
        
    
while (row = mysql_fetch_row(res)) {
        
printf("Ther userid #%d 's username is: %s\n", atoi(argv[1]),(((row[0]==NULL)&&(!strlen(row[0]))) ? "NULL" : row[0])) ;
        
puts( "query ok !\n" ) ;
    
}
    
    
mysql_free_result(res);
    
mysql_close(sock);
    
exit(0);
    
return 0;   //. 为了兼容大部分的编译器加入此行
}

编译的时候,使用下面的命令

gcc -o mysql_select ./mysql_select.c -I/usr/local/include/mysql -L/usr/local/lib/mysql -lmysqlclient (-lz) (-lm) 后面两个选项可选,根据您的环境情况

运行的时候,执行下面的命令

./mysql_select 1

将返回如下结果:

number of fields returned: 1
Ther userid #1 's username is: Michael
query ok !

上面的代码我想大部分都能看明白,不明白的可以参考一下MySQL提供的有关C语言API部分文档,各个函数都有详细说明,有时间我整理一份常用的API说明出来。

C/C++中内存管理参考

Show All   1 2 3

  程序员们经常编写内存管理程序,往往提心吊胆。如果不想触雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本文的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。

1、内存分配方式

内存分配方式有三种:

(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

2、常见的内存错误及其对策

  发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户怒气冲冲地把你找来,程序却没有发生任何问题,你一走,错误又发作了。 常见的内存错误及其对策如下:

* 内存分配未成功,却使用了它。

  编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

* 内存分配虽然成功,但是尚未初始化就引用它。

  犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。

* 内存分配成功并且已经初始化,但操作越过了内存的边界。

例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

* 忘记了释放内存,造成内存泄露。

  含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。

  动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。

* 释放了内存却继续使用它。

有三种情况:

(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。

(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。

(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。

【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。

【规则2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

【规则3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。

【规则4】动态内存的申请与释放必须配对,防止内存泄漏。

【规则5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。

3、指针与数组的对比

  C++/C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。

  数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。

  指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。

下面以字符串为例比较指针与数组的特性。

3.1 修改内容

示例3-1中,字符数组a的容量是6个字符,其内容为hello。a的内容可以改变,如a[0]= ‘X’。指针p指向常量字符串“world”(位于静态存储区,内容为world),常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句 p[0]= ‘X’有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误。

char a[] = “hello”;
a[0] = ‘X’;
cout << a << endl;
char *p = “world”; // 注意p指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误
cout << p << endl;

示例3.1 修改数组和指针的内容

3.2 内容复制与比较

  不能对数组名进行直接复制与比较。示例7-3-2中,若想把数组a的内容复制给数组b,不能用语句 b = a ,否则将产生编译错误。应该用标准库函数strcpy进行复制。同理,比较b和a的内容是否相同,不能用if(b==a) 来判断,应该用标准库函数strcmp进行比较。

  语句p = a 并不能把a的内容复制指针p,而是把a的地址赋给了p。要想复制a的内容,可以先用库函数malloc为p申请一块容量为strlen(a)+1个字符的内存,再用strcpy进行字符串复制。同理,语句if(p==a) 比较的不是内容而是地址,应该用库函数strcmp来比较。

// 数组…
char a[] = "hello";
char b[10];
strcpy(b, a); // 不能用 b = a;
if(strcmp(b, a) == 0) // 不能用 if (b == a)

// 指针…
int len = strlen(a);
char *p = (char *)malloc(sizeof(char)*(len+1));
strcpy(p,a); // 不要用 p = a;
if(strcmp(p, a) == 0) // 不要用 if (p == a)

示例3.2 数组和指针的内容复制与比较

3.3 计算内存容量

  用运算符sizeof可以计算出数组的容量(字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了’’)。指针p指向a,但是 sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。 C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。

char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12字节
cout<< sizeof(p) << endl; // 4字节

示例3.3(a) 计算数组和指针的内存容量

void Func(char a[100])
{
 
cout<< sizeof(a) << endl; // 4字节而不是100字节
}

示例3.3(b) 数组退化为指针

Show All   1 2 3

使用JScript.encode进行网页的加密与解密

我们常常看到类似新浪上面的视频播放页面源文件是一堆乱码,实际上是经过JScript加密过的代码,这样可以防止普通用户轻易的找到视频源文件地址,从而盗链,下面把JScript加密解密的方法整理了一下:

more »

写给C语言初学者的话

我一个好朋友,Linux C方面的高手,有很多经验可以和大家分享,下面是他的一些经验,对于C语言初学者来说,应该会有不少帮助的。

学习C语言不要心急,要循序渐进,须知欲速则不达的道理。千万不要盲目的写大量的代码,这样做只会堆出大量的低档次代码,同时使你形成不好的代码习惯。先买本基础的教材来看看,使得对C语言有个初步的认识,其实我现在手头上还放着《The C Programming Language》和《C程序设计(第二版)》(大学教材)呢,有些时候我还会为了一些基本性的概念来翻翻看呢。
more »

在UltraEdit的查找和替换中使用正则表达式

很多朋友都用过或者正在用UltraEdit,这个编辑器陪伴我也好几年了,从很多地方影响着我写代码的快捷键习惯,Ultraedit提供了非常丰富的编辑功能,其中非常重要的查找和替换功能一定大家都用过,Ultraedit提供的查找替换功能非常方便和强大,可以在单独文件里面查找替换,也可以在多个文件、多个目录里面进行查找替换。而我们在使用这些查找替换功能的时候,一般都是针对某个字符串进行,前两天我要对一个目录下(包含子目录)所有的html文件中某一段代码进行查找替换,一下子不知道怎么操作了,由于长期写程序用到正则表达式,于是猜想具备如此强大功能的Ultraedit一定也有这样类似的匹配功能,于是点击Help一看,果然不出所料,Ultraedit支持基本的正则表达式匹配查找和替换功能,这能满足我们几乎全部的需要了。
more »

网页中插入视频播放代码全集

我们经常要在网页中插入各种在线视频格式的播放器,可以让用户访问的时候直接欣赏视频,这里收集整理了大部分的视频格式播放代码。

1.avi格式

代码片断如下:

<object id="video" width="400" height="200" border="0" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA">
<param name="ShowDisplay" value="0"/>
<param name="ShowControls" value="1"/>
<param name="AutoStart" value="1"/>
<param name="AutoRewind" value="0"/>
<param name="PlayCount" value="0"/>
<param name="Appearance value="0 value="""/>
<param name=
"BorderStyle value="0 value="""/>
<param name="MovieWindowHeight" value="240"/>
<param name="MovieWindowWidth" value="320"/>
<param name="FileName" value="/Mbar.avi"/>
<embed width="400" height="200" border="0" showdisplay="0" showcontrols="1" autostart="1" autorewind="0" playcount="0" moviewindowheight="240" moviewindowwidth="320" filename="/Mbar.avi" src="Mbar.avi"/>
 
</object>

more »

Flash 视频(FLV)编码,转换,录制,播放方案参考

今天看到Danger`s的博客,看到了这个信息,非常的有用啊,收藏了.

客户端编码工具(Client-Side-FLV-Encoding)
场景:拿到一个 MPG 或 AVI 文件,打算在个人电脑上转换成FLV.
1,Sorenson Squeeze
2,Riva FLV Encoder
3,Turbine Video Encoder
4,Flix Exporter
5,Flash 自带的Flash Video Exporter
更多…
more »