一个语言的程序设计有一些常用的基本模式,这些模式是许多人长期工作的总结。在这个语言的程序中到处可见。对于一些典型问题,采用适当的模式是最容易把程序写好、写正确的。在这里我们将从简单到复杂,分门别类地列处一些C程序模式,供大家参考。这里列出的东西选自各种材料(包括《从问题到程序》书中)。这里列出的东西是很初步的。如果你认为有些东西也很重要,请给我们提示。 在所有模式描述中,用$$符号括起来的一段段文字表示的是应该实际写出的东西。 有关解释如果写了页数,请参考《从问题到程序》书中相关的页。 简单输出程序模式: #include <stdio.h> int main () { $一个或几个输出语句,例如printf("Hello, world!\n");$ return 0; } ---------------------------------------------------- 例: #include <stdio.h> int main() { printf("Welcome\n"); printf("to\n"); printf("Beijing!\n"); return 0; } 简单表达式计算模式: #include <stdio.h> int main() { printf($ 格式描述串$, $一个或几个表达式$); return 0; } --------------------------------------------------- 注意:格式描述串中转换描述与参数个数一致,类型一致。 --------------------------------------------------- #include <stdio.h> int main() { printf("%f * %f = %f", 3.14, 6.5, 3.14 * 6.5); return 0; } 简单算术计算函数定义: double fun ($一个或几个参数的说明$) { return $计算表达式$; } ---------------------------------------------------- 1,函数返回值类型根据需要写出,未必是double; 2,参数写出类型和参数名的对,多个参数用逗号分隔; 3,计算表达式描述如何由参数出发算出函数值; 4,如果计算中需要用数学函数,应该在程序开始写一行 #include <math.h> ---------------------------------------------------- 例: double circle_area (double r) { return r * r * 3.14159265; } 有函数定义的一般程序: #include … …… /* 函数定义写在这里(可以有一个或几个) */ int main () { /* 主程序体,通常包含对函数的调用 */ return 0; } 常用while循环形式: n = 1; /* 初始化循环中使用的变量 */ while (n <= 100) { /* 已知次数的循环用for结构写得更多 */ /* 其他语句 */ n = n + 1; /* 循环最后更新辅助变量 */ } 注:这种更常见的是采用for循环形式写。见下。 ---------------------------------------------------- /* 有关变量的初始化 */ while ($表达式$ >= 1E-6) { /* 循环中的计算应该影响“表达式”的值,否则将导致无限循环 */ } 常用for循环形式: for (n = 0; n < N; n++) { $循环体里的语句$ } --------------------------------------------------- 注意:C语言里一般不用(除非有特殊目的): for (n = 1; n <= N; n++) { $循环体里的语句$ } 给程序计时: #include <stdio.h> #include <time.h> /* 其他定义 */ int main () { /* 其他程序变量的定义 */ double x; x = clock() / CLOCKS_PER_SEC; /* 需要计时的程序片段 */ x = clock() / CLOCKS_PER_SEC - x; printf("Timing: %f\n", x); /* 输出形式自己确定 */ return 0;} --------------------------------------------------- 注意:不同系统的计时精度可能不同。有些系统还有非标准的计时功能。 输入和处理由标准输入文件来的一系列字符 int c; /* 其他定义或语句 */ while ((c = getchar()) != EOF) { /* 对读入字符的处理 */ } --------------------------------------------------- 1,接收读入字符的变量(例如上面的c)必须用int类型; 2,注意while条件中的括号,不能写错; 3,应该写 #include <stdio.h> 最常见的数组操作 for (i = 0; i < N; i++) { .... .... .... a[i] .... b[i] .... .... } --------------------------------------------------- 1,循环范围不能超出数组下标的范围 典型的处理数组的函数 double sqsum(double a[], int n) { double x = 0.0; int i; for (i = 0; i < n; i++) x += a[i] * a[i]; return x; } --------------------------------------------------- 1,注意数组参数的写法; 2,增加一个描述数组长度的参数,借助于它控制对数组元素的处理; 3,通过这种函数可以改变实际参数数组。 处理字符串的典型函数 void str_copy (char s[], char t[]) { int i; for (i = 0; t[i] != '\0'; i++) s[i] = t[i]; s[i] = '\0'; } --------------------------------------------------- void str_copy1 (char *s, char *t) { for (; *t != '\0'; s++, t++) *s = *t; *s = '\0'; } --------------------------------------------------- 1,参数用 char s[] 或者 char *s 描述,两者等价,但用 char s[] 更具有提示性; 2,用遇到空字符'\0'作为循环结束条件; 3,还有些更紧凑的写法,参见有关书籍 逐个处理命令行参数 int main (int argc, char *argv[]) { int i; ... ... for (i = 0; i < argc; i++) { .... argv[i] .... } ... ... } --------------------------------------------------- int main (int argc, char *argv[]) { ... ... for (; *agrv != NULL; argv++) { ... *argv ... } ... ... } --------------------------------------------------- 循环中的 *argv 将依次取各个命令行参数字符串。 注意:编号0的参数是命令名本身,如果不处理它应该先跳过去。 使用动态存储分配函数malloc或calloc if ((p = (... *)malloc(...)) == NULL) { .. ... /* 对分配未成功情况的处理 */ } --------------------------------------------------- 1,指针应当具有合适的类型; 2,在malloc名前写合适的转换描述; 3,malloc的参数应当借助sizeof计算。 链接表的处理模式(以扫描的方式逐个处理表中的数据) for (p = head; p != NULL; p = p->next) { .... p->data .... } --------------------------------------------------- 假设head是指向表头结点的指针。 结点中的next成分是指向下一个结点的指针,data是数据。 文件使用的基本模式 FILE *fp; .... .... if ((fp = fopen($文件名$, $打开方式$)) == NULL) { /* 当文件打不开时的处理 */ } ... ... /* 对文件的各种操作 */ fclose(fp); --------------------------------------------------- 执行文件打开操作之后,必须检查操作是否正常完成。 使用<stdlib.h>里的bsearch和qsort,比较函数的基本写法 1,确定被比较对象的顺序关系; 2,比较函数总用两个const void* 参数; 3,在函数开始时将参数正确转换到指向数组元素类型的指针; 4,在第一个参数大于、等于、小于第二个时分别返回1、0、-1; 5,注意使用方式。 --------------------------------------------------- 例子:假定被排序的是整数数组。定义比较函数: int icmp(const void *p, const void *q){ const int *m = p, *n = q; return *m > *n ? 1 : (*m == *n ? 0 : -1); } 使用: int *p, a[] = {5, 6, 3, 28, 23, 34, 7, 9, 6, 14}, k = 7; int main () { ... ... qsort(a, sizeof(a)/sizeof(int), sizeof(int), icmp); /* 这样,数组a的元素已经按照上升顺序排列好了 */ p = bsearch(&k, a, sizeof(a)/sizeof(int), sizeof(int), icmp); /* 指针p将指向数组a中元素7的位置 */ ... ... } --------------------------------------------------- 请注意在这里如何为bsearch和qsort提供所要求的各个参数。

评论