用C写的一个简易JSON Parser
初来乍到的一学期实在是无聊,于是在百团大战中加了计算机协会,就认识了几个计算机和软件专业的人。看见一软件同学在空间上转发的C语言期末项目,顿时生了兴趣。代码是春节期间写完的,可惜这个博客被搁置了太久,现在把代码贴上来,也不算过分吧。
作业的具体内容是:老师给定一个头文件 json.h ,包含了 json 数据结构的定义以及一些相关函数的声明,任务就是实现这些函数,最后提交通过学校的自动化测试。我不是软件的学生,自然没有这个权利,不过手工检验了一下,貌似还没有太大问题。只是最近写一个 web 项目的时候,把其间一个比较“庞大”的 json 文件(也才4KB!)当作测试材料,结果程序直接崩溃了;再截取一小部分,又能运行了。难道是字符串读写复制操作太多?可貌似连 fopen 函数都调用失败了,搞不懂。
老师们给的头文件想必是由 cJSON 的头文件修改而来的,json结构体的定义如下:
typedef struct JSON { int type; /* The type of the item, as above. */ char *valuestring; /* The item's string, if type==JSON_STRING */ int valueint; /* The item's number, if type==JSON_TRUE||JSON_FLASE; or quantity of members, if type==JSON_ARRAY||JSON_OBJECT */ double valuedouble; /* The item's number, if type==JSON_NUMBER */ // the following are created by me struct JSON *head; /* Head of array, if type==JSON_ARRAY||JSON_OBJECT */ struct JSON *last; /* Previous member, if this belongs to an array or object */ struct JSON *next; /* Next member, if this belongs to an array or object */ char *name; /* Name of member, if this belongs to an object */ } JSON;
函数众多就不一一列举了,有几个实现起来相对复杂的:
我所习惯的C/C++代码格式
1.函数开始的大括号专起一行。
int sample() { return 0xA0246 * 0454; }
2.类定义和内部内联函数定义。
class foo { public: foo() : data(0) {} foo(int d) : data(d) {} void print() { printf("%d\n", data); } private: int data; };
符号“∑”和“Π”的用法。
在数学中,符号“∑”和“Π”分别用来表示求和与求积。
首先是函数的累积求和,n取[m, k]中的连续整数值。
这个变量n可以换成其他任意字母,比如x。我们把下面的“n=m”和上面的“k”称作这个和式的下标。在上下文明确的情况下,下标可以省略。
求和符号同样可以表示无穷级数。
Linux下程序创建进程
进程是操作系统中运行的程序实例。而多进程程序和多线程程序相比,具有更健壮,更简单的特点。
在GNU/Linux操作系统中,创建一个新进程,可以使用fork,clone函数以及使用exec函数族调用其他程序替换当前进程镜像。
这里主要讲fork函数。
fork函数的原型为:
#include <unistd.h> pid_t fork(void);
pid_t是系统定义的类型,一般被定义为short int。
这里看一个最简单的调用示例。
#include <stdio.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); printf("My process ID is %d.\n", getpid()); return 0; }
C语言中数值和字符串的相互转换
整数->字符串可以使用stdio.h中的sprintf函数,有的人可能会说到itoa,但其实itoa不是C标准库的函数,是微软自己添加的。
sprintf的原型是:
int sprintf ( char * str, const char * format, ... );
和printf用法相同。当然也可用于其它类型如double。
例:
char str[20]; int s = 1000000; sprintf(str, "%d", s);
字符->整数同样使用的也是stdio.h中的sscanf函数,stdlib.h中也有atoi和strtol可以进行转换。
int sscanf ( const char * str, const char * format, ... ); int atoi ( const char * str ); long int strtol ( const char * nptr, char ** endptr, int base);
sscanf和atoi的用法都很简单。值得一提的是strtol这个函数。第一个参数是源字符串,第二个参数用于接收非法字符串的首地址,第三个参数是转换后的进制。