读懂严蔚敏C语言数据结构需要弄清楚的N个C语言语法

来源:互联网 发布:霸刀战神翅膀升级数据 编辑:程序博客网 时间:2024/05/16 00:55

摘要:

初学者如果对c语言的语法不熟悉,读严蔚敏版的c语言教材时常常会感觉糊里糊涂,在源代码的细节上晕晕乎乎,过于纠结于细节反而模糊了算法的本质。我第一遍读的时候就是这样,于是第二遍重读数据结构教材时,花了些功夫把书里常常用到而学C语言时容易忽略的语法整理了一下,和大家分享。在博客上看了一些文章,写得挺好,不过有些读着比较费劲,我努力以初学者的角度考虑把它们讲得明白易懂,并尽量采用与教材代码相关的简化过的例子说明。另外我也会跟若干我觉得不错的文章链接作为扩展阅读。随着学习的深入,这篇博文会查遗补缺不定期更新

内容包括:

(一). typedef的用法和使用意义。

(二). 函数中引用类型的参量(其实是C++里的,但教材里用得很频繁)。

(三). 字符型指针的特性。

(四). 动态数组的创建和使用。

(五). 指针数组。

(六) .字符型指针数组极其动态内存分配管理。

 

正文:

(一).typedef的用法和使用意义

typedef是用来重新定义类型名字的,可以把系统已有的类型名和自己定义的机构体名重新定义成一个自己瞧着顺眼的名字,引用时既可以使用原名也可以使用自己定义过的新名。如:

typedef int status;//严蔚敏版数据结构的源码里,把Int型定义成了status,status常常用于函数类型的定义,表示函数运行后返回的状态。

typedef struct  LNode{

ElemType data;

struct LNode *next; 

}*Link,*Position;

/*在使用这个结构体的时候,比如初始化一个该类型的结构体时,你既可以这样:struct  LNode  *node1;

也可以这样:Link node1;或者Position node1; 此外,在定义结构体时,红色的LNode位置的这个原名是可以省略的。

使用typedef的好处,有很多,教材里使用typedef主要作用有两点,

1是使代码容易记忆,提高代码可读性;

2是方便结构体的引用(对比赋值方法1和2,就可以发现能省下一个struct关键字= =|||)。此外有兴趣可以阅读百度文库中关于c语言typedef的使用http://wenku.baidu.com/view/cd7a472d2af90242a895e570.html。*/

 

(二)函数中引用类型的参量

来看一段代码:

void fun1(int x) {   x=73;   printf("%d\t",x);  } //普通类型参量

void fun2(int &x) {   x=73;   printf("%d\t",x);  } //引用类型参量

void main

{

int a=87;

int b=87;

fun1(a);

fun2(b);

printf(“%d\t”,a);

printf("%d\t",b);

}

打印的结果是:73      73      87      73,so,显然使用引用类型的参量时,是将变量的地址作为形参传入的,当函数改变形参时,原变量的值也会发生变化,而普通的形参,即使函数中改变了形参的大小,原变量的值也不会发生任何变化。所以教材里讲 &型参量可以返回变量的值就是这个意思了。

 

(三)字符型指针的特性

如果对指针的特性还晕乎乎的,请先翻看原来学c语言的教材看看指针的介绍,弄清楚基本概念。接下来讲讲字符型指针的特性。

char *text ;   /*c语言中对于字符串的处理是把字符串作为一个字符型数组处理的,对于形如左边的字符串指针,text指向的是一个字符型数组的首元素地址,也就是相当于text[ ]*/

text="stay foolish,stayhungry." /*所以可以直接将一个字符串赋给text指针,相当于text[ ]=”字符串“;*/

text[i]=”v";  /*也可以这样把一个字符赋给数组的第i个元素*/

要点是一出现糊涂时,谨记字符型指针是一个字符型数组,是数组,数组!就Ok了。

 

{四)动态数组的创建和使用

我记得自己学c语言的时候,老师对于动态数组这个概念好像就是轻描淡写地几句话带过,我自己也没弄清楚,因为当时不知道这个东西做什么用。接触了一点电子开发的知识之后才发现这个东西非常有用,不管是单片机开发还是其他高级一点的嵌入式开发,基本上芯片的内存大小是十分有限的,你必须精打细算地来,才能免于因为内存不足而崩溃。我们初学c的时候,都是随随便便直接建一个数组,比如:int numchain[MAXNUM]; 这样创建完调用啊赋值啊修改啊,都没问题,程序跑得很欢乐,但是有时创建某个数组在程序里只是在某个局部使用,直接创建的数组使用完后,数组的内存空间还占用在硬件物理内存中,也就是那一块内存被占用了不允许放入其他数据或操作,如果一个程序比较大,里头这样的死数组很多,那么程序跑着跑着就发现硬件内存不足,就崩溃了,而这个bug是隐性的,不好检查。所以最好的习惯是养成使用动态数组的习惯。

