开发成长之路(3)-- C语言从入门到开发(讲明白指针和引用,链表很难吗?)

在这里插入图片描述

指针和动态内存分配

指针是C语言的基本概念,C语言中指针无处不在。实际上,每种数据类型,都有相应的指向T的指针类型。
指针类型变量存放的值,实际上就是内存地址。指针类型有两个最基本的操作:

&:取地址操作 
*:去引用 (间接引用)操作

引用&

首先,&不是地址运算符,而是类型标识符的一种,就像*也不是指针运算符一样。

就像char* 意为指向char的指针一样,int& 意为指向int 的引用。

栗子来一颗:

int a;
int &at = a;
//上述声明允许将at和a互换,它们指向相同的值和内存单元,就像连体婴一样。

上面这个栗子其实很有内涵在里面
我为什么不写成下面这个形式呢?

int a;
int &at;
at = a;

在指针中是可以的,但是&不允许,&必须在声明时将其初始化。

引用经常被用作函数参数,使得函数中的变量名成为调用程序中变量的别名。这种调用方法我一直搞得晕晕的,正好这次一次性根除。这种传递参数的方法称为按引用传递。按引用传递允许被调用函数能够访问调用函数中的变量。这是C++相比C的一个超越。
来个经典的栗子:

void swap_a(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

//顺便来个指针的
void swap_b(int *a,int *b)
{
	int temp;
	temp = *a;	//a,b是指针,*a,*b才是int
	*a = *b;
	*b = temp;
}

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	int d = 4;
	swap_a(a,b);	//看仔细咯,这个是引用调用
	swap_b(&a,&b);	//看仔细咯,这个是指针调用
	//如果理解不了,这样理解:参数中的*和&只是走个过场,告诉人家那个参数是什么类型的
	//调用函数时的参数是a,不是*a,也不是&a
	//所以&a传的这个a是一个int类型,而*a的这个a就是指针,地址,所以要取地址传给它
	//虽然我语文不好,但是都讲到这份上了那应该是可以理解了
	return 0;
}

如果你的意图是让函数使用传给它的信息,又不想把这些信息进行改动,那么应该使用const。
将引用参数声明为const数据的好处有这些:

防止无意中被修改。
使用const参数可以兼容非const传参。

将引用用于结构

C++引入引用主要就是为了和结构和类。
它还通过让函数返回指向结构的引用而增添了一个有趣的特点,这与返回结构有所不同。

//代码太长,放段伪代码吧
struct Str	//不知道什么是结构体不急,稍后就会有
{
};

Str& test(Str &a,const Str &b)	
{
	//从b中取值,对a进行填充
	return a;//其实可以做void类型,没必要多此一举
}

int main()
{
	Str a,b,c;
	//b是有初值的,这是伪代码
	c = test(a,b);
	return 0;
}

如果test函数返回一个结构,而不是指向结构的引用,相当于把整个结构体复制到一个临时位置,再将这个拷贝复制给c,但是现在返回值为引用,将直接将a复制到c,效率更高

返回引用时最重要的一点是:应避免返回函数终止时将不再存在的内存单元的引用
下面是一个反面教材:

Str& test(const Str &d)
{
	Str &e;
	···
	return e;
}

何时使用引用参数?

程序员能够修改调用函数中的数据对象。
通过传递引用而不是整个数据对象,可以提高程序的运行速度。

指针

指针和const

将const用于指针有一些很微妙的地方。
可以用两种不同的方式将const关键字用于指针。

int age = 20; const int * pt = &age;
//该声明指出,pt指向一个const int,因此不能使用pt来修改这个值。
//现在来看一个很微妙的问题:其实age并不是一个常量,只是对于pt来说,它是一个常量。
//就是说age可以改,只不过不能用pt来改而已。

注意点:不允许将常量数据赋值给非常量指针,个中理由就不用多解释了吧。

const int age = 20; int * pt = &age;

int sloth = 80; int * const finger = &sloth;
// 这种声明格式使得这个指针只能指向sloth,不过可以通过这个指针修改sloth的值。

通过指针返回字符串的函数

现在,假设需要一个返回字符串的函数,是的,函数无法返回一个字符串,但是可以返回字符串的地址,这样效率更高。

void test(char *rc)
{
	···
	memset(rc,字符串);
	···
}

相当于是使用回调函数,我个人比较喜欢这一套模式。

通过指针返回结构

具体操作参考第二点。
当然,这里还有另外的应用场景:

void test2(const JieGouTi1 *a,JieGouTi2 *b)
{
	//将a中的某些值赋值给b
}
//这里有一个注意点,传进去赋值的结构体指针最好用const.

函数指针

关于为什么要使用函数指针,我的理解还不是很深刻,毕竟功力不足。但是我知道那些回调函数都是用函数指针的,所以对函数指针必须要理解好。
这叫啥,“但行好事,莫问为啥”。

