C语言编程:从指针函数到结构体的深度探索
立即解锁
发布时间: 2025-08-22 00:24:52 阅读量: 1 订阅数: 6 


C语言编程基础与实践
# C语言编程:从指针函数到结构体的深度探索
## 1. 编写`tail`程序
在编程实践中,有时需要打印输入内容的最后几行。`tail`程序就能实现这个功能,默认情况下,它会打印最后 10 行,但也可以通过参数 `-n` 来指定打印的行数。以下是对该程序的要求:
- 无论输入内容或 `n` 的值是否合理,程序都应能合理运行。
- 程序要充分利用可用的存储空间,不能使用固定大小的二维数组来存储行,而应采用类似排序程序中的存储方式。
## 2. 指针函数与排序程序
### 2.1 指针函数的概念
在 C 语言里,函数本身并非变量,但可以定义指向函数的指针。这些指针能进行赋值、存入数组、作为参数传递给其他函数以及从函数返回等操作。
### 2.2 排序程序的改进
为了说明指针函数的应用,我们对之前的排序程序进行了修改。当输入参数 `-n` 时,程序会按数值对输入行进行排序,而非按字典序排序。排序通常包含三个部分:
- 比较操作:确定任意两个对象的顺序。
- 交换操作:反转对象的顺序。
- 排序算法:不断进行比较和交换,直至对象有序。
排序算法与比较和交换操作相互独立,通过传递不同的比较和交换函数,我们可以按不同标准进行排序。以下是改进后的排序程序代码:
```c
#include <stdio.h>
#include <string.h>
#define MAXLINES 5000 /* max #lines to be sorted */
char *lineptr[MAXLINES]; /* pointers to text lines */
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void qsort(void *lineptr[], int left, int right,
int (*comp)(void *, void *));
int numcmp(char *, char *);
/* sort input lines */
main(int argc, char *argv[])
{
int nlines; /* number of input lines read */
int numeric = 0; /* 1 if numeric sort */
if (argc > 1 && strcmp(argv[1], "-n") == 0)
numeric = 1;
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
qsort((void**) lineptr, 0, nlines-1,
(int (*)(void*,void*))(numeric ? numcmp : strcmp));
writelines(lineptr, nlines);
return 0;
} else {
printf("input too big to sort\n");
return 1;
}
}
```
### 2.3 `qsort`函数的实现
`qsort`函数可以处理任何数据类型,它接受一个指针数组、两个整数和一个带有两个指针参数的函数作为参数。以下是`qsort`函数的代码:
```c
/* qsort: sort v[left]...v[right] into increasing order */
void qsort(void *v[], int left, int right,
int (*comp)(void *, void *))
{
int i, last;
void swap(void *v[], int, int);
if (left >= right) /* do nothing if array contains */
return; /* fewer than two elements */
swap(v, left, (left + right)/2);
last = left;
for (i = left+1; i <= right; i++)
if ((*comp)(v[i], v[left]) < 0)
swap(v, ++last, i);
swap(v, left, last);
qsort(v, left, last-1, comp);
qsort(v, last+1, right, comp);
}
```
### 2.4 `numcmp`函数的实现
`numcmp`函数用于按数值比较两个字符串,它通过调用`atof`函数计算字符串的数值。以下是`numcmp`函数的代码:
```c
#include <stdlib.h>
/* numcmp: compare s1 and s2 numerically */
int numcmp(char *s1, char *s2)
{
double v1, v2;
v1 = atof(s1);
v2 = atof(s2);
if (v1 < v2)
return -1;
else if (v1 > v2)
return 1;
else
return 0;
}
```
### 2.5 `swap`函数的实现
`swap`函数用于交换两个指针,其代码如下:
```c
void swap(void *v[], int i, int j)
{
void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
```
### 2.6 排序程序的扩展
我们还可以为排序程序添加各种选项,例如:
- `-r` 选项:实现逆序(降序)排序,确保它能与 `-n` 选项配合使用。
- `-f` 选项:忽略大小写进行排序,使 `a` 和 `A` 被视为相等。
- `-d` 选项:仅比较字母、数字和空格,确保它能与 `-f` 选项配合使用。
- 字段搜索功能:可以按行内的字段进行排序,每个字段可根据独立的选项集进行排序。
## 3. 复杂声明的处理
### 3.1 复杂声明的问题
C 语言的声明语法有时会让人感到困惑,尤其是涉及指针函数的声明。声明不能从左到右直接读取,且括号使用过多。例如:
- `int *f();` 表示 `f` 是一个返回指向 `int` 指针的函数。
- `int (*pf)();` 表示 `pf` 是一个指向返回 `int` 的函数的指针。
### 3.2 `dcl`程序:C 声明转文字描述
`dcl` 程序可以将 C 声明转换为文字描述,它基于特定的语法规则进行解析。以下是 `dcl` 程序的主要代码:
```c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXTOKEN 100
enum { NAME, PARENS, BRACKETS };
void dcl(void);
void dirdcl(void);
int gettoken(void);
int tokentype; /* type of last token */
char token[MAXTOKEN]; /* last token string */
char name[MAXTOKEN]; /* identifier name */
char datatype[MAXTOKEN]; /* data type = char, int, etc. */
char out[1000];
main() /* convert declaration to words */
{
while (gettoken() != EOF) { /* 1st token on line */
strcpy(datatype, token); /* is the datatype */
out[0] = '\0';
dcl(); /* parse rest of line */
if (tokentype != '\n')
printf("syntax error\n");
printf("%s: %s %s\n", name, out, datatype);
}
return 0;
}
/* dcl: parse a declarator */
void dcl(void)
{
int ns;
for (ns = 0; gettoken() == '*'; ) /* count *'s */
ns++;
dirdcl();
while (ns-- > 0)
strcat(ou
```
0
0
复制全文
相关推荐