那么动态数组怎么 用呢?看代码段:

#include <stdlib.h> //malloc free等函数被藏在这个库里头,需要先include一下。

void main

{

char *text;//创建一个字符型指针,也即一个字符型数组。

text=(char*)malloc(10*sizeof(char));

/*以教材里出现频率最高的malloc函数为例,我们给text指针动态创建一个内存空间,这个内存空间是在一个叫堆的系统空间中的,因为text指针是字符型,而malloc本身的返回值是一个十六进制的地址,所以应该用红色部分代码将它转换一下。malloc多大的空间呢,就是10乘以蓝色部分代码,即10个字符大小。*/

text="I'm happy.“;

/*注意此时赋值字符串长度不应该超过10,虽然超过10,系统虽然也可以编译执行,但超过部分的字符串是随机分配到系统的某个内存区域的,当用free()释放内存后,超过10的那部分字符串所占的内存并未释放干净,成为残留的内存垃圾。*/

free(text);//释放内存,使用了这个函数,动态分配内存机制才算有意义。

}

所以,总结下,动态数组,其实就是用malloc函数给数组分配存储空间,当数组使用完后,用free()把他释放掉。so easy,isn't it?

除了malloc之外,c语言中还有 calloc 和realloc函数,拓展阅读请点击链接:

http://blog.csdn.net/bigloomy/article/details/6615012

 

(五)指针数组

简单的说,指针数组的意思就是有那么一种数组,它的每个元素都是指针(即每个元素都是一个地址)。

譬如:char *text[5]; 

这行代码的意思就是规定一个字符型指针数组text,text有五个元素text[0]~text[4],每个元素都是字符型的指针。我们上面已经说过了,每个字符型的指针都可以视为一个字符型数组,所以这个指针数组实际上是一个二维数组 text[5][ ],text[i]可以用来赋给一个字符串,也就是说这个指针数组里有五个字符串,text[0]~text[4],你可以这样操作:

text[0]=”Hello ";

text[1]="world ";

text[2]=",";

text[3]="hello ";

text[4]="073";

非常easy,不是吗?所以碰到教材里出现的诸如:

typedef struct{

char *item[ ];

int last;

}WordListType; 

认真分析一下就不是问题了,譬如,对于上面的结构体做如下操作:

WordListType wdlist;//教材P88中间位置

p=*(wdlist.item+i);//这行代码不是等价于p=*(wdlist.item[i]);么?表示把wdlist.item[i]所指向的的地址里的字符串赋值给p,p是一个字符指针,char *p;

 

(六).字符型指针数组极其动态内存分配管理

好吧,这条其实就是上面(三)(四)(五)点的综合。假设现在要建立一个反应文本段落数据结构,在一个段中有若干行,每行都是一个字符串,应该采用什么样的数据结构,对这个数据结构进行初始化、修改、打印等操作时,内存分配应该怎么做呢?我们把上面的内容综合起来写段代码,作为总结吧:

#include<stdlib.h>
#include<iostream.h>//c++输入输出流比c的标准输入输出方便一点,反正在pc上调试效果一样,遂弃用<stdio.h>。


typedefstruct{
         char *text[5];//不妨设段落最大有5行吧。
         int line;//用来标识当前的行数。
}paragraph;


paragraphpara;//全局变量para1


void main()
{
         for(para.line=0;para.line<5;para.line++)//为段落分配动态内存空间。
         {
         para.text[para.line]=(char*)malloc(80*sizeof(char));//假设每行最大字符数为80个。
         }
         for(para.line=0;para.line<5;para.line++)//输入每行的字符串,以回车结束改行输入。
         {        cout<<"请依次输入第"<<para.line+1<<"行的字符串"<<endl;
                   cin.getline(para.text[para.line],80*sizeof(char));//这是用了c++的一个溜输出函数,可以实现输入整行,以回车为标识符。
         }
         for(para.line=0;para.line<5;para.line++)//打印每一行。
         cout<<para.text[para.line]<<endl;
         for(para.line=0;para.line<5;para.line++)//释放每一行的内存空间
         free(para.text[para.line]);
}


原创粉丝点击