函数指针完成任务的流程是这样的:

获取函数的地址
声明一个函数指针
使用函数指针来调用函数
获取函数地址

获取函数地址那是比较简单的事,如果说 void Hanshu();这是一个函数,那么它的地址就是 Hanshu。
如果函数Hanshubaba();要调用这个函数,是这样的:Hanshubaba(Hanshu);
切记不能写成:Hanshubaba(Hanshu());

声明函数指针

假设现在有这么一个函数:int test3(void *arg); //这个arg参数,回调函数里面用,要解释有点长。
现在要将之改成函数指针形式:int (*test3)(void *arg);

首先,将test3更换成(*test3),因此,(*test3)也是函数,那么test3就是函数指针。
为声明优先级,需要将 *test3 括号起来。

函数指针用武之地

如果你非要我说函数指针存在的意义,那我也真不好给你扯个所以然出来,那我就,举几个用得到的地方吧:

自定义排序/搜索

不同的模式(如策略,观察者)

回调
关于指针的一些思考

前面说到,将指针作为参数传入,在函数内部对指针进行修改,函数结束后指针的修改将被保留。
因为指针传参代表着地址传参。

解惑:如何让对指针参数的修改不被保存。

看个栗子:

class B {
	char* b;
public:
	B() {
		b = new char[5];
		strcpy(b,"aaaa");
	}
	char* get_b() { return b; }
};

class A {
private:
	char* a;
public:
	A(B* temp) { a = temp->get_b(); };

	void set_A() { 
		strcpy(a, "kkkk");	//顶替掉了
	}
};

int main() {
	B* b = new B();
	A* a = new A(b);
	a->set_A();
	cout << b->get_b() << endl;

	return 0;
}

结局打印出来的 b,就是“kkkk”。
那为什么会这样?前面解释过了,a、b都是对内存地址的映射,对a进行修改,就是对地址上的数据进行修改,而b只不过是地址的一个映射而已,读取b,就是读取地址上的东西,那本质已经被改了,读出来的东西自然不一样。

再看个例子:

void Del (POINT_T * the_head, int index)
{
	POINT_T *pFree=NULL;
	
	POINT_T *pNode=the_head;
	int flag=0;
	while (pNode->next!=NULL)
	{
		if(flag==index-1)
		{
			pFree=pNode->next;				//再指向数据域就爆了
			pNode->next=pNode->next->next;
			free(pFree->pData);
			free(pFree);
			break;
		}
		pNode=pNode->next;
		flag++;	
	}	
}

这是链表的一个例子,那可能会纳闷儿,为什么对 pNode执行了 pNode=pNode->next;操作,而the_head却没有跟着变呢?
原因很简单,pNode->next也是一个映射地址,这句话的意思就是用一个新的地址映射,顶替掉那个旧的,使得指针pNode指向一块新的地址,和the_head失去联系。


结构体

结构是 C 编程中一种用户自定义的可用的数据类型,它允许我们存储不同类型的数据项。

struct tag {	// 定义一个结构体,名字叫tag 
    member-list	// 结构体成员变量
    member-list 
    member-list  
    ...
} variable-list ;	// 结构体的简称

如果有简称时,初始化结构体对象是这样的:

variable-list vl;
variable-list *vl2;

如果没有简称时,初始化结构体对象是这样的:

struct tag t;
struct tag *t2;

//就是要带上‘struct’

在一般情况下,tag、variable-list 这 2 部分至少要出现 1 个。


调试

调试呢,是我们解决代码运行过程中突然暴雷的一个很好的手段,如果代码量一大的时候,凭肉眼想找到bug太难了。
但是如果我们对程序的运行流程应该是有一定的设想的吧,就是不知道实际它有没有阳奉阴违。

调试,就是放慢程序运行的速度,让我们看清楚它内部是如何运行的。

1.选择需要检查或暂停运行的行,如下图红色方框前
在这里插入图片描述

2.点击Windows调试器(或者F5)
在这里插入图片描述

3、让程序一步步执行,点击单步执行(F10)、进入函数(F11)、跳出函数(shift+F11)、下一个断点(F5)
是可以在代码中打多个断点的。

(每个人的界面排版不一定一样,所以建议使用快捷键法)

程序执行时,可以看到每个变量的状态
在这里插入图片描述

简单调试就介绍到这里,大家可以先练习一下。

链表

链表在C语言的数据结构中的地位可不低。后面很多的数据结构,特别是树,都是基于链表发展的。
所以学好链表,后面的结构才有看的必要。

初识链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

链表有很多种不同的类型:单向链表,双向链表以及循环链表。


单链表

在这里插入图片描述

单链表实现

