现在的位置: 首页 > 设计导读 > 正文

【K&R C语言】第5章 指针与数组

2011年04月13日 设计导读 ⁄ 共 2674字 ⁄ 字号 暂无评论

使用指针通常可以生成更高效、更紧凑的代码

本章分成两部分内容:【基础部分】 和 【高级部分】

【基础部分】体现了指针和数组之间的密切联系,【高级部分】体现了C语言的灵活性,但也使得这部分内容不容易掌握。

掌握【基础部分】并不难,你只需牢牢记住:指针是数组名的另一种表达。

【基础部分】

5.2 指针与函数参数 【A swap 交换两个整数 】
5.3 指针与数组	【B strlen5.4 地址算术运算 【C strlen5.5 字符指针与函数 【D strcpy】 【E strcmp5.7 多维数组 【F 日期转换】 
5.8 指针数组的初始化 【G 月份名字】

【高级部分】

5.6 指针数组以及指向指针的指针 【文本行排序】
5.10 命令行参数
     【回显程序 echo】
     【查找模式串 高级版】
5.11 指向函数的指针	【文本行排序】
5.12 复杂声明	【声明转换为文字描述】

5.2 指针与函数参数 【 swap 交换两个整数 】

1
2
3
4
5
6
void swap(int *px, int *py) 
{
    int t;
 
    t = *px;  *px = *py;  *py = t;
}

5.3 指针与数组 【strlen】

1
2
3
4
5
6
7
8
int strlen(char *s)
{
    int n;
 
    for (n = 0; *s != '\0'; s++)
        n++;
    return n;
}

5.4 地址算术运算 【strlen】

1
2
3
4
5
6
7
8
int strlen(char *s)
{
    char *p = s;
 
    while (*p != '\0')
        p++;
    return p - s;
}

5.5 字符指针与函数
【strcpy】

数组版本

1
2
3
4
5
6
7
void strcpy(char *s, char *t)
{
    int i = 0;
 
    while ((s[i] = t[i]) != '\0')
        i++;
}

指针版本

1
2
3
4
5
6
void strcpy(char *s, char *t)
{
    while ((*s = *t) != '\0') {
        s++;    t++;
    }
}

经验丰富的程序员写的版本:

1
2
3
4
5
void strcpy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
        ;
}

更为精炼的版本

1
2
3
4
5
void strcpy(char *s, char *t)
{
    while (*s++ = *t++)
        ;
}

【strcmp】

字符串比较函数 strcmp(s, t)。该函数比较字符串 s 和 t,并且根据 s 按照小于、等于或大于 t 的结果分别返回负整数、0 或正整数。该返回值是 s 和 t 由前向后逐字符比较时遇到的第一个不相等字符处的字符的差值。

数组版本

1
2
3
4
5
6
7
8
9
int strcmp(char *s, char *t)
{
    int i = 0;
 
    for ( ; s[i] == t[i]; i++)
        if (s[i] == '\0')
            return 0;
    return s[i] - t[i];
}

指针版本

1
2
3
4
5
6
7
int strcmp(char *s, char *t)
{
    for (  ;  *s == *t ;  s++, t++)
        if (*s == '\0')
            return 0;
    return *s - *t;
}

5.7 多维数组 【F 日期转换】

日期转换的问题,把某月某日这种日期表示形式转换为某年中第几天的表示形式,反之亦然。例如,3 月 1 日是非闰年的第 60 天,是闰年的第 61 天。

将某年某月的日期转换为某年中的第几天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
 
int is_leap(int year)
{
	if (year%400==0) return 1;
	if (year%100==0) return 0;
	if (year%4==0) return 1;
	return 0;	
}
 
int daytab[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
 
int day_of_year(int year, int month, int day)
{
    int i, leap;
    leap = is_leap(year);
    for (i = 1; i < month; i++)
        day = day + daytab[leap][i];
    return day;
}
 
int main(int argc, char *argv[])
{
	int year, month, day;
	while (scanf("%d%d%d", &year, &month, &day)==3) {
		printf("%d\n",day_of_year(year, month, day) );
	}
 
    return 0;
}

将某年中的第几天转换为某年某月的日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void month_day(int year, int yearday, int *pmonth, int *pday)
{
    int i, leap;
 
    leap = is_leap(year);
    for (i = 1; yearday > daytab[leap][i]; i++)
        yearday = yearday - daytab[leap][i];
    *pmonth = i;
    *pday = yearday;
}
 
int main(int argc, char *argv[])
{
	int year, yearday, month, day;
	while (scanf("%d%d", &year, &yearday)==2) {
		month_day(year, yearday, &month, &day);
		printf("month = %d, day = %d\n", month, day);
	}
 
    return 0;
}

month_day 这个函数有的特别,需要计算出两个值:月份和日期;普通的函数只能返回一个值。
怎么办呢? 使用指针,传递 month 和 day 的地址。

指针:白刀子进去,红刀子出来 =》 发生了变化

5.8 指针数组的初始化 【G 月份名字】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
char* month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        "April", "May", "June",
        "July", "August", "September",
        "October", "November", "December"
    };
    return (n<1 || n>12) ? name[0] : name[n];
}
 
int main(int argc, char *argv[])
{
    int year, yearday, month, day;
    while (scanf("%d%d", &year, &yearday)==2) {
        month_day(year, yearday, &month, &day);
        printf("%s %d\n", month_name(month), day);
    }
    return 0;
}

函数 month_name 返回的是什么? 月份的英文名字,是一个字符串,或者说是一个字符数组。
字符数组怎么表示? 如 char str[100] ,类型呢? char [] ,等价于 char*

1
2
3
    char* month_name(int n)
    相当于
    char *month_name(int n)

抱歉!评论已关闭.