话不多说啊,这里我只想直接放代码:

#include <stdio.h>	//初学者,C语言开手
#include <conio.h>
#include <stdlib.h>
#include <memory.h>
#include <assert.h>

//节点数据结构体
typedef struct test
{	
	char name[12];		//名字
	char pwd[8];		//密码
	int number;			//编号
	int flag;			//区分管理员和用户	// 	0 超级管理员 1 管理员  2 普通用户 3 屏蔽用户
	int money;			//仅用户有存款,初始500
} TEST_T;

//如果不多来一个数据域,怎么能体现出通用链表的优势
typedef struct reported
{
	int amount;//交易金额
	int rflag; //交易方式	1、存款 2、取款 3、转账转出 4、转账转入
	int lastmoney;//余额
	int lastmoney2;//收款者的余额
	int number1;//付款账户
	int number2;//入款账户
	char time[12];//操作时间	
} REPORT_T;

//节点描述结构体
typedef struct point
{
	void *pData;				//指向数据域
	struct point *next;			//指向下一个节点	
} POINT_T;

POINT_T * head ;
extern POINT_T * head;

这还是个通用链表的头呢!!!

//创建结点
POINT_T * creat(void *data )	//创建一个属于结构体point的函数,
//传入结构体test的指针便可以用以操作test变量,
{								//并返回一个point的指针用以操作point函数
	POINT_T *p=NULL;
	
	p=(POINT_T *)malloc(sizeof(POINT_T));
	if(p==NULL)
	{
		printf("申请内存失败");
		exit(-1);
	}
	memset(p,0,sizeof(POINT_T));
	
	p->pData=data;
	p->next=NULL;	//处理干净身后事
	return p;
}

//新增节点
void add(POINT_T * the_head,void *data )				//这里的data不会和上面那个冲突吗?
{
	POINT_T * pNode=the_head;							//把头留下
	POINT_T *ls=creat(data);
	//后面再接上一个
	while (pNode->next != NULL)							//遍历链表,找到最后一个节点
	{
		pNode=pNode->next;
	}
	pNode->next=ls;			//ls 临时
}

//删除节点
void del(POINT_T * the_head, int index)
{
	POINT_T *pFree=NULL;					//用来删除
	
	POINT_T *pNode=the_head;
	int flag=0;
	while (pNode->next!=NULL)
	{
		if(flag==index-1)
		{
			pFree=pNode->next;				//再指向数据域就爆了
			pNode->next=pNode->next->next;	//这里要无缝衔接
			free(pFree->pData);				//先释放数据
			free(pFree);					//释放指针
			break;
		}
		pNode=pNode->next;
		flag++;	
	}	
}

//计算节点数
int Count(POINT_T * the_head)
{
	int count=0;
	POINT_T *pNode1=the_head;
	while (pNode1->next!=NULL)
	{
		pNode1=pNode1->next;
		count++;		
	}	
	return count;
}

//查找固定节点数据
POINT_T * find(POINT_T *the_head,int index)
{
	int f=0;
	POINT_T *pNode=NULL;
	int count=0;
	pNode=the_head;
	
	count=Count(the_head);
	
	if(count<index)	
		printf("find nothing");
	
	while(pNode->next!=NULL)
	{
		if(index==f)
			return pNode;
		pNode=pNode->next;
		f++;		
	}
}

我就挑简单的讲,先入个门,之前有专门的数据结构专栏,后面也会有专门的数据结构专栏,一步一个脚印,现在都不要太着急。

在这里插入图片描述

已标记关键词 清除标记
相关推荐
CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《C语言入门经典第4版》的源代码及课后练习答案 对应的书籍资料见: C语言入门经典第4版 基本信息 原书名: Beginning C: From Novice to Professional, Fourth Edition 原出版社: Apress 作者: (美)Ivor Horton 译者: 杨浩 出版社:清华大学出版社 ISBN:9787302170839 上架时间:2008-4-15 出版日期:2008 年4月 开本:16开 页码:571 版次:4-1 编辑推荐    本书是编程语言先驱者Ivor Horton的经典C语言方面最畅销的图书品种一,在世界范围内广受欢迎口碑极佳。    本书的目标是使你在C语言程序设计方面由一位初学者成为一位称职的程序员。 内容简介   本书是编程语言先驱者Ivor Horton的经典C语言方面最畅销的图书品种一。本书集综合性、实用性为一体是学习C语言的优秀入门教材在世界范围内广受欢迎口碑极佳。书中除了解C程序设计语言还广泛介绍了作为一名C程序设计人员应该掌握的必要知识并提供了大量的实用性很强的编程实例。本书的目标是使你在C语言程序设计方面由一位初学者成为一位称职的程序员。读者基本不需要具备任何编程知识即可通过本书头开始编写自己的C程序。 作译者 作者   Ivor Horton是世界著名的计算机图书作家主要事与编程相关的咨询及撰写工作曾帮助无数程序员步入编程的殿堂。他曾在IBM工作多年能使用多种语言进行编程(在多种机器上使用汇编语言高级语言)设计实现了实时闭环工业控制系统。Horton拥有丰富的教学经验(教学内容包括C、C++、Fortran、PL/1、APL等)同时还是机械、加工电子CAD系统、机械CAM系统DNC/CNC系统方面的专家。IvorHorton还著有关于C、C++Java的多部入门级好书如《C语言入门经典(第4版)》《C++入门经典(第3版)》。 译者   杨浩知名译者大学事机械计算机方面的教学研究多年发表论文数篇参编翻译的图书多达20余部还曾多次获得市部级奖项。近几年一直在跟踪.NET技术的发展积极事.NET技术文档图书的翻译工作。 目录 封面 -12 封底 572 前言 -9 目录 -6 第1章 C语言编程 1 1.1 创建C程序 1 1.1.1 编辑 1 1.1.2 编译 2 1.1.3 链接 2 1.1.4 执行 3 1.2 创建第一个程序 4 1.3 编辑第一个程序 4 1.4 处理错误 5 1.5 剖析一个简单的程序 6 1.5.1 注释 6 1.5.2 预处理指令 7 1.5.3 定义main()函数 7 1.5.4 关键字 8 1.5.5 函数体 8 1.5.6 输出信息 9 1.5.7 参数 10 1.5.8 控制符 10 1.6 用C语言开发程序 12 1.6.1 了解问题 12 1.6.2 详细设计 12 1.6.3 实施 13 1.6.4 测试 13 1.7 函数及模块化编程 13 1.8 常见错误 17 1.9 要点 17 1.10 小结 18 1.11 习题 18 第2章 编程初步 19 2.1 计算机的内存 19 2.2 什么是变量 21 2.3 存储数值的变量 21 2.3.1 整数变量 21 2.3.2 变量的命名 25 2.3.3 变量的使用 26 2.3.4 变量的初始化 28 2.3.5 算术语句 28 2.4 变量与内存 34 2.5 整数变量类型 35 2.5.1 无符号的整数类型 35 2.5.2 使用整数类型 36 2.5.3 指定整数常量 37 2.6 浮点数 38 2.7 浮点数变量 38 2.8 使用浮点数完成除法运算 39 2.8.1 控制小数位数 40 2.8.2 控制输出的字段宽度 41 2.9 较复杂的表达式 41 2.10 定义常量 44 2.10.1 极限值 46 2.10.2 sizeof运算符 49 2.11 选择正确的类型 50 2.12 强制类型转换 53 2.12.1 自动转换类型 53 2.12.2 隐式类型转换的规则 54 2.12.3 赋值
CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 C语言入门经典第4版 基本信息 原书名: Beginning C: From Novice to Professional, Fourth Edition 原出版社: Apress 作者: (美)Ivor Horton 译者: 杨浩 出版社:清华大学出版社 ISBN:9787302170839 上架时间:2008-4-15 出版日期:2008 年4月 开本:16开 页码:571 版次:4-1 编辑推荐    本书是编程语言先驱者Ivor Horton的经典C语言方面最畅销的图书品种一,在世界范围内广受欢迎口碑极佳。    本书的目标是使你在C语言程序设计方面由一位初学者成为一位称职的程序员。 内容简介   本书是编程语言先驱者Ivor Horton的经典C语言方面最畅销的图书品种一。本书集综合性、实用性为一体是学习C语言的优秀入门教材在世界范围内广受欢迎口碑极佳。书中除了解C程序设计语言还广泛介绍了作为一名C程序设计人员应该掌握的必要知识并提供了大量的实用性很强的编程实例。本书的目标是使你在C语言程序设计方面由一位初学者成为一位称职的程序员。读者基本不需要具备任何编程知识即可通过本书头开始编写自己的C程序。 作译者 作者   Ivor Horton是世界著名的计算机图书作家主要事与编程相关的咨询及撰写工作曾帮助无数程序员步入编程的殿堂。他曾在IBM工作多年能使用多种语言进行编程(在多种机器上使用汇编语言高级语言)设计实现了实时闭环工业控制系统。Horton拥有丰富的教学经验(教学内容包括C、C++、Fortran、PL/1、APL等)同时还是机械、加工电子CAD系统、机械CAM系统DNC/CNC系统方面的专家。IvorHorton还著有关于C、C++Java的多部入门级好书如《C语言入门经典(第4版)》《C++入门经典(第3版)》。 译者   杨浩知名译者大学事机械计算机方面的教学研究多年发表论文数篇参编翻译的图书多达20余部还曾多次获得市部级奖项。近几年一直在跟踪.NET技术的发展积极事.NET技术文档图书的翻译工作。 目录 封面 -12 封底 572 前言 -9 目录 -6 第1章 C语言编程 1 1.1 创建C程序 1 1.1.1 编辑 1 1.1.2 编译 2 1.1.3 链接 2 1.1.4 执行 3 1.2 创建第一个程序 4 1.3 编辑第一个程序 4 1.4 处理错误 5 1.5 剖析一个简单的程序 6 1.5.1 注释 6 1.5.2 预处理指令 7 1.5.3 定义main()函数 7 1.5.4 关键字 8 1.5.5 函数体 8 1.5.6 输出信息 9 1.5.7 参数 10 1.5.8 控制符 10 1.6 用C语言开发程序 12 1.6.1 了解问题 12 1.6.2 详细设计 12 1.6.3 实施 13 1.6.4 测试 13 1.7 函数及模块化编程 13 1.8 常见错误 17 1.9 要点 17 1.10 小结 18 1.11 习题 18 第2章 编程初步 19 2.1 计算机的内存 19 2.2 什么是变量 21 2.3 存储数值的变量 21 2.3.1 整数变量 21 2.3.2 变量的命名 25 2.3.3 变量的使用 26 2.3.4 变量的初始化 28 2.3.5 算术语句 28 2.4 变量与内存 34 2.5 整数变量类型 35 2.5.1 无符号的整数类型 35 2.5.2 使用整数类型 36 2.5.3 指定整数常量 37 2.6 浮点数 38 2.7 浮点数变量 38 2.8 使用浮点数完成除法运算 39 2.8.1 控制小数位数 40 2.8.2 控制输出的字段宽度 41 2.9 较复杂的表达式 41 2.10 定义常量 44 2.10.1 极限值 46 2.10.2 sizeof运算符 49 2.11 选择正确的类型 50 2.12 强制类型转换 53 2.12.1 自动转换类型 53 2.12.2 隐式类型转换的规则 54 2.12.3 赋值语句中的隐式类型转换 54 2.13 再谈数值数据类型 55 2.13.1 字符类型 56 2.13.2 字符的输入输出 57 2.13.3 宽字符类型 60 2.13.4 枚举 60 2.13.5 存储布尔值的变量 63 2.13.6 复数类型 63 2.14 赋值操作的op=形式 66 2.15 数学函数 68 2.16 设计一个程序 69 2.16.1 问题 69 2.16.2 分析 69 2.16.3 解决方案 71 2.17 小结 75 2.18 练习 76 第3章 条件判断 79 3.1 判断过程 79 3.1.1 算术比较 80 3.1.2 涉及关系运算符的表达式 80 3.1.3 基本的if语句 81 3.1.4 扩展if语句:if-else 84 3.1.5 在if语句中使用代码块 86 3.1.6 嵌套的if语句 87 3.1.7 更多的关系运算符 90 3.1.8 逻辑运算符 93 3.1.9 条件运算符 97 3.1.10 运算符的优先级 99 3.2 多项选择问题 103 3.2.1 给多项选择使用else-if语句 104 3.2.2 switch语句 104 3.2.3 goto语句 113 3.3 按位运算符 114 3.3.1 按位运算符的op=用法 116 3.3.2 使用按位运算符 117 3.4 设计程序 120 3.4.1 问题 120 3.4.2 分析 120 3.4.3 解决方案 121 3.5 小结 124 3.6 练习 124 第4章 循环 127 4.1 循环 127 4.2 递增递减运算符 128 4.3 for循环 129 4.4 for循环的一般语法 132 4.5 再谈递增递减运算符 133 4.5.1 递增运算符 133 4.5.2 递增运算符的前置后置形式 134 4.5.3 递减运算符 134 4.6 再论for循环 135 4.6.1 修改for循环变量 137 4.6.2 没有参数的for循环 138 4.6.3 循环内的break语句 138 4.6.4 使用for循环限制输入 141 4.6.5 生成伪随机整数 143 4.6.6 再谈循环控制选项 145 4.6.7 浮点类型的循环控制变量 146 4.7 while循环 147 4.8 嵌套循环 150 4.9 嵌套循环goto语句 153 4.10 do-while循环 154 4.11 continue语句 157 4.12 设计程序 157 4.12.1 问题 157 4.12.2 分析 157 4.12.3 解决方案 158 4.13 小结 170 4.14 习题 170 第5章 数组 173 5.1 数组简介 173 5.1.1 不用数组的程序 173 5.1.2 什么是数组 175 5.1.3 使用数组 176 5.2 内存 179 5.3 数组地址 182 5.4 数组的初始化 184 5.5 确定数组的大小 184 5.6 多维数组 185 5.7 多维数组的初始化 187 5.8 设计一个程序 191 5.8.1 问题 192 5.8.2 分析 192 5.8.3 解决方案 193 5.9 小结 200 5.10 习题 200 第6章 字符串文本的应用 201 6.1 什么是字符串 201 6.2 处理字符串文本的方法 203 6.3 字符串操作 206 6.3.1 连接字符串 206 6.3.2 字符串数组 208 6.4 字符串库函数 210 6.4.1 使用库函数复制字符串 210 6.4.2 使用库函数确定字符串的长度 211 6.4.3 使用库函数连接字符串 212 6.4.4 比较字符串 213 6.4.5 搜索字符串 216 6.5 分析转换字符串 219 6.5.1 转换字符 222 6.5.2 将字符串转换成数值 225 6.7 使用宽字符串 225 6.8 设计一个程序 228 6.8.1 问题 229 6.8.2 分析 229 6.8.3 解决方案 229 6.9 小结 237 6.10 习题 237 第7章 指针 239 7.1 指针初探 239 7.1.1 声明指针 240 7.1.2 通过指针访问值 241 7.1.3 使用指针 244 7.1.4 指向常量的指针 248 7.1.5 常量指针 248 7.1.6 指针的命名 249 7.2 数组指针 249 7.3 多维数组 252 7.3.1 多维数组指针 255 7.3.2 访问数组元素 257 7.4 内存的使用 260 7.4.1 动态内存分配:malloc()函数 260 7.4.2 分配内存时使用sizeof运算符 261 7.4.3 用calloc()函数分配内存 265 7.4.4 释放动态分配的内存 265 7.4.5 重新分配内存 267 7.5 使用指针处理字符串 268 7.5.1 更多地控制字符串输入 268 7.5.2 使用指针数组 269 7.6 设计程序 280 7.6.1 问题 280 7.6.2 分析 281 7.6.3 解决方案 281 7.7 小结 291 7.8 习题 291 第8章 程序的结构 293 8.1 程序的结构 293 8.1.1 变量的作用域生存期 294 8.1.2 变量的作用域函数 297 8.2 函数 297 8.2.1 定义函数 298 8.2.2 return语句 301 8.3 按值传递机制 304 8.4 函数声明 305 8.5 指针用作参数返回值 307 8.5.1 常量参数 310 8.5.2 函数中返回指针318 8.5.3 在函数中递增指针 322 8.6 小结 322 8.7 习题 323 第9章 函数再探 325 9.1 函数指针 325 9.1.1 声明函数指针 325 9.1.2 通过函数指针调用函数 326 9.1.3 函数指针数组 329 9.1.4 作为变元的函数指针 331 9.2 函数中的变量 334 9.2.1 静态变量:函数内部的追踪 334 9.2.2 在函数间共享变量 336 9.3 调用自己的函数:递归 338 9.4 变元个数可变的函数 341 9.4.1 复制va_list 344 9.4.2 长度可变的变元列表的基本规则 344 9.5 main()函数 345 9.6 结束程序 346 9.7 函数库:头文件 347 9.8 提高性能 348 9.8.1 内联声明函数 348 9.8.2 使用restrict关键字 348 9.9 设计程序 349 9.9.1 问题 349 9.9.2 分析 349 9.9.3 解决方案 351 9.10 小结 367 9.11 习题 368 第10章 基本输入输出操作 369 10.1 输入输出流 369 10.2 标准流 370 10.3 键盘输入 371 10.3.1 格式化键盘输入 371 10.3.2 输入格式控制字符串 372 10.3.3 输入格式字符串中的字符 377 10.3.4 输入浮点数的各种变化 378 10.3.5 读取十六进制八进制值 379 10.3.6 用scanf()读取字符 381 10.3.7 scanf()的陷阱 383 10.3.8 键盘上输入字符串 383 10.3.9 键盘的非格式化输入 384 10.4 屏幕输出 389 10.4.1 使用printf()格式输出屏幕 389 10.4.2 转义序列 391 10.4.3 整数输出 392 10.4.4 输出浮点数 394 10.4.5 字符输出 395 10.5 其他输出函数 398 10.5.1 屏幕的非格式化输出 398 10.5.2 数组的格式化输出 399 10.5.3 数组的格式化输入 400 10.6 打印机输出 400 10.7 小结 401 10.8 习题 401 第11章 结构化数据 403 11.1 数据结构:使用struct 403 11.1.1 定义结构类型结构变量 405 11.1.2 访问结构成员 405 11.1.3 未命名的结构 408 11.1.4 结构数组 408 11.1.5 表达式中的结构 411 11.1.6 结构指针 411 11.1.7 为结构动态分配内存 412 11.2 再探结构成员 414 11.2.1 将一个结构作为另一个结构的成员 414 11.2.2 声明结构中的结构 415 11.2.3 将结构指针用作结构成员 416 11.2.4 双向链表 420 11.2.5 结构中的位字段 423 11.3 结构与函数 424 11.3.1 结构作为函数的变元 424 11.3.2 结构指针作为函数变元 425 11.3.3 作为函数返回值的结构 426 11.3.4 修改程序 430 11.3.5 二叉树 433 11.4 共享内存 442 11.4.1 联合 442 11.4.2 联合指针 444 11.4.3 联合的初始化 444 11.4.4 联合中的结构成员 444 11.5 定义自己的数据类型 446 11.5.1 结构与类型定义(typedef)功能 446 11.5.2 使用typedef简化代码 447 11.6 设计程序 448 11.6.1 问题 448 11.6.2 分析 448 11.6.3 解决方案 448 11.7 小结 459 11.8 习题 459 第12章 处理文件 461 12.1 文件的概念 461 12.1.1 文件中的位置 462 12.1.2 文件流 462 12.2 文件访问 462 12.2.1 打开文件 463 12.2.2 文件重命名 465 12.2.3 关闭文件 465 12.2.4 删除文件 466 12.3 写入文本文件 466 12.4 读取文本文件 467 12.5 将字符串写入文本文件 470 12.6 文本文件中读入字符串 471 12.7 格式化文件的输入输出 474 12.7.1 格式化文件输出 474 12.7.2 格式化文件输入 475 12.8 错误处理 477 12.9 再探文本文件操作模式 478 12.10 二进制文件的输入输出 479 12.10.1 指定二进制模式 479 12.10.2 写入二进制文件 480 12.10.3 读取二进制文件 480 12.11 在文件中移动 488 12.11.1 文件定位操作 489 12.11.2 找出我们在文件中的位置 489 12.11.3 在文件中设定位置 490 12.12 使用临时文件 496 12.12.1 创建临时文件 496 12.12.2 创建唯一的文件名 496 12.13 更新二进制文件 497 12.13.1 修改文件的内容 502 12.13.2 键盘读取记录 503 12.13.3 将记录写入文件 504 12.13.4 文件中读取记录 505 12.13.5 写入文件 506 12.13.6 列出文件内容 507 12.13.7 更新已有的文件内容 508 12.14 文件打开模式小结 515 12.15 设计程序 516 12.15.1 问题 516 12.15.2 分析 516 12.15.3 解决方案 516 12.16 小结 522 12.17 习题 522 第13章 支持功能 523 13.1 预处理 523 13.1.1 在程序中包含头文件 523 13.1.2 外部变量及函数 524 13.1.3 替换程序源代码 525 13.1.4 宏替换 526 13.1.5 看起来像函数的宏 526 13.1.6 多行上的预处理指令 528 13.1.7 字符串作为宏参数 528 13.1.8 结合两个宏展开式的结果 529 13.2 预处理器逻辑指令 530 13.2.1 条件编译 530 13.2.2 测试指定值的指令 531 13.2.3 多项选择 531 13.2.4 标准预处理宏 532 13.3 调试方法 533 13.3.1 集成的调试器 533 13.3.2 调试阶段的预处理器 533 13.3.3 使用assert()宏 537 13.4 其他库函数 539 13.4.1 日期时间函数库 539 13.4.2 获取日期 543 13.5 小结 549 13.6 习题 549 附录A 计算机中的数学知识 551 附录B ASCII字符代码定义 559 附录C C语言中的保留字 565 附录D 输入输出格式指定符 567 前言   欢迎使用《C语言入门经典(第4版)》。研读本书你就可以成为一位称职的C语言程序员。许多方面来说C语言都是学习程序设计的理想起步语言。C语言很简洁因此无须学习大量的语法就能够开始编写真正的应用程序。除了简明易学外它还是一种功能非常强大的语言至今仍被专业人士广泛使用。C语言的强大处主要体现在它能够进行各种层次的程序设计硬件设备驱动程序操作系统组件大规模的应用程序都能胜任。事实上任何计算机都支持C语言编译器因此当我们学会了C语言就可以在任何环境下进行程序设计。最后一点掌握了C语言就为理解面向对象的C++语言奠定了良好的基础。.   积极热情的程序员都必将面对三大障碍即掌握适用于所有程序设计语言的术语理解如何使用一种语言的元素(而不仅仅只知道它们的概念)以及领会如何在实际环境中应用这种语言本书的目的就是将这些障碍降最低。   术语是专业人士与优秀的业余人士们进行交流时必不可少的因此掌握它们是必需的。本书会让你理解这些术语并自如地在各种环境下使用它们。这样才能更有效地使用大多数软件产品附带的文档且能轻松地阅读学习大多数程序设计语言的相关文献。   显然理解语言元素的语法作用是学习一门语言的关键不过认识语言的特性如何发挥作用如何应用它们也同等重要。在说明每种语言特性与特定问题的关系时本书采用实际应用的程序示例而不只是代码片断。这些示例提供了实践的基础你可以任意改动它们研究改动后的效果。   要理解在特定背景中的程序设计方法需要理解应用独立语言元素的机理。为了帮助理解它们本书每章最后都给出一个较复杂的程序该程序应用了本章前面已经学习的知识。这些程序可帮助你获得开发程序的能力信心了解如何综合运用各种语言元素。最重要的是它们能让你了解设计真实程序时会遇的问题以及如何管理实际的代码。   学习任何程序设计语言都要认识几件事情。首先要学的东西很多但是掌握了它们你会有极大的成就感。其次学习的过程很有趣你将体会这一点。第三你只有通过动手实践才能学会程序设计。最后学习程序设计语言比你想象的容易得多所以你肯定能掌握它。   如何使用本书   作者认为动手实践是最好的方法你应当立刻开始编写自己的第一个程序。每一章都有几个把理论应用于实践的程序这些示例是学习本书的关键。建议读者输入并运行文中的示例因为输入程序对记住语言元素有极大的帮助。此外你还应该做每章后面的练习。当你第一次使一个程序运行起来尤其是在试图解决自己的问题时快速的进展会使你有很大的成就感。..   刚开始学习的进展不会太快不过随着逐渐深入我们会加快学习的速度。每一章都会涉及很多基础知识因此在学习新的内容需要花些时间确保理解了前面学过的所有知识。实践各部分的代码并尝试实现自己的想法这是学习程序设计语言的一个重要部分。尝试修改书中的程序看看还能让它们做什么这是很有趣的。不要害怕尝试如果不明白某一点如何使用输入几种变体看看会出现哪些情况。好的学习方法是先通读整章全面了解其中介绍的内容然后再实践其中的所有程序示例。   你可能会觉得某些章末尾的程序非常难。如果第一次读这样的程序没有完全理解不必担心。第一次难免会觉得难以理解因为它们通常都是把你所学的知识应用了相当复杂的问题中。如果你真的不能理解可以略过那些章末尾的程序继续学习下一章然后再回头研究这些程序。甚至可以在学完全书后再来研究它们。所以演示这些程序是因为即使读完了本书它们对你来说仍是非常有用的资源。   本书读者对象   本书的目的是教你如何尽可能简单快速地编写有用的程序如果你属于下列情况那么本书就非常适合你:   ●刚接触程序设计但想直接深入了解C语言头开始学习程序设计及编写C语言程序。   ●以前有一点程序设计经历对其基本概念有一定了解也许曾经使用过BASIC或PASCAL。现在想学习C语言进一步提高自己的程序设计技能。   本书并未假设此前你对程序设计的知识有所了解不过本书会很快地基本概念转入实际应用。学完了本书你就为自己的C语言程序设计奠定了全面的基础。   使用本书的条件   要使用本书需要一台安装了C语言编译器库的计算机这样才能执行书中的示例还需要一个程序文本编辑器用于创建源代码文件。你使用的编译器要很好地支持C语言国际标准:ISO/IEC 9899。你还需要一个用于创建修改代码的编辑器可以采用任何纯文本编辑器创建源程序文件如Notepad或vi。不过采用专为编辑C语言代码设计的编辑器更有帮助。   要最大限度地发挥本书的功效你需要有学习的意愿、成功的渴望当学习不顺利觉得前途渺茫时还要有坚持下去的决心。几乎每个人在初次学习程序设计时都会在某处觉得迷茫。当你发现自己艰难地掌握了C语言的某个方面时要坚持下去迷雾一定会消散你会觉得为什么当初我不明白这一点呢也许你明白要做这些将会很难不过相信你一定会惊讶自己能在较短的时间内取得很大进步。本书会帮助你开始自己的实践使你成为成功的程序设计员。   本书采用的约定   本书的文本布局采用了许多不同的样式以便区分各种不同的信息。大多数样式表达的含义都很明显其中程序代码以类似下面的样子出现: .  int main(void)   {   printf("\nBeginning C");   return 0;   }   如果代码片段是前面的实例修改而来的修改过的代码行就用粗体显示如下所示:   int main(void)   {   printf("\nBeginning C by Ivor Horton");   return 0;   }   程序代码中还使用了各种“括号”。它们间的差别非常重要不能互换。本书中称( )为圆括号{ }为大括号[ ]为方括号。   本书源代码下载   Apress的站点可以下载本书中的所有代码练习的解决方案:http://www.apress.com。也可以访问www.tupwk.com.cn/downpage下载本书中的所有代码解决方案。...   
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付 29.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值