暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一起talkC

yBmZlQzJ 2023-12-16
431

Cover

Table of Contents

前言

第 1 章 一起talk C栗子吧(第一回:C语言实例概述)

第 2 章 一起talk C栗子吧(第二回:C语言实例--判断闰年)

第 3 章 一起talk C栗子吧(第三回:C语言实例--求阶乘)

第 4 章 一起talk C栗子吧(第四回:C语言实例--斐波那契数列)

第 5 章 一起talk C栗子吧(第五回:C语言实例--数组巧妙赋值)

第 6 章 一起talk C栗子吧(第六回:C语言实例--生成随机数)

第 7 章 一起talk C栗子吧(第七回:C语言实例--进制转换)

第 8 章 一起talk C栗子吧(第八回:C语言实例--素数)

第 9 章 一起talk C栗子吧(第九回:C语言实例--最大公约数)

第 10 章 一起talk C栗子吧(第十回:C语言实例--最小公倍数)

第 11 章 一起talk C栗子吧(第十一回:C语言实例--文件组织结构)

第 12 章 一起talk C栗子吧(第十二回:C语言实例--单链表一)

第 13 章 一起talk C栗子吧(第十三回:C语言实例--单链表二)

第 14 章 一起talk C栗子吧(第十四回:C语言实例--循环链表)

第 15 章 一起talk C栗子吧(第十五回:C语言实例--双向链表)

第 16 章 一起talk C栗子吧(第十六回:C语言实例--栈一)

第 17 章 一起talk C栗子吧(第十七回:C语言实例--栈二)

第 18 章 一起talk C栗子吧(第十八回:C语言实例--输出十六进制)

第 19 章 一起talk C栗子吧(第十九回:C语言实例--位操作)

第 20 章 一起talk C栗子吧(第二十回:C语言实例--括号匹配)

第 21 章 一起talk C栗子吧(第二十一回:C语言实例--表达式求值)

第 22 章 一起talk C栗子吧(第二十二回:C语言实例--队列一)

前言

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。

这一次我给大家带来的是:C栗子。哈哈!你是要请我们吃例子吗?当然不是了,现在还不是吃栗子的季节 呢。C“栗子”其实是C例子的谐音,取这么个名字就是为了叫着顺口一些,再说了咱们这是在说章回体小说, 给小说起个漂亮的名字是理所当然的。大家以后看到C栗子就要想到我们的的小说主题:C语言实例。

在C栗子小说中我们会说一C语言编程中的例子,小到求素数,大到遍历树,甚至是一些工程项目,都会在 小说里介绍。例子的代码,我会写到正文内容中,希望大家能够和我一起愉快地走完这段旅程。

1

一起talk C栗子吧(第一回:C语言实例概述)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C语言实例吧!

看官们,大家好!我们又见面了。这一次我给大家带来的是:C栗子。哈哈!你是要请我们吃例子吗?当 然不是了,现在还不是吃栗子的季节呢。C“栗子”其实是C例子的谐音,取这么个名字就是为了叫着顺口一 些,再说了咱们这是在说章回体小说,给小说起个漂亮的名字是理所当然的。大家以后看到C栗子就要想到 我们的的小说主题:C语言实例。

在C栗子小说中我们会说一C语言编程中的例子,小到求素数,大到遍历树,甚至是一些工程项目,都会在 小说里介绍。例子的代码,我不会再写到正文内容中,但是我会上传到我的资源中,供大家下载。希望大 家能够和我一起愉快地走完这段旅程。

看官们,为什么要选择这么一个话题来说呢?原因有以下几点:

  • 1.有一段时间不用C语言了,对C语言的基本语法有点生疏。写一些C语言实例来回顾C语言。
  • 2.有些实例使用的算法,时间长了后,有点生疏。通过写一些C语言实例来回顾这些算法。
  • 3.以前都是在Windows上写例子,这一回在Linux上写例子,希望加一些Linux的元素在实例中。
  • 4.以前写的程序算是学生版程序,在性能上不太好,而且不够健状。这次写工程版实例。

各位看官,此回算作C栗子章回体小说的开始。欲知后事如何,且听下回分解。

2

一起talk C栗子吧(第二回:C语言实例--判断闰年)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提,
言归正转。让我们一起talk C语言实例吧!

看官们,上一回中咱们给小说做了个开头,这一回咱们正式说C例子,这回说的例子是:判断闰年。

看官们,闰年是什么?这个是地理天文方面的概念。如果不明白的话,自己百度去,哈哈。我也偷一把懒。
看官们,判断闰年的方法有两种:

  • 1.如果某年能被4整除,但是不能被100整除,那么这一年就是闰年。
  • 2.如果某年能被400整除,那么这一年就是闰年。

看官们看到整除肯定想到除法了吧,其实C程序中的除法运算和数学中的除法运算不一样,C程序中除法运
算只会取整数,小数点后面的小数会被舍弃。比如:5/3=1.666...。这是数学运算的结果,C程序中的结果
是1.因为它把1后面的小数部分舍弃了。所以我们不能使用除法运算来判断闰年。哪怎么判断?看官莫急。
在C程序中提供了取余运算,运算符号是%。取余运算就是取出除法运算中的余数。比如:5/3的余数是2.
那么5%3的运算结果是2.大家想想,对一个数字进行取余运算后,如果运算结果为0,这代表着什么意思?
“这表示这个数字可以被另外一个数字整除”。这位看官说的对。比如,4%2=0就可以说明4能被2整除。看
官们,话都说到这里了,大家现在明白如何判断闰年了吧。

看官们,详细的代码如下,共享给大家参考使用:

1 /* **************************
2 * For Leap Year
3 * *************************/
4 #include<stdio.h>
5
6 #define SUCCESS 1
7 #define FAILED 0
8 #define BAD_PARAMETERS -1
9
10 int LeapYear(int year)
11 {
12 int result = 0;
13 if(year <=0 || year >9999)
14 {
15 printf("The year is not a correct year,(between 0 - 9999 )\n");
16 return BAD_PARAMETERS;
17 }
18
19 if( (year % 400 == 0)
20 || ((year % 4 == 0) && (year % 100 != 0)) )
21 return SUCCESS;
22 else
23 return FAILED;
24
25 }
26 int main()
27 {
28 int year, result;
29 year = result = 0;
30
31 printf("Please input a year,such as 2015 \n");
32 scanf("%d",&year);
33 result = LeapYear(year);
34
35 if(result == SUCCESS)
36 printf("It is a Leap Year \n");
37 else if(result == FAILED)
38 printf("It is not a Leap Year \n");
39 else
40 printf("Please check you input years \n");
41
42 return 0;
43 }

各位看官,关于判断闰年的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

3

一起talk C栗子吧(第三回:C语言实例--求阶乘)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C语言实例吧!

看官们,上一回中咱们说的是判断闰年的例子,这一回咱们说的例子是:求阶乘。

看官们,阶乘是数学中的一种运算,通常使用感叹号来表示阶乘。比如:3!表示3的阶乘。阶乘的定义是这 样的:正整数n=0时,n的阶段乘为1,n>0时,n的阶乘为n*(n-1)!。

看官们,我在程序中使用了两种方法来求阶乘。一种是递归方法,另外一种是循环方法。正文中就不写代 码了,详细的代码如下,请大家参考使用:

1 /* **************************
2 * For Factorial
3 * *************************/
4 #include<stdio.h>
5
6 #define SUCCESS 1
7 #define FAILED 0
8 #define BAD_PARAMETERS -1
9
10 //使用递归方法来求阶乘
11 int Factorial(int n)
12 {
13 if(n < 0)
14 return BAD_PARAMETERS;
15
16 if(n == 0)
17 return 1;
18 else
19 return n*Factorial(n-1);
20 }
21
22 //使用循环方法来求阶乘
23 int f(int n)
24 {
25 int res = 1;
26 int i = 0;
27
28 if(n < 0)
29 return BAD_PARAMETERS;
30
31 if(n == 0)
32 return 1;
33
34 for(i=0;i<n;++i)
35 res *= (i+1);
36
37 return res;
38 }
39
40 int main()
41 {
42 int result = 0;
43
44 result = Factorial(5);
45 if(result > 0)
46 printf("%d \n",result);
47
48 result = f(5);
49 if(result > 0)
50 printf("%d \n",result);
51
52 return 0;
53 }

补充一点:循环和递归是比较常见的方法,所以这里不做过多的说明。不过,在工程中尽量少用递归,一 般情况下,递归可以解决的问题,可以使用循环方法去解决。不推荐递归的理由是因为,递归的性能稍微 差一些,尤其在递归的嵌套比较深的时候。

各位看官,关于判求阶乘的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

4

一起talk C栗子吧(第四回:C语言实例--斐波那契数列)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C语言实例吧!

看官们,上一回中咱们说的是求阶乘的例子,这一回咱们说的例子是:斐波那契数列。

看官们,斐波那契数列是以数学家斐波那契数列的姓来命名的。斐波那契数列的定义:数列的第0项和第1项 为1,第n项为第n-1项和第n-2项的和。用数学公式表示出来就是:f(n)=f(n-1)+f(n-2),其中(n>1), f(n)=1;(n=0,1).看官们,我在程序中使用了递归方法来实现斐波那契数列,这点和求阶乘一样。不过 没有像求阶乘一样使用循环方法去实现斐波那契数列。详细的代码如下:请大家参考:

1 /* **************************
2 * For Fibonacci
3 * *************************/
4 #include<stdio.h>
5
6 #define SUCCESS 1
7 #define FAILED 0
8 #define BAD_PARAMETERS -1
9
10 //使用递归方法来求阶乘
11 int Fibonacci(int n)
12 {
13 if(n < 0)
14 return BAD_PARAMETERS;
15
16 if(n == 0 || n==1)
17 return 1;
18 else
19 return (Fibonacci(n-1)+Fibonacci(n-2));
20 }
21
22
23 int main()
24 {
25 int result = 0;
26
27 result = Fibonacci(7);
28 if(result > 0)
29 printf("%d \n",result);
30
31 return 0;
32 }

补充一点:斐波那契数列和求阶乘背后的算法思想是一样的。它们都使用了递归的思想。

各位看官,关于斐波那契数列的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

5

一起talk C栗子吧(第五回:C语言实例--数组巧妙赋值)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是斐波那契数列的例子,这一回咱们说的例子是:数组巧妙赋值。

看官们,大家如果学习过C语言的话,应该知道给变量赋值的方法为:a=b。它表示把变量b的值赋值给变 量a。当然变量a和b要事先定义好,而且最好是同一种类型。但是a=b这种赋值方法对数组类型的变量就 不起作用了。大家可以看我写的例子。如果把例子中52行的注释去掉的话,就引起编译错误。不过看官们 先不要着急。我在例子中使用了一种方法,可以巧妙地使用a=b这种形式给变量赋值。大家知道,结构体 变量可以使用a=b这种形式去赋值,于是我就在结构体中定义了一个数组类型的变量,当使用结构体变量 以a=b这种形式赋值时,就能把结构体中数组类型的成员也一起赋值,从而巧妙地使用a=b这种形式给数组 类型的变量赋值。

看官们,详细的代码如下,请大家参考:

1 /* **************************
2 * For ArrayValue-使用a=b这种形式给数组赋值
3 * *************************/
4 #include<stdio.h>
5
6 #define LENGTH 5
7
8 typedef struct _array
9 {
10 int a[LENGTH];
11 }Array;
12
13 int main()
14 {
15 int i = 0;
16 int a1[LENGTH] = {0};
17 int a2[LENGTH] = {0};
18 Array a3,a4;
19
20 // init array
21 for(i=0; i<LENGTH; ++i)
22 a1[i] = i+1;
23
24 //show the value of array
25 for(i=0; i<LENGTH; ++i)
26 printf("%d \t",a1[i]);
27
28 printf("\n");
29
30 //init the struct value
31 for(i=0; i<LENGTH; ++i)
32 a3.a[i] = i+1;
33
34 //show the struct value
35 printf("---the value of a3 --- \n");
36 for(i=0; i<LENGTH; ++i)
37 printf("%d \t",a3.a[i]);
38
39 printf("\n");
40
41 //init the struct value
42 for(i=0; i<LENGTH; ++i)
43 a4.a[i] = i+5;
44
45 //show the struct value
46 printf("---the value of a4 --- \n");
47 for(i=0; i<LENGTH; ++i)
48 printf("%d \t",a4.a[i]);
49
50 printf("\n");
51
52 //a2 = a1;
53 a4 = a3;
54 printf("---the value of a4 --- \n");
55 for(i=0; i<LENGTH; ++i)
56 printf("%d \t",a4.a[i]);
57
58 printf("\n");
59
60 return 0;
61 }

各位看官,关于数组巧妙赋值的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

6

一起talk C栗子吧(第六回:C语言实例--生成随机数)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是数组巧妙赋值的例子,这一回咱们说的例子是:生成随机数。

看官们学过C语言的话,还记得如何生成随机数吧。忘记了?那么我们一起说说。使用rand()函数可以生 成随机数,不过,它生成的随机数是一种伪随机数。因为重复执行程序的话,得到的随机数是一样。生成 随机数的函数是通过一个固定的数值来计算随机数的,我们可以通过srand()函数来指定这个数值,这样 生成的随机数就是真正意义上的随机数了。我在示例程序中使用时间当作srand()函数的值,这样的话, 生成的随机数就显得更加随机了。

看官们,详细的代码如下,请大家参考:

1 /* **************************
2 * For CreateRandom
3 * *************************/
4 #include<stdio.h>
5 #include<time.h>
6
7
8 int main()
9 {
10 int iVal = 0;
11
12 iVal = rand()% 10;
13 printf(" the random value is :%d \n",iVal);
14
15 srand(time(NULL));
16 iVal = rand()% 10;
17 printf(" the random value is :%d \n",iVal);
18
19 return 0;
20 }

各位看官,关于生成随机数的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

7

一起talk C栗子吧(第七回:C语言实例--进制转换)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是生成随机数的例子,这一回咱们说的例子是:进制转换。说到进制估计大家 都不陌生,计算机中的进制有二进制,八进制,十进制,十六进制。

今天咱们将要说的是十进制如何转换成二进制,八进制和十六进制。在这里我把写程序的步骤和算法思路 写出来供大家参考。

  • 1.获取用户想要转换的数值和想到转换的进制。这里要检查输入是否正确。这是程序健壮性的体现。
  • 2.依据用户输入的不同进制,进行不同的转换。在代码中,我把转换过程封装成了一个函数。
  • 3.输出转换后的结果。输出转换后的结果也封装成了一个函数。

看官们,咱们接下来说说如何进行进制转换,也就是进制转换函数的内容。

  • 1.使用被转换的数值模转换进制,并且把模的结果保存起来。比如被转换的数值为9,转换进制为2.那么模的 结果 =9%2.该步骤要执行多次,具体的次数由步骤2决定。把每次执行的结果从左到右排列成一排就是转换 进制的结果。在程序中使用一个数组来保存结果。
  • 2.使用被转换的数值除以转换进制,并且判断商是否为0.如果不为0重复步骤1和2,直到商等于0为止。

看官们,说完了转换函数,咱们接下来说说输出进制转换结果的函数。

  • 1.输出结果时与转换转换函数中保存结果的顺序正好相反。保存是沿着数组头到尾的方向,输出时是沿着 数组尾到头的方向。两个方向正好相反。
  • 2.十六进制的输出结果中包含A-F这些字符,所以专门对它们进行了转换。

看官们,详细的代码如下,请大家参考:

1 /* **************************
2 * For Hex conversion
3 * *************************/
4 #include<stdio.h>
5
6 /*convert function
7 *Parameter a is used for saving converting result
8 *Parameter iVal is a value ,which will be converted.
9 *Parameter base is a base value ,
10 */
11
12 #define SUCCESS 0
13 #define FALSE 1
14 #define BIT 32
15
16 int convert(int *a,int iVal,int base)
17 {
18 int index = 0;
19 int res = 0;
20
21
22 if(NULL == a)// check the pointer
23 {
24 printf("null pointer \n");
25 return FALSE;
26 }
27
28 if( 0 == base) //check the base, 0 can't be used for division
29 {
30 printf("bad value of base \n");
31 return FALSE;
32 }
33
34 res = iVal;
35 //the main algorithm
36 do
37 {
38 *(a+index) = res % base;
39 res /= base;
40 ++index;
41 }while(res != 0);
42
43 return SUCCESS;
44 }
45
46 int showConvertResult(int *a)
47 {
48 int index = 0;
49
50 if(NULL == a)// check the pointer
51 {
52 printf("null pointer \n");
53 return FALSE;
54 }
55
56 for(index=BIT; index>0; --index)
57 {
58 if(index %4 == 0)
59 printf(" ");
60
61 switch( *(a+index-1) ) // input hex character
62 {
63 case 10:
64 printf("%c",'A');
65 break;
66 case 11:
67 printf("%c",'B');
68 break;
69 case 12:
70 printf("%c",'C');
71 break;
72 case 13:
73 printf("%c",'D');
74 break;
75 case 14:
76 printf("%c",'E');
77 break;
78 case 15:
79 printf("%c",'F');
80 break;
81 default:
82 printf("%d",a[index-1]);
83 break;
84 }
85 }
86
87 printf("\n");
88
89 return SUCCESS;
90 }
91
92 int main()
93 {
94 int base = 0;
95 int iVal =0;
96 int result = 0;
97 int hex[BIT] = {0}; // the max bit is 32
98
99 printf("please input a number for conversion: \n");
100 if(0 == scanf("%d",&iVal))
101 {
102 printf("Input number is not right \n");
103 return FALSE;
104 }
105
106 printf("please select a char for conversion: \n");
107 printf(" \t ->Decimal conver to Binary:input 1 : \n");
108 printf(" \t ->Decimal conver to Octonary:input 2 : \n");
109 printf(" \t ->Decimal conver to Hex:input 3 : \n");
110
111 if(0 == scanf("%d",&base))
112 {
113 printf("Input number for selecting is not right \n");
114 return FALSE;
115 }
116
117 switch(base)
118 {
119 case 1:
120 result = convert(hex,iVal,2);
121 break;
122
123 case 2:
124 result = convert(hex,iVal,8);
125 break;
126
127 case 3:
128 result = convert(hex,iVal,16);
129 break;
130
131 default:
132 break;
133
134 }
135
136 if(result == FALSE)
137 return FALSE;
138 else
139 {
140 showConvertResult(hex);
141 return SUCCESS;
142 }
143 }

各位看官,关于进制转换的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

8

一起talk C栗子吧(第八回:C语言实例--素数)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是进制转换的例子,这一回咱们说的例子是:素数。

素数又叫质数,在大于1的自然数中,如果一个正整数除了1和它本身外,不能被其它自然数整除,那么这 个数就是一个素数。素数比较多,所以咱们例子中只展示从1到100这个范围内的素数。

看官们觉得这个例子算是简单,我也觉得比较简单。只要把范围内的数从头到尾遍历一下,判断是否能被 除1和自身以外的其它的数整除就可以。我专门说素数这个例子是为想介绍另外一种方法,该方法可以节省 遍历的时间,提高程序运行效率。我在例子中使用的原理:假如有一个正整数n,除了1和它本身外,用从2 到正整数n的平方根之间所有的正整数数去除 n,如果n都不能被整除。那么正整数n就是素数。使用该方法 可以减少遍历的数目,进而提高程序的效率。

看官们,详细的代码如下,大家可以参考:

1 /* **************************
2 * For Prime Number
3 * *************************/
4 #include<stdio.h>
5
6 #define N 100
7
8 int main()
9 {
10 int index,step;
11 int i = 0;
12 int res[N]= {0};
13
14 index = step = 0;
15
16 printf("show the PrimeNumber of [1--%d]i\n",N);
17
18 for(index=2; index <=N; ++index)
19 {
20 for(step=2; step*step <= N; ++step)
21 {
22 if( index != step && index % step == 0 ) //如果不第一个判断条件,那么会有遗漏
23 break;
24 }
25
26 if(step*step > N)
27 {
28 res[i] = index;
29 ++i;
30 }
31 }
32
33 while(i-- >0)
34 printf("%d \n",res[i]);
35
36 return 0;
37 }

各位看官,关于素数的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

9

一起talk C栗子吧(第九回:C语言实例--最大公约数)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是素数的例子,这一回咱们说的例子是:最大公约数。

看官们,最大公约数也叫最大公因数。两个整数中的公约数有好几个,这些公约数中最大的一个就叫作最 大公约数。当然了,这是数学中的一个概念,如果不明白了,可以查阅相关的数学知识。

最大公约数的求法有好几种,最常用的是辗转相除法,也叫欧几里德算法。该算法的原理如下:

  • 如果正整数a除以正整数b所得的余数为c,那么a和b的最大公约数与b和c的最大公约数相等。
  • 重复步骤1中的操作,继续求b和c的最大公约数。如此反复,直到余数等于0为止。

看官们,详细的代码如下,请大家参考

1 /* **************************
2 * For Greatest Common Divisor
3 * *************************/
4 #include<stdio.h>
5
6 int main()
7 {
8 int a,b,gcd,temp,ta,tb;
9 int mod;
10 a = b = gcd = temp = ta = tb = mod = 0;
11
12 printf("Please input 2 number for get the GCD of them .\n");
13 scanf("%d %d",&a,&b);
14 if(a <0 || b < 0)
15 {
16 printf("bad input number \n");
17 return 0;
18 }
19
20 if(a < b)
21 {
22 temp = a;
23 a = b;
24 b = temp;
25 }
26
27 ta = a;
28 tb = b;
29 mod= a % b;
30 while(mod != 0)
31 {
32 ta = tb;
33 tb = mod;
34 mod = ta % tb;
35 }
36
37 printf("the GCD of %d and %d is:%d \n",a,b,tb);
38
39 return 0;
40 }
41

各位看官,关于最大公约数的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

10

一起talk C栗子吧(第十回:C语言实例--最小公倍数)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是最大公约数的例子,这一回咱们说的例子是:最小公倍数。

看官们,最小公倍数和最大公约数类似。两个整数中的公倍数有好多个,这些公约数中最小的一个就叫作 最小公倍数。当然了,这是数学中的一个概念,如果不明白了,可以查阅相关的数学知识。

最小公倍数的求法有好几种,最常用的是通过最大公约数来求。因为两个数的最大公约数乘以它们的最小 公倍数等于这两个数的积。所以通常先求出两个数的最大公约数,然后用两个数的积除以它们的最大公约 数就得到了它们的最小公倍数。

看官们,详细的代码如下,请大家参考:

1
2 /* **************************
3 * For Least Common Multiple
4 * *************************/
5 #include<stdio.h>
6
7 int main()
8 {
9 int a,b,gcd,temp,ta,tb;
10 int mod,res,lcm;
11 a = b = gcd = temp = ta = tb = mod = res = lcm = 0;
12
13 printf("Please input 2 number for get the LCM of them .\n");
14 scanf("%d %d",&a,&b);
15 if(a <0 || b < 0)
16 {
17 printf("bad input number \n");
18 return 0;
19 }
20
21 if(a < b)
22 {
23 temp = a;
24 a = b;
25 b = temp;
26 }
27
28 ta = a;
29 tb = b;
30 mod= a % b;
31 while(mod != 0)
32 {
33 ta = tb;
34 tb = mod;
35 mod = ta % tb;
36 }
37
38 lcm = (a * b)/tb; // a和b 积除以gcd等于lcm
39 printf("the LCM of %d and %d is:%d \n",a,b,lcm);
40
41 return 0;
42 }
43

各位看官,关于最小公倍数的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

11

一起talk C栗子吧(第十一回:C语言实例--文件组织结构)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是最小公倍数的例子,这一回咱们不说具体的例子,咱们说一下C例子中的文件 组织方法以及实际开发软件时的“文件组织结构方法”。

看官们,在我前面写的例子中,只有一个源文件(也就是通常看到的.c文件)。我没有单独写头文件(也 就是通常看到的.h文件),而是把头文件的内容放到了源文件中。主要是这些例子中关于头文件的内容不 多,如果单独写一个头文件。有点多余,所以就把头文件和源文件的内容都放到一起了。在实际的软件开 发中,头文件的内容需要和源文件的内容分开写,这样可以很好地管理文件。试想一下,在实际的软件开 发过程中,不会像我在这里写的例子一样,只有几十行代码,一个文件就能搞定。实际的软件开发中会有 成千上万行代码,文件数量也有成百上千个,这么多文件放在一起,如果没有好的管理方法,那么会给软 件开发带来很大的困难,所以实际软件开发中需要把头文件和源文件分开来写。

头文件中通常包含文件引用,宏定义,全局变量,结构体,枚举声明,函数声明。源文件中通常包含函数 的实现,程序的主体逻辑。这是一种通用的文件组织结构方法。

在我写的C例子中,如果头文件中的内容少,我就不去专门写一个头文件,而是把所有的内容都放到源文件 中。这样做虽然不符合文件组织结构方法,但是比较方便实用。如果头文件中的内容比较多,那么我会单 独写一个头文件,把头文件中的内容和源文件中的内容分开写。这样做是为了方便管理文件,而且符合通 用的文件组织结构方法。

各位看官,关于文件组织结构的方法咱们就说到这里。欲知后面还有什么例子,且听下回分解。

12

一起talk C栗子吧(第十二回:C语言实例--单链表一)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们没有说具体的例子,而且是说了例子中的文件组织结构。这一回咱们继续说C例子, 说的例子是链表,更准确的说法叫作单链表。咱们不但要说C例子,而且会在例子中使用上一回中说过的 文件组织结构,就当作是举例说明文件组织结构的使用方法。 有点一石二鸟的感觉,哈哈。

链表定义:看官们,所谓的链表其实就是一组元素通过一定的方式链接在一起。比如我们坐的火车和地铁, 就是把一节节的车厢链接在一起才形成了一个火车或者地铁。在软件开发中常用的链表有单链表,双向链 表和循环链表。今天,我们主要说的是单链表,其它类型的链表在后面的章回中依次介绍。

链表实现:单链表有两种实现方法,一种是线性存储,一种是链式存储。这么说,大家可能可能觉得有点 抽象,不容易理解。没关系,咱们用举个生活中的例子说明。线性存储可以看作元素一个接一个的排列在 一起,我们日常生活中的排队就可以看作是线性存储,队列中的每个人看作是链表中的元素,排队时每个 人都是一个跟着一个,生怕中间有个空间被其它人插队,这种一个跟着一个的方式可以看作是线性存储。 在写程序的时候,使用数组来表示单链表的线性存储。数组中的元素大小相同,而且各个元素依次排列在 一起,通过数组下标可以访问数组中的元素。链式存储可以看作元素通过一条链连接在一起,我们日常生 活中马路上的车队可以看作是链式存储。每当上下班高峰的时候,马路上的车辆都是一个接一个地在马路 上缓慢行走,远远望去就是一条汽车链。每辆汽车可以看作链表中的元素,而这条汽车链就是通过马路连 接在一起的。当然了,这些汽车里有一些公交车,它们会在路边公交车站临时停车,供乘客上下车。但是 不会影响其它汽车在马路上行走。我们把公交车停在公交车站的当作从汽车链中删除一个元素。当公交车 离开公交车站回到马路上时,可以看作是向汽车链中插入一个元素。看官们能感觉到公交车在公交车站的 停靠,对汽车链的影响非常小。这也体现了单链表的好处,删除或者插入元素很方便。哈哈,把日常生活 中的东西和链表这个抽象的概念结合起来,是不是感觉理解容易了呢?

看官们,关于的单链表的例子,详细的代码如下,大家可以参考。在例子中能看到:通过数组来实现单链 表的顺序储存方式,同时提供了单链表常用的功能:遍历链表,插入和删除元素,查找元素。

1 /* **************************
2 * Head file of Single List
3 * *************************/
4 #ifndef SINGLE_LIST_H
5 #define SINGLE_LIST_H
6
7 #include<stdio.h>
8
9 #define SIZE 10
10
11 typedef int LIST; //把int当作List类型,实际中可以使用其它的类型或者自己定义一个List类型,不过不能是使用struct复合类型
12
13 int ListSize = 0; //定义List的实际长度,它不能比SIZE大,因为实际只有SIZE个空间
14
15 //声明函数原型,这里有插入,删除,查找链表元素的函数,以及遍历链表的函数
16 int ListInsert(LIST *list,LIST a);
17 int ListDelete(LIST *list,LIST a);
18 int ListTravel(LIST *list);
19 int ListFindElement(LIST *list,LIST a);
20
21 #endif /*SINGLE_LIST_H*/

1 /* **************************
2 * Source file of Single List
3 * *************************/
4 #include"Ex010_SingleList.h"
5
6 //函数的实现,和主函数放到了一个源文件中,实际中最好不要放在一起
7 int ListTravel(LIST *list)
8 {
9 int index =0;
10
11 if(NULL == list)
12 return 1;
13
14 for(index=0; index<ListSize && index < SIZE; ++index)
15 printf("%d ",list[index]);
16
17 printf("\n");
18
19 return 0;
20 }
21
22 //查找到元素后返回无数在链表中的位置,即数组的下标,否则返回-1
23 int ListFindElement(LIST *list,LIST a)
24 {
25 int index = 0;
26
27 if(NULL == list)
28 return -1;
29
30 for(index=0; index<ListSize && index < SIZE; ++index)
31 {
32 if(list[index] == a )
33 return index;
34 }
35
36 return -1;
37 }
38
39 int ListInsert(LIST *list,LIST a)
40 {
41 if(NULL == list)
42 return 1;
43
44 if( ListSize >= SIZE)
45 {
46 printf("The list is full \n");
47 return 1;
48 }
49
50 list[ListSize++] = a; //从List尾部插入元素
51
52 return 0;
53 }
54
55 int ListDelete(LIST *list,LIST a)
56 {
57 int index = 0;
58
59 if(NULL == list)
60 return 1;
61
62 if( ListSize < 0 )
63 {
64 printf("The list is empty\n");
65 return 1;
66 }
67
68 index = ListFindElement(list,a);
69
70 if(-1 != index )
71 {
72 if(index == SIZE-1) //链表中最后一个元素的时候这样删除
73 {
74 list[index] = 0;
75 ListSize -= 1;
76 return 0;
77 }
78
79 index += 1;
80 while(index <= ListSize )
81 {
82 list[index-1] = list[index];
83 index++;
84 }
85 list[index-1] = 0;
86 ListSize -= 1;
87 }
88
89 return 0;
90 }
91
92 //程序主要逻辑部分
93 int main()
94 {
95 int i = 0;
96 LIST List[SIZE] = {0}; //定义了一个SIZE大小的链表,通过数组实现顺序存储
97
98 for(i=0; i<SIZE; ++i)
99 ListInsert(List,i+1);
100
101 ListTravel(List);
102 ListInsert(List,23);
//注意插入的元素类型需要是LIST类型,因为当前的LIST是int类型,所以插入一个数字23
103 ListDelete(List,10); //删除元素的类型和插入的一样,不多说了
104 ListTravel(List);
105 ListDelete(List,5);
106 ListTravel(List);
107 ListDelete(List,1);
108 ListTravel(List);
109
110
111 return 0;
112 }

各位看官,关于单链表的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

13

一起talk C栗子吧(第十三回:C语言实例--单链表二)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是链表以及单链表顺序储存方式的例子,这一回咱们继续说单链表的例子,不 过这一回咱们说的是:单链表链式存储。

看官们单链表的链式存储,咱们在上一回已经说过,这里就不再多说了。这一回主要举例子,通过例子来 说明什么是单链表的链式存储。

通过对比单链表的顺序储存和链式存储,可以看出来。顺序存储链表的优点:遍历链表方便,查找也方便。 其缺点:删除,插入元素比较繁琐。链式存储链表的优点:插入,删除元素比较方便,遍历和查找比较繁 琐。总体来说链式存储的链表在实际开发中使用较多,因为它比较灵活,而且链表的大小可以依据需要动 态地调整,空间利用率高。

看官们,详细的代码如下,请大家参考。关于代码有以下几点需要大家注意:

  • 1.在代码中创建链表时,使用头结点,这样方便链表操作。详细的原因,可以看代码中的注释。
  • 2.代码中有debgu语句,在代码中如果定义DEBUG宏后,可以打印一些debug语句,这样可以快速的查找 问题的原因。如果不需要debug可以不定义这个宏,默认情况下也没有定义该宏。
  • 3.代码中使用了二级指针,使用的时候特别小心。

1 /* **************************
2 * Head file of List
3 * *************************/
4 #ifndef LIST_H
5 #define LIST_H
6
7 #include<stdio.h>
8 #include<stdlib.h>
9
10 //#define DEBUG 0
11 #ifdef DEBUG
12 int size = 0;
13 #endif
14
15 #define SUCCESS 0
16 #define FAILE 1
17
18 typedef int ListElmt; //把int当作List类型,实际中可以使用其它的类型或者自己定义一个List类型,不过不能是使用struct复合类型
19 typedef struct _ListNode //List node 类型
20 {
21 ListElmt data;
22 struct _ListNode *next;
23 }ListNode;
24
25 //typedef struct _ListNode ListNode;
26 typedef struct _ListNode *List; //定义链表的类型为ListNode类型的指针
27
28 //声明函数原型,这里有插入,删除,查找链表元素的函数,以及遍历链表的函数
29 int ListCreate(List *list,int len);
30 int ListDestroy(List *list);
31 int ListInsert(List *list,ListNode *node);
32 int ListDelete(List *list,ListElmt data);
33 int ListTravel(List list);
34 int ListFindElement(List list,ListElmt data);
35
36 #endif /*LIST_H*/

1 /* **************************
2 * Soure file of List
3 * *************************/
4
5 #include"Ex011_List.h"
6
7 //实现List的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8
9 //创建List Node,创建一个长度为len的链表,其中有一个链表头,链表中结点个数为len
10 int ListCreate(List *list,int len)
11 {
12 ListNode *l = NULL;
13 ListNode *p = NULL;
14
15 l = (ListNode*)malloc(sizeof(ListNode)); //先创建头结点
16
17 if(NULL == l) //分配成功后才能对它进行操作
18 return FAILE;
19
20 *list = l; //创建头结点,并且初始化
21 l->data = 0;
22 l->next = NULL;
23 #ifdef DEBUG
24 size += 1;
25 #endif
26
27 while(len-- > 0 )
28 {
29 p = (ListNode*)malloc(sizeof(ListNode)); //新创建结点
30
31 if(NULL != p)
32 {
33 l->next = p;
34 l = p;
35 l->data = 0; //结点中的元素初始化为0,这里的data是Int类型
36 l->next = NULL;
37 }
38 #ifdef DEBUG
39 size += 1;
40 #endif
41 }
42
43 return SUCCESS;
44 }
45
46 //删除List,从链表头开始删除,每次删除一个结点,直到所有结点都删除为止,此时为空链表,只剩下头结点
47 int ListDestroy(List *list)
48 {
49 ListNode *l = NULL;
50 ListNode *p = NULL;
51
52 if(NULL == *list) //空链表时不进行删除操作
53 {
54 printf("the list is empty \n");
55 return FAILE;
56 }
57
58 l = (*list)->next;
59 free(*list); //释放头结点
60 *list = NULL;
61
62 #ifdef DEBUG
63 size -= 1;
64 printf(" a delete a node in the list \n");
65 #endif
66 while(l != NULL) //从链表头结点的下一个结点开始,一个结点接着一个结点地删除
67 {
68 p = l->next;
69 free(l);
70 l = p;
71 #ifdef DEBUG
72 size -= 1;
73 printf("delete a node in the list \n");
74 #endif
75 }
76
77 return SUCCESS;
78 }
79
80 //向链表中插入结点,插入时从链表尾部插入,每次插入一个结点.
81 int ListInsert(List *list,ListNode *node)
82 {
83 ListNode *l = NULL;
84
85 if(NULL == *list)
86 {
87 printf("this is a empty list, can't be insered \n");
88 return FAILE;
89 }
90
91 l = (*list)->next;
92 // while(l != NULL) //遍历链表到表尾
93 // l = l->next;
94
95 // l = node; //在表尾插入结点
96 // l->next = NULL;
97
98 (*list)->next = node; //在表头,也就是头结点后面插入结点,省去遍历链表的时间,这是有头结点的好处
99 node->next = l;
100
101 #ifdef DEBUG
102 size += 1;
103 #endif
104 return SUCCESS;
105 }
106
107 //删除链表中包含data的结点
108 int ListDelete(List *list,ListElmt data)
109 {
110 int flag = 0;
111 int result = FAILE;
112 ListNode *current = NULL;
113 ListNode *next = NULL;
114
115 if(NULL == *list) //空链表没有结点,不能删除结点
116 {
117 printf("this is a empty list, can't be deleted \n");
118 return FAILE;
119 }
120
121 current = *list;
122 next = (*list)->next;
123
124 while(next != NULL) //依次遍历链表,查找被删除的元素,如果找到则删除结点,并且停止遍历链表
125 {
126 if(data == next->data)
127 {
128 current->next = next->next;
129 free(next);
130 next = NULL;
131 flag = 1;
132 #ifdef DEBUG
133 size -= 1;
134 #endif
135 break;
136 }
137 current = next;
138 next = next->next;
139 }
140
141 if( 1 == flag )
142 result = SUCCESS;
143 else
144 result = FAILE;
145
146 return result;
147 }
148
149 //遍历链表,显示链表中的每个结点的data
150 int ListTravel(List list)
151 {
152 ListNode *l = NULL;
153
154 if(NULL == list) //空链表直接返回
155 {
156 printf("It is a empyt list \n");
157 return FAILE;
158 }
159
160 l = list->next;
161
162 while(NULL != l) //遍历链表,并且显示链表中的data
163 {
164 printf("%d \n",l->data);
165 l = l->next;
166 }
167
168 #ifdef DEBUG
169 printf("list size: %d \n",size);
170 #endif
171 return SUCCESS;
172 }
173
174 //查找链表中是否包含值为data的结点
175 int ListFindElement(List list,ListElmt data)
176 {
177 ListNode *l = NULL;
178 int result = FAILE;
179
180 if(NULL == list) //空链表直接返回
181 {
182 printf("It is a empyt list \n");
183 return FAILE;
184 }
185
186 l = list->next;
187 while(NULL != l) //依次遍历链表,查找值为data的结点
188 {
189 if(data == l->data) //找到后停止遍历链表,否则继续遍历链表
190 {
191 result = SUCCESS;
192 break;
193 }
194 else
195 l = l->next;
196 }
197
198 return result;
199 }
200
201 int main()
202 {
203 int result = FAILE;
204 int len = 3;
205 ListNode *node = NULL; //node必须是指针,而且要用malloc分配空间,因为要使free释放
206 List list = NULL; //创建一个指向链表的空指针
207
208 node = (ListNode *)malloc(sizeof(ListNode));
209 if(NULL != node)
210 {
211 node->data = 1;
212 node->next = NULL;
213 }
214
215 result = ListCreate(&list,len); //创建一个长度为Len的链表
216 if(result == SUCCESS)
217 ListTravel(list);
218
219 printf("Insert a node into list \n");
220 ListInsert(&list,node);
221 ListTravel(list);
222
223 result = ListFindElement(list,0);
224 if(result == SUCCESS )
225 printf("find it in the list \n");
226 else
227 printf("don't find it in the list \n");
228
229 printf("main delete a node in list \n");
230 result = ListDelete(&list,1);
231 if(result == SUCCESS )
232 ListTravel(list);
233
234 ListDestroy(&list);
235
236 #ifdef DEBUG
237 printf("list size: %d \n",size);
238 #endif
239 ListTravel(list);
240 return result;
241 }

各位看官,关于单链表链式存储的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

14

一起talk C栗子吧(第十四回:C语言实例--循环链表)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是单链表链式存储的例子,这一回咱们说的例子是:循环链表。

看官们,循环链表也是链表的一种,只不过该链表的头部和尾部相连接,所以构成了一个循环链,因此叫 作循环链表。让我们一起对比一下单链接与循环链表的不同之处:单链表的尾结点哪里也没有指,因为它 的next指针值为空。循环链表的尾结点指向了它的头结点。

看官们,详细的代码放如下,大家可以参考。该例子的代码与上一回中例子中的代码类似,不同之处在于, 上一回的例子中判断链表结束时需要使用指针和NULL进行对比。这一回的例子中判断链表结束时需要使用 尾结点的指针和头结点的指针进行对比。如果这两个指针相同,那么就表示链表结束。

1 /* **************************
2 * Head file of CircleList
3 * *************************/
4 #ifndef CIRCLE_LIST_H
5 #define CIRCLE_LIST_H
6
7 #include<stdio.h>
8 #include<stdlib.h>
9
10 //#define DEBUG 0
11 #ifdef DEBUG
12 int size = 0;
13 #endif
14
15 #define SUCCESS 0
16 #define FAILE 1
17
18 typedef int ListElmt; //把int当作List类型,实际中可以使用其它的类型或者自己定义一个List类型,不过不能是使用struct复合类型
19 typedef struct _ListNode //List node 类型
20 {
21 ListElmt data;
22 struct _ListNode *next;
23 }ListNode;
24
25 //typedef struct _ListNode ListNode;
26 typedef struct _ListNode *List; //定义链表的类型为ListNode类型的指针
27
28 //声明函数原型,这里有插入,删除,查找链表元素的函数,以及遍历链表的函数
29 int ListCreate(List *list,int len);
30 int ListDestroy(List *list);
31 int ListInsert(List *list,ListNode *node);
32 int ListDelete(List *list,ListElmt data);
33 int ListTravel(List list);
34 int ListFindElement(List list,ListElmt data);
35
36 #endif /*CIRCLE_LIST_H*/

1 /* **************************
2 * Soure file of Cirecle List
3 * *************************/
4
5 #include"CircleList.h"
6
7 //实现List的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8
9 //创建List Node,创建一个长度为len的链表,其中有一个链表头,链表中结点个数为len
10 int ListCreate(List *list,int len)
11 {
12 ListNode *l = NULL;
13 ListNode *p = NULL;
14
15 l = (ListNode*)malloc(sizeof(ListNode)); //先创建头结点
16
17 if(NULL == l) //分配成功后才能对它进行操作
18 return FAILE;
19
20 *list = l; //创建头结点,并且初始化
21 l->data = 0;
22 l->next = l; //循环链表,首尾相连
23 #ifdef DEBUG
24 size += 1;
25 #endif
26
27 while(len-- > 0 )
28 {
29 p = (ListNode*)malloc(sizeof(ListNode)); //新创建结点
30
31 if(NULL != p)
32 {
33 p->next = l->next;
34 l->next = p;
35 l = p;
36 l->data = 0; //结点中的元素初始化为0,这里的data是Int类型
37 }
38 #ifdef DEBUG
39 size += 1;
40 #endif
41 }
42
43 return SUCCESS;
44 }
45
46 //删除List,从链表头开始删除,每次删除一个结点,直到所有结点都删除为止,此时为空链表,只剩下头结点
47 int ListDestroy(List *list)
48 {
49 ListNode *l = NULL;
50 ListNode *p = NULL;
51
52 if(NULL == *list) //空链表时不进行删除操作
53 {
54 printf("the list is empty \n");
55 return FAILE;
56 }
57
58 l = (*list)->next;
59 #ifdef DEBUG
60 size -= 1;
61 printf(" a delete a node in the list \n");
62 #endif
63 while(l != *list) //从链表头结点的下一个结点开始,一个结点接着一个结点地删除
64 {
65 p = l->next;
66 free(l);
67 l = p;
68 #ifdef DEBUG
69 size -= 1;
70 printf("delete a node in the list \n");
71 #endif
72 }
73 free(*list); //释放头结点
74 *list = NULL;
75
76 return SUCCESS;
77 }
78
79 //向链表中插入结点,插入时从链表尾部插入,每次插入一个结点.
80 int ListInsert(List *list,ListNode *node)
81 {
82 ListNode *l = NULL;
83
84 if(NULL == *list)
85 {
86 printf("this is a empty list, can't be insered \n");
87 return FAILE;
88 }
89
90 l = (*list)->next;
91 // while(l != *list) //遍历链表到表尾
92 // l = l->next;
93
94 // l = node; //在表尾插入结点
95 // l->next =*list;
96
97 (*list)->next = node; //在表头,也就是头结点后面插入结点,省去遍历链表的时间,这是有头结点的好处
98 node->next = l;
99
100 #ifdef DEBUG
101 size += 1;
102 #endif
103 return SUCCESS;
104 }
105
106 //删除链表中包含data的结点
107 int ListDelete(List *list,ListElmt data)
108 {
109 int flag = 0;
110 int result = FAILE;
111 ListNode *current = NULL;
112 ListNode *next = NULL;
113
114 if(NULL == *list) //空链表没有结点,不能删除结点
115 {
116 printf("this is a empty list, can't be deleted \n");
117 return FAILE;
118 }
119
120 current = *list;
121 next = (*list)->next;
122
123 while(next != current) //依次遍历链表,查找被删除的元素,如果找到则删除结点,并且停止遍历链表
124 {
125 if(data == next->data)
126 {
127 current->next = next->next;
128 free(next);
129 next = NULL;
130 flag = 1;
131 #ifdef DEBUG
132 size -= 1;
133 #endif
134 break;
135 }
136 current = next;
137 next = next->next;
138 }
139
140 if( 1 == flag )
141 result = SUCCESS;
142 else
143 result = FAILE;
144
145 return result;
146 }
147
148 //遍历链表,显示链表中的每个结点的data
149 int ListTravel(List list)
150 {
151 ListNode *l = NULL;
152
153 if(NULL == list) //空链表直接返回
154 {
155 printf("It is a empyt list \n");
156 return FAILE;
157 }
158
159 l = list->next;
160
161 while(list != l) //遍历链表,并且显示链表中的data
162 {
163 printf("%d \n",l->data);
164 l = l->next;
165 }
166
167 #ifdef DEBUG
168 printf("list size: %d \n",size);
169 #endif
170 return SUCCESS;
171 }
172
173 //查找链表中是否包含值为data的结点
174 int ListFindElement(List list,ListElmt data)
175 {
176 ListNode *l = NULL;
177 int result = FAILE;
178
179 if(NULL == list) //空链表直接返回
180 {
181 printf("It is a empyt list \n");
182 return FAILE;
183 }
184
185 l = list->next;
186 while(list != l) //依次遍历链表,查找值为data的结点
187 {
188 if(data == l->data) //找到后停止遍历链表,否则继续遍历链表
189 {
190 result = SUCCESS;
191 break;
192 }
193 else
194 l = l->next;
195 }
196
197 return result;
198 }
199
200 int main()
201 {
202 int result = FAILE;
203 int len = 3;
204 ListNode *node = NULL; //node必须是指针,而且要用malloc分配空间,因为要使free释放
205 List list = NULL; //创建一个指向链表的空指针
206
207 node = (ListNode *)malloc(sizeof(ListNode));
208 if(NULL != node)
209 {
210 node->data = 1;
211 node->next = NULL;
212 }
213
214 result = ListCreate(&list,len); //创建一个长度为Len的链表
215 if(result == SUCCESS)
216 ListTravel(list);
217
218 printf("Insert a node into list \n");
219 ListInsert(&list,node);
220 ListTravel(list);
221
222 result = ListFindElement(list,0);
223 if(result == SUCCESS )
224 printf("find it in the list \n");
225 else
226 printf("don't find it in the list \n");
227
228 printf("main delete a node in list \n");
229 result = ListDelete(&list,0);
230 if(result == SUCCESS )
231 ListTravel(list);
232
233 ListDestroy(&list);
234
235 #ifdef DEBUG
236 printf("list size: %d \n",size);
237 #endif
238 ListTravel(list);
239 return result;
240 }

各位看官,关于循环列表的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

15

一起talk C栗子吧(第十五回:C语言实例--双向链表)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是循环链表的例子,这一回咱们说的例子是:双向链表。

看官们,双向链表也是一种链表。我们在前面两回中说到的链表,都是沿着链表头部到链表尾部这样的方 向进行操作,而今天咱们要说的双向链表既可以沿着链表头部到链表尾部这样的方向进行操作,也可以沿 着链表尾部到链表头部这样的方向进行操作。这也是正是叫它双向链表的原因。

在例子中,查找和删除结点的函数中,可以使用沿着链表尾部向链表头部这样的方向进行查找或者删除, 当然了,也可以向单链表一样沿着链表头部到链表尾部这样的方向进行查找或者删除。不论沿着哪个方向 操作,只需要关注该方向的指针就可以。比如,沿着链表头部到链表尾部这样的方向进行相关的操作,只 需要关注结点中的next指针就行,pre指针可以忽略。但是删除操作需要注意,因为它会从链表中删除一 个符合要求的结点,删除的时候需要把该结点的pre和next指针都处理好,不然会破坏链表的完成性,在 删除操作后,如果再进行遍历操作,就会因为链表不完整,遍历不到链表中的所有结点,也就是形成了断 链,这是最严重的错误。我在代码中有中文注释。

看官们,详细的代码如下,大家可以参考:

1 /* **************************
2 * Head file of Double Linked List
3 * *************************/
4 #ifndef DOUBLE_LINKED_LIST_H
5 #define DOUBLE_LINKED_LIST_H
6
7 #include<stdio.h>
8 #include<stdlib.h>
9
10 //#define DEBUG 0
11 #ifdef DEBUG
12 int size = 0;
13 #endif
14
15 #define SUCCESS 0
16 #define FAILE 1
17
18 typedef int ListElmt; //把int当作List类型,实际中可以使用其它的类型或者自己定义一个List类型,不过不能是使用struct复合类型
19 typedef struct _ListNode //List node 类型
20 {
21 ListElmt data;
22 struct _ListNode *pre;
23 struct _ListNode *next;
24 }ListNode;
25
26 //typedef struct _ListNode ListNode;
27 typedef struct _ListNode *List; //定义链表的类型为ListNode类型的指针
28
29 //声明函数原型,这里有插入,删除,查找链表元素的函数,以及遍历链表的函数
30 int ListCreate(List *list,int len);
31 int ListDestroy(List *list);
32 int ListInsert(List *list,ListNode *node);
33 int ListDelete(List *list,ListElmt data);
34 int ListTravel(List list);
35 int ListFindElement(List list,ListElmt data);
36
37 #endif /*DOUBLE_LINKED_LIST_H*/

1 /* **************************
2 * Soure file of Double Linked List
3 * *************************/
4
5 #include"DoubleLinkedList.h"
6
7 //实现List的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8
9 //创建List Node,创建一个长度为len的链表,其中有一个链表头,链表中结点个数为len
10 int ListCreate(List *list,int len)
11 {
12 ListNode *l = NULL;
13 ListNode *p = NULL;
14
15 l = (ListNode*)malloc(sizeof(ListNode)); //先创建头结点
16
17 if(NULL == l) //分配成功后才能对它进行操作
18 return FAILE;
19
20 *list = l; //创建头结点,并且初始化
21 l->data = 0;
22 l->pre = NULL;
23 l->next = NULL;
24 #ifdef DEBUG
25 size += 1;
26 #endif
27
28 while(len-- > 0 )
29 {
30 p = (ListNode*)malloc(sizeof(ListNode)); //新创建结点
31
32 if(NULL != p)
33 {
34 l->next = p;
35 p->pre = l;
36 p->next = NULL;
37 l = p;
38 l->data = 0; //结点中的元素初始化为0,这里的data是Int类型
39 }
40 #ifdef DEBUG
41 size += 1;
42 #endif
43 }
44
45 return SUCCESS;
46 }
47
48 //删除List,从链表头开始删除,每次删除一个结点,直到所有结点都删除为止,此时为空链表,只剩下头结点
49 int ListDestroy(List *list)
50 {
51 ListNode *l = NULL;
52 ListNode *p = NULL;
53
54 if(NULL == *list) //空链表时不进行删除操作
55 {
56 printf("the list is empty \n");
57 return FAILE;
58 }
59
60 l = (*list)->next;
61 free(*list); //释放头结点
62 *list = NULL;
63
64 #ifdef DEBUG
65 size -= 1;
66 printf(" a delete a node in the list \n");
67 #endif
68 while(NULL != l) //从链表头结点的下一个结点开始,一个结点接着一个结点地删除
69 {
70 p = l->next; //detroy循环链表,沿着一个方向遍历就行,不需要考虑pre,但是delete链表时需要考虑,因为只是删除链表中的一个结点,不考虑会影响链表的完成性。
71 free(l);
72 l = p;
73 #ifdef DEBUG
74 size -= 1;
75 printf("delete a node in the list \n");
76 #endif
77 }
78 return SUCCESS;
79 }
80
81 //向链表中插入结点,插入时从链表尾部插入,每次插入一个结点.
82 int ListInsert(List *list,ListNode *node)
83 {
84 ListNode *l = NULL;
85
86 if(NULL == *list)
87 {
88 printf("this is a empty list, can't be insered \n");
89 return FAILE;
90 }
91
92 l = (*list)->next;
93 // while(l != *list) //遍历链表到表尾
94 // l = l->next;
95
96 // l = node; //在表尾插入结点
97 // l->next =*list;
98
99 (*list)->next = node; //在表头,也就是头结点后面插入结点,省去遍历链表的时间,这是有头结点的好处
100 node->pre = l->pre;
101 l->pre = node;
102 node->next = l;
103
104 #ifdef DEBUG
105 size += 1;
106 #endif
107 return SUCCESS;
108 }
109
110 //删除链表中包含data的结点
111 int ListDelete(List *list,ListElmt data)
112 {
113 int flag = 0;
114 int result = FAILE;
115 ListNode *current = NULL;
116 ListNode *next = NULL;
117
118 if(NULL == *list) //空链表没有结点,不能删除结点
119 {
120 printf("this is a empty list, can't be deleted \n");
121 return FAILE;
122 }
123
124 current = *list;
125 next = (*list)->next;
126
127 while(NULL != next) //依次遍历链表,查找被删除的元素,如果找到则删除结点,并且停止遍历链表
128 {
129 if(data == next->data)
130 {
131 current->next = next->next;
132 (next->next)->pre = next->pre;
133 free(next);
134 next = NULL;
135 flag = 1;
136 #ifdef DEBUG
137 size -= 1;
138 #endif
139 break;
140 }
141 current = next; //这里只沿一个方向进行遍历就可以
142 next = next->next;
143 }
144
145 if( 1 == flag )
146 result = SUCCESS;
147 else
148 result = FAILE;
149
150 return result;
151 }
152
153 //遍历链表,显示链表中的每个结点的data
154 int ListTravel(List list)
155 {
156 ListNode *l = NULL;
157
158 if(NULL == list) //空链表直接返回
159 {
160 printf("It is a empyt list \n");
161 return FAILE;
162 }
163
164 l = list->next;
165
166 while(l != NULL) //遍历链表,并且显示链表中的data
167 {
168 printf("%d \n",l->data);
169 l = l->next;
170 }
171
172 #ifdef DEBUG
173 printf("list size: %d \n",size);
174 #endif
175 return SUCCESS;
176 }
177
178 //查找链表中是否包含值为data的结点
179 int ListFindElement(List list,ListElmt data)
180 {
181 ListNode *l = NULL;
182 int result = FAILE;
183
184 if(NULL == list) //空链表直接返回
185 {
186 printf("It is a empyt list \n");
187 return FAILE;
188 }
189
190 l = list->next;
191 while( NULL != l) //依次遍历链表,查找值为data的结点
192 {
193 if(data == l->data) //找到后停止遍历链表,否则继续遍历链表
194 {
195 result = SUCCESS;
196 break;
197 }
198 else
199 l = l->next;
200 }
201
202 return result;
203 }
204
205 int main()
206 {
207 int result = FAILE;
208 int len = 3;
209 ListNode *node = NULL; //node必须是指针,而且要用malloc分配空间,因为要使free释放
210 List list = NULL; //创建一个指向链表的空指针
211
212 node = (ListNode *)malloc(sizeof(ListNode));
213 if(NULL != node)
214 {
215 node->data = 1;
216 node->next = NULL;
217 node->pre = NULL;
218 }
219
220 result = ListCreate(&list,len); //创建一个长度为Len的链表
221 if(result == SUCCESS)
222 ListTravel(list);
223
224 printf("Insert a node into list \n");
225 ListInsert(&list,node);
226 ListTravel(list);
227
228 result = ListFindElement(list,0);
229 if(result == SUCCESS )
230 printf("find it in the list \n");
231 else
232 printf("don't find it in the list \n");
233
234 printf("main delete a node in list \n");
235 result = ListDelete(&list,0);
236 if(result == SUCCESS )
237 ListTravel(list);
238
239 ListDestroy(&list);
240
241 #ifdef DEBUG
242 printf("list size: %d \n",size);
243 #endif
244 ListTravel(list);
245 return result;
246 }

各位看官,关于双向链表的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

16

一起talk C栗子吧(第十六回:C语言实例--栈一)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是双向链表的例子,这一回咱们说的例子是:栈。

什么是栈?我们听过龙门客栈,你这个是哪家客栈?我还没有说,台下已经有客官在问了。看官们,栈是 类似我们在前面几回中说过的链表,它也是用来存放数据的一种抽象的数据结构。因为比较抽象,咱们还 是举个现实生活中的例子来说明吧。我们出去旅游时通常拿一个行李箱存放自己的物品,比如衣服,鞋子 电脑,相机等。出发前,我们会把这些东西依次放到行李箱中,首先会把不容易压坏的物品放到箱底,比 如衣服。然后把容易压坏的物品放到上面,比如电脑和相机。当我们到达目的地时,会取出行李箱中的物 品。首先拿出放在箱子上面的电脑和相机,最后拿出放在箱子底部的衣服。大家看看,拿出物品的顺序和 存放物品的顺序正好相反。最后放进去的电脑和相机等易压碎的物品最先拿出来,最先放进去的衣服等不 易压碎的物品最后拿出来。这个行李箱就好比一个存放数据的栈,箱子里面的物品好比数据,从箱子里拿 物品好比操作数据,拿物品要先拿最后存放的物品,操作数据也要先操作最后放到栈中的数据。就是说最 先存放到栈中的数据最后被拿出。这便是栈的特点:先进后出。

看官们,和链表一样,栈也有两种实现方式:顺序存放和链式存放。我们会分别举例子说明。栈有两个基 本的操作:出栈和入栈。入栈就是把数据存放到栈中,出栈就是把数据从栈中拿出来。入栈和出栈这两个 操作要符合栈“先进后出”的特点。

看官们,详细的代码如下,大家可以参考。关于代码中有一些需要注意的地方和大家说一下:

  • 1.栈的顺序存储是通过一个全局数组实现的,栈的大小就也就是数组的长度,可以自己定义。
  • 2.入栈时要确认栈是否已经満了,不然会有溢出。我在代码中多放了一个空间可以避免溢出。
  • 3.出栈时要确认栈是否已经空了,不然会有溢出。我在代码中通过多放了一个变量size可以避免溢出。

1 /* **************************
2 * Head file of Stack
3 * *************************/
4 #ifndef STACK_H
5 #define STACK_H
6
7 #include<stdio.h>
8 #include<stdlib.h>
9
10 #define SUCCESS 0
11 #define FAILE 1
12
13 #define LEN 5 //栈的长度先定义为5,需要时可自行修改
14
15 typedef int StackElmt; //把int当作栈中元素的类型,实际中可以使用其它的类型或者自己定义一个List类型
16 typedef struct _Stack{
17 StackElmt *base;
18 StackElmt *top;
19 int size;
20 }Stack;
21
22 StackElmt STACK[LEN+1] = {0}; //顺序存储方式的栈,防止数组越界,最后一个位置不放元素
23
24 //声明函数原型,这里有入栈和出栈操的函数
25 int StackInit(Stack *s);
26 int StackPrint(Stack *s);
27 int StackPush(Stack *s, StackElmt e);
28 int StackPop(Stack *s, StackElmt *e);
29
30 #endif /*STACK_H*/

1 /* **************************
2 * Soure file of Stack
3 * *************************/
4
5 #include"Stack1.h"
6
7 //实现List的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8 //初始化中栈
9 int StackInit(Stack *s)
10 {
11 if(NULL == s)
12 return FAILE;
13
14 s->top = s->base = &STACK[0];
15 s->size = 0;
16
17 }
18 //输出栈中存放的元素
19 int StackPrint(Stack *s)
20 {
21 int index = 0;
22
23 if(NULL == s)
24 return FAILE;
25
26 if(s->size == 0)
27 {
28 printf("the Stack is empty,there is not any element \n");
29 return FAILE;
30 }
31
32 while(index < (s->size))
33 {
34 printf("%d ",*((s->base)+index) );
35 index++;
36 }
37
38 printf("\n ");
39
40 return SUCCESS;
41 }
42
43 //入栈函数,top指向栈顶,先把元素入栈,然后向栈顶移动一位
44 int StackPush(Stack *s, StackElmt e)
45 {
46 if(NULL == s)
47 return FAILE;
48
49 if(s->size >= LEN)
50 {
51 printf("the Stack is full \n");
52 return FAILE;
53 }
54
55 *(s->top) = e;
56 (s->top)++;
57 (s->size)++;
58
59 return SUCCESS;
60 }
61
62 //出栈函数,top先向栈底移到一位,然后移出当前它所指向的元素
63 int StackPop(Stack *s, StackElmt *e)
64 {
65 if(NULL == s)
66 return FAILE;
67
68 if(s->size == 0)
69 {
70 printf("the Stack is empty \n");
71 return FAILE;
72 }
73
74 (s->top)--;
75 *e = *(s->top);
76 (s->size)--;
77
78 return SUCCESS;
79 }
80
81
82 int main()
83 {
84 int i = 0;
85 StackElmt e = 0;
86 Stack stack ;
87
88 if( SUCCESS == StackInit(&stack) )
89 StackPrint(&stack);
90
91 StackPush(&stack,7);
92 StackPrint(&stack);
93
94 StackPop(&stack,&e);
95 printf("%d is poped \n",e);
96
97 while(i++ < LEN+5)
98 {
99 if( SUCCESS == StackPush(&stack,i) )
100 printf("%d is pushed \n",i);
101 }
102
103 while(i-- > 0)
104 {
105 if( SUCCESS == StackPop(&stack,&e) )
106 printf("%d is poped \n",e);
107 }
108
109 }

各位看官,关于栈的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

17

一起talk C栗子吧(第十七回:C语言实例--栈二)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是栈和特点和基本操作,最后通过顺序存储的方式实现了栈,这一回咱们继续 说栈,不过咱们这一回说的是栈的链式存储方式。

在代码中通过双向链表来实现栈的链式存储。入栈操作沿着表头到表尾的方向进行,出栈操作与其正好相 反(就把它当作双向链表的一个使用实例吧)。栈的结点可以看作是链表中的结点,对栈的操作,可以看 作是在链表中进行插入或者删除结点操作。只不过插入或者删除时要遵循栈“先进后出"的特点。栈的类型 中增加了一个size成员,可以通过它方便地得出栈的长度。与栈的顺序存储方式相比,多了一个销毁栈的 功能。因为栈中的空间都是动态分配得来的,每次入栈操作都会分配一块内存空间,与其相反,每次出栈 操作都会把内存空间释放掉。但是在实际程序中入栈和出栈并不是成对出现的,也就是说,如果使用完栈 后,没有通过出栈操作来释放动态空间,那么就会造成内存泄漏。所以我增加了销毁栈的功能,以方便在 程序的最后检查栈中动态分配来的空间是否被释放。

栈的链式存储与栈的顺序存储相比,最大的优点就是不需要事先知道栈的长度,只要内存空间足够大就能 存放足够多的元素到栈中。不过,它也有缺点,那就是入栈和出栈操作要复杂,而且效率低。总之,在实 际的程序中如果事先知道栈的长度,可以使用栈的顺序存储,如果与事先不知道栈的长度,那么可以使用 栈的链式存储,这样比较灵活一些。

看官们,详细的代码如下,大家可以参考:

1 /* **************************
2 * Head file of Stack
3 * *************************/
4 #ifndef STACK_H
5 #define STACK_H
6
7 #include<stdio.h>
8 #include<stdlib.h>
9
10 #define SUCCESS 0
11 #define FAILE 1
12
13 typedef struct _StackElmt
14 {
15 int data;
16 struct _StackElmt *pre;
17 struct _StackElmt *next;
18 }StackElmt; //把int当作栈中元素的类型,实际中可以使用其它的类型或者自己定义一个类型
19
20 typedef struct _Stack{
21 StackElmt *base; //栈底指针
22 StackElmt *top; //栈顶指针,它指向的区域存放StackElmt类型的值
23 int size; //方便统计栈的长度
24 }Stack;
25
26 //声明函数原型,这里有入栈和出栈操的函数
27 int StackInit(Stack *s);
28 int StackPrint(Stack *s);
29 int StackPush(Stack *s, int e);
30 int StackPop(Stack *s, int *e);
31 int StackDestroy(Stack *s);
32
33 #endif /*STACK_H*/

1 /* **************************
2 * Soure file of Stack
3 * *************************/
4
5 #include"Ex015_Stack2.h"
6
7 //实现List的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8 //
9 //初始化中栈
10 int StackInit(Stack *s)
11 {
12 if(NULL == s)
13 return FAILE;
14
15 s->top = s->base = NULL;
16 s->size = 0;
17
18 return SUCCESS;
19 }
20
21 //输出栈中存放的元素
22 int StackPrint(Stack *s)
23 {
24 int index = 0;
25 StackElmt *t = NULL;
26
27 if(NULL == s)
28 return FAILE;
29
30 if(s->size == 0)
31 {
32 printf("the Stack is empty,there is not any element \n");
33 return FAILE;
34 }
35
36 t = s->base;
37 while(NULL != t)
38 {
39 printf("%d ",t->data);
40 t = t->next;
41 }
42
43 printf("\n ");
44
45 return SUCCESS;
46 }
47
48 //入栈函数,top指向栈顶,每次push操作都会分配一个空间,top永远指向该空间
49 int StackPush(Stack *s, int e)
50 {
51 StackElmt *node = NULL;
52
53 if(NULL == s)
54 return FAILE;
55
56 node = (StackElmt *)malloc( sizeof(StackElmt) );
57
58 if(NULL != node)
59 {
60 if(NULL == s->base)
61 {
62 s->top = s->base = node;
63 node->pre = NULL;
64 }
65 else
66 {
67 (s->top)->next = node;
68 node->pre = s->top;
69 s->top = node; //相当于顺序存储中的top++
70 }
71
72 node->data = e;
73 node->next = NULL;
74 (s->size)++;
75
76 return SUCCESS;
77 }
78 else
79 return FAILE;
80 }
81
82 //出栈函数,先把top指向的元素出栈,然后释放top指向的空间
83 int StackPop(Stack *s, int *e)
84 {
85 StackElmt *t = NULL;
86
87 if(NULL == s)
88 return FAILE;
89
90 if(s->size == 0)
91 {
92 printf("the Stack is empty \n");
93 return FAILE;
94 }
95
96 *e = (s->top)->data ;
97 t = (s->top)->pre;
98 free(s->top);
99 s->top = t; //相当于top--
100
101 if(s->size == 1) //最后一个元素出栈时,base和top都为NULL
102 s->base = s->top;
103
104 (s->size)--;
105
106 return SUCCESS;
107 }
108
109 //栈销毁函数,因为有动态分配的空间,如果不执行出栈操作,要把栈destroy
110 int StackDestroy(Stack *s)
111 {
112 int t = 0;
113 int result = 0;
114
115 if(NULL == s)
116 return FAILE;
117
118 while(NULL != (s->base) )
119 result = StackPop(s,&t);
120
121 return result;
122 }
123
124 int main()
125 {
126 int i = 0;
127 int e = 0;
128 Stack stack ;
129
130 if( SUCCESS == StackInit(&stack) )
131 StackPrint(&stack);
132
133 StackPush(&stack,7);
134 StackPrint(&stack);
135
136 StackPop(&stack,&e);
137 printf("%d is poped \n",e);
138
139 while(i++ < 5)
140 {
141 if( SUCCESS == StackPush(&stack,i) )
142 printf("%d is pushed \n",i);
143 else
144 printf("push failed \n");
145 }
146
147 while(i-- > 0)
148 {
149 if( SUCCESS == StackPop(&stack,&e) )
150 printf("%d is poped \n",e);
151 else
152 printf("pop failed \n");
153 }
154
155 if( SUCCESS == StackDestroy)
156 printf("Stack destroy successfully \n");
157 else
158 printf("Stack need not to destroy \n");
159
160 }

各位看官,关于栈的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

18

一起talk C栗子吧(第十八回:C语言实例--输出十六进制)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提,言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是栈的例子,这一回咱们说的例子是:输出十六进制。

看官们,我想熟悉C语言的朋友们,对于输出十六进制的内容,肯定都会使用printf函数进行格式化输出。不过,有时候想输出十六进制时就会有点“不识庐山真面目,只缘身在此山中”的感觉。我在前面的例子中 有一个关于进制转换的例子。当时输出十六进制时使用分别判断10到15,然后依据判断结果输出A到F。现在回头看这个例子,就是刚才说的“不识庐山真面目,只缘身在此山中”。为此,我专门把进制转换例子中的 代码进行了修改。使用printf函数中的%X输出十六进制的内容。看官们,详细的代码如下,大家可以参考:

1 /* **************************
2 * For Hex output
3 * *************************/
4 #include<stdio.h>
5
6 /*convert function
7 *Parameter a is used for saving converting result
8 *Parameter iVal is a value ,which will be converted.
9 *Parameter base is a base value ,
10 */
11
12 #define SUCCESS 0
13 #define FALSE 1
14 #define BIT 32
15
16 int convert(int *a,int iVal,int base)
17 {
18 int index = 0;
19 int res = 0;
20
21
22 if(NULL == a)// check the pointer
23 {
24 printf("null pointer \n");
25 return FALSE;
26 }
27
28 if( 0 == base) //check the base, 0 can't be used for division
29 {
30 printf("bad value of base \n");
31 return FALSE;
32 }
33
34 res = iVal;
35 //the main algorithm
36 do
37 {
38 *(a+index) = res % base;
39 res /= base;
40 ++index;
41 }while(res != 0);
42
43 return SUCCESS;
44 }
45
46 int showConvertResult(int *a)
47 {
48 int index = 0;
49
50 if(NULL == a)// check the pointer
51 {
52 printf("null pointer \n");
53 return FALSE;
54 }
55
56 for(index=BIT; index>0; --index)
57 {
58 if(index %4 == 0)
59 printf(" ");
60
61 switch( *(a+index-1) ) // input hex character
62 {
63 case 10:
64 case 11:
65 case 12:
66 case 13:
67 case 14:
68 case 15:
69 printf("%X",a[index-1]);
70 break;
71 default:
72 printf("%d",a[index-1]);
73 break;
74 }
75 }
76
77 printf("\n");
78
79 return SUCCESS;
80 }
81
82 int main()
83 {
84 int base = 0;
85 int iVal =0;
86 int result = 0;
87 int hex[BIT] = {0}; // the max bit is 32
88
89 printf("please input a number for conversion: \n");
90 if(0 == scanf("%d",&iVal))
91 {
92 printf("Input number is not right \n");
93 return FALSE;
94 }
95
96 printf("please select a char for conversion: \n");
97 printf(" \t ->Decimal conver to Binary:input 1 : \n");
98 printf(" \t ->Decimal conver to Octonary:input 2 : \n");
99 printf(" \t ->Decimal conver to Hex:input 3 : \n");
100
101 if(0 == scanf("%d",&base))
102 {
103 printf("Input number for selecting is not right \n");
104 return FALSE;
105 }
106
107 switch(base)
108 {
109 case 1:
110 result = convert(hex,iVal,2);
111 break;
112
113 case 2:
114 result = convert(hex,iVal,8);
115 break;
116
117 case 3:
118 result = convert(hex,iVal,16);
119 break;
120
121 default:
122 break;
123
124 }
125
126 if(result == FALSE)
127 return FALSE;
128 else
129 {
130 showConvertResult(hex);
131 return SUCCESS;
132 }
133 }

该例子的代码使用了前面进制转换的代码,只修改了其中输出十六进制的内容,因此该例子也可以看作是进制转换例子的改进版。只所以写该例子就是为了避免“不识庐山真面目,只缘身在此山中”这种感觉。

各位看官,关于输出十六进制的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

19

一起talk C栗子吧(第十九回:C语言实例--位操作)

各位看官们,大家好,上一回中咱们说的是输出十六进制的例子,这一回咱们说的例子是:位操作。闲话休提,言归正转。让我们一起talk C栗子吧!

看官们,位操作有五种:与、或、非、异或、移位。接下来咱们分别介绍这些操作。为了方便说明,我们先统一做一下说明,位操作的对象是比特位。假如有三个比特位:A、B和C,大家都知道比特位的值只有0 或者1两种,所以A、B和C的值是0或者1.我们把A和B当作位操作的对象,C当作A和B操作的结果。

  • 与操作:操作符为&。例子:C=A & B.只有A和B的值都为1时,C的值才为1.其它情况时,C的值为0。
  • 或操作:操作符为|。例子:C=A | B.只要A和B中有一个值为1时,C的值就为1.其它情况时,C的值为0。
  • 非操作:操作符为~。例子:C=~A.如果A的值为1时,C的值才为0.反之,C的值为1。
  • 异或操作:操作符为^。例子:C=A ^ B.只有A和B的值不相同时,C的值才为1.其它情况时,C的值为0。
  • 移位操作:分为右移位和左移位两种。操作符为>>和<<。向左移位的话,右边空缺出来的位会补为0.向右

移位时有两种不同情况:算术移位和逻辑移位。使用算术移位时左边空缺出来的位会除去最高位操持不变外,其它空缺位补为0.使用逻辑移位时,左边空缺出来的位被补为0.一般情况下,编译器都是使用算术移位, 其实对于无符号数来说,不论是算术移位还是逻辑移位,他们的操作结果都一样。对于有符号数来说,要不一样了,因为有符号的数的最高位是用来表示符号的,特别是有符号数中的负数,它们的最高位是1.因 此使用右移位操作时要注意一下移位对象。另外,左称位操作相当于乘以2,右移位操作相当于除以2.当然移动的位数不能超过变量拥有的最大的位数。因为移位操作的效率高,所以它可以取代乘除法。

看官们,我们说了这么多位操作,到底有什么用途?看官莫急,通过位操作,可以取出某个位串中的一部分位,也可以对位串的某些位置置0和1.常见的做法是,首先定义一个掩码,通过掩码来对原来的位串进行 操作,比如取出A中的4和5位的值,C=(A&00011000)>>3。

看官们,位操作中的与或操作容易与逻辑运算中的与或运算混淆。我在这里给大家作一下说明:从“外表”上来看,它们是不同的:与操作使用&而与运算使用&&。或操作使用|而与运算使用||,与或操作的运算符 和与或运算的操作符明显不一样。从“内心”上来看,它们也是不同的:与或操作是对变量存储单元中的位进行操作,操作的结果就是新的变量。与或运算是对变量或表达式的进行真假判断,它的结果要么是真,要 么是假。大家可以是“外表”和“内心”来区分与或操作和与或运算。

各位看官,关于位操作例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

20

一起talk C栗子吧(第二十回:C语言实例--括号匹配)

各位看官们,大家好,前几回中咱们说了堆栈的原理,并且举了实际的例子进行解说,这一回咱们说的例 子是:括号匹配。括号匹配使用了堆栈的原理,大家可以从例子看出来,所以我们把它们放在一起。闲话 休提,言归正转。让我们一起talk C栗子吧!

看官们,所谓的括号匹配,就是给了一连串括号,里面有各种类型的的括号,然后确定该串中的括号是否 是一一 匹配的。例如:({[]})这串括号中的括号就是匹配的。因为串中的括号都是成对出现。(({)这串括号就 不是匹配的,串中{没有与它配对的括号,而且与(匹配的括号数量也不正确。

在确认括号是否匹配的过程中,我们的思路是这样的:首先依次从串中读取括号,每次读取一个括号,如 果读取的括号是左括号,比如(,{,[,那么就让括号入栈,如果读取的是右括号,比如),},],那么就把栈顶的 括号取出来,和它匹配,如果匹配,就继续进行判断串中的下一个括号,如果不匹配,那么就说明该串中 的括号不匹配。

看官们,详细的代码如下,请大家参考:

1 /* **************************
2 * For ParenthesisMatching
3 * *************************/
4
5 #include<stdio.h>
6
7 #define SIZE 10
8
9 char array[SIZE]; //using the array for stack
10 typedef struct _Stack
11 {
12 char *top;
13 int size;
14 }Stack;
15
16 int push(Stack *s,char ch)
17 {
18 if(NULL == s)
19 return 0;
20
21 if(s->size < SIZE)
22 {
23 *(s->top) = ch;
24 s->top++;
25 s->size++;
26
27 return 1;
28 }
29 else
30 return 0;
31 }
32
33 int pop(Stack *s, char *ch)
34 {
35 if(NULL == s)
36 return 0;
37
38 if(s->size > 0)
39 {
40 s->top--;
41 s->size--;
42 *ch = *(s->top);
43
44 return 1;
45 }
46 else
47 return 0;
48 }
49
50 int main()
51 {
52 char parenthesis[SIZE]={'(','{','[',']','}',')','[','{','}',']'}; // parenthesis ,you can init it by your self
53 int i;
54 int result;
55 char ch;
56 Stack s ; // stack defination and init
57 s.top = &array[0];
58 s.size =0;
59
60 result =0;
61 for(i=0; i<SIZE; ++i)
62 {
63 ch = parenthesis[i];
64
65 switch(ch)
66 {
67 case '(':
68 case '{':
69 case '[':
70 if(!push(&s,ch) )
71 return 0;
72 break;
73 case ')':
74 if(!pop(&s,&ch))
75 return 0;
76
77 if( ch != '(')
78 {
79 result = 1;
80 }
81 break;
82 case '}':
83 if(!pop(&s,&ch))
84 return 0;
85
86 if( ch != '{')
87 {
88 result = 1;
89 }
90 break;
91 case ']':
92 if(!pop(&s,&ch))
93 return 0;
94
95 if( ch != '[')
96 {
97 result = 1;
98 }
99 break;
100 default:
101 break;
102 }
103
104 if(1 == result)
105 {
106 printf("Parenthesis is not matching \n");
107 break;
108 }
109 }
110
111 if(0 == result)
112 {
113 printf("Parenthesis is matching \n");
114 }
115
116 return 0;
117 }

各位看官,关于括号匹配的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

21

一起talk C栗子吧(第二十一回:C语言实例--表达式求值)

各位看官们,大家好,前几回中咱们说了堆栈的原理,并且举了实际的例子进行解说,这一回咱们说的例 子是:表达式求值。表达式求值和上一回中说的括号匹配一样,都使用了堆栈的原理,大家可以从例子中 看出来,所以我们把它们放在一起。闲话休提,言归正转。让我们一起talk C栗子吧!

看官们,我们在这里说的表达式为包含加,减,乘除的四则运算表达式。例如:1+23-4/5就是一个四则运 算表达式。这个表达式中,运算符在数字中间,所以我们叫它中缀表达式,这也是符合我们思维的一种表 现形式,不过,计算机就不理解中缀表达式了,因为它没有办法像我们一样先进行乘除运算,然后再进行 加减运算,所以我们需要把中缀表达式转换成计算机能理解的后缀表达式。“什么是后缀表达式”,这时候 台下有看官在提问了,看官莫急,所谓的后缀表达式就是运算符在数字后面。例如:" 1+23-6/3 "这个中缀 表达式可以为" 123*+63/- "这种后缀表达式.

表达式求值有两个大的步骤:

  • 1.中缀表达式转换为后缀表达式。
  • 2.对后缀表达式进行求值。

这两个大的步骤中还有一些小的步骤,接下来我们详细说说这些小步骤。在说之前,我首先说明一个概念: 优先级。优先级代表着先后顺序,举一个日常为生活中的例子:排队买东西的时候,排在队列前面的人, 比排在队列后面人具有优先买东西的权利,我们就可以说:排在队列前面的人买东西的优先级高。优先级 在表达式运算过程中体现为:乘法和除法的优先级比加法和减法的优先级高。也就是我们通常说的先乘除 后加减,这个内容我就不多说了,大家在小学数学中都学过。我们在表达式求值过程中把中缀表达式转换 为后缀表达式也与优先级有关,因为后缀表达式可以去掉运算符的优先级。没有优先级了,计算机就能理 解后缀表达式并对其进行相关的运算。

中缀表达式转换为后缀表达式的步骤如下:

  • 1.从头到尾依次遍历中缀表达式,每次从表达式中读取一个字符;
  • 2.判断步骤1中读取的字符,如果是数字则保存到数组a中,如果是+*等运算符,请看下一个步骤;
  • 3.对存放运算符的栈进行出栈操作,把步骤的2中的运算符和刚才出栈的运算符进行优先级比较;
  • 4.如果步骤2中的运算符优先级高,那么把参与比较的这两个运算符都入栈。否则看下一步;
  • 5.如果步骤2中的运算符优先级低,那么让栈中的运算符继续出栈,并且把出栈的运算符存放数组a中;
  • 6.重复步骤4和步骤5,直到出栈运算符的优先级比步骤2中运算符的优先级高为止;
  • 7.重复步骤1到步骤6.直到遍历完中缀表达式为止;
  • 8.判断栈中是否还有运算符,如果有的话,就把所有运算符出栈,并且把出栈的运算符存放数组a中。

对后缀表达式求值的步骤如下:

  • 1.从头到尾依次遍历后缀表达式,每次从表达式中读取一个字符;
  • 2.判断步骤1中读取的字符,如果是数字则入栈,如果是+*等运算符,请看下一个步骤;
  • 3.对存放数字的栈进行两次出栈操作,依据步骤2中运算符的类型,对出栈的两个数字进行运算;
  • 4.对步骤3中的运算结果进行入栈操作,这样可以把运算结果保存到存放数字的栈中;
  • 5.重复步骤1到步骤4.直到遍历完后缀表达式为止;
  • 6.栈中最后一个元素就是该表达式的运算结果。

看官们,详细的代码如下,请大家参考:

1 /* **************************
2 * Head file of Expression Evaluation
3 * *************************/
4 #ifndef EXPRESSION_EVALUATION_H
5 #define EXPRESSION_EVALUATION_H
6
7 #include<stdio.h>
8 #include<stdlib.h>
9
10 #define SUCCESS 0
11 #define FAILE 1
12
13 #define LEN 20 //栈的长度先定义为5,需要时可自行修改
14
15 typedef char StackElmt; //把char当作栈中元素的类型,实际中可以使用其它的类型或者自己定义一个元素类型
16 typedef struct _Stack{
17 StackElmt *base;
18 StackElmt *top;
19 int size;
20 }Stack;
21
22 StackElmt STACK[LEN+1] = {0}; //顺序存储方式的栈,防止数组越界,最后一个位置不放元素
23
24 //声明函数原型,这里有入栈和出栈操的函数
25 int StackInit(Stack *s);
26 int StackDestroy(Stack *s);
27 int StackPrint(Stack *s);
28 int StackPush(Stack *s, StackElmt e);
29 int StackPop(Stack *s, StackElmt *e);
30
31 #endif /* EXPRESSION_EVALUATION_H */

1 /* **************************
2 * Soure file of Expression Evaluation
3 * *************************/
4
5 #include"ExpressionEvaluation.h"
6
7 //实现栈相关的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8 //初始化中栈
9 int StackInit(Stack *s)
10 {
11 if(NULL == s)
12 return FAILE;
13
14 s->top = s->base = &STACK[0];
15 s->size = 0;
16
17 }
18 int StackDestroy(Stack *s)
19 {
20 int i =0;
21
22 if(NULL == s)
23 return FAILE;
24
25 while(i<LEN)
26 {
27 STACK[i] = 0;
28 i++;
29 }
30 s->top = s->base = NULL;
31 s->size = 0;
32 }
33 //输出栈中存放的元素
34 int StackPrint(Stack *s)
35 {
36 int index = 0;
37
38 if(NULL == s)
39 return FAILE;
40
41 if(s->size == 0)
42 {
43 printf("the Stack is empty,there is not any element \n");
44 return FAILE;
45 }
46
47 while(index < (s->size))
48 {
49 printf("%d ",*((s->base)+index) );
50 index++;
51 }
52
53 printf("\n ");
54
55 return SUCCESS;
56 }
57
58 //入栈函数,top指向栈顶,先把元素入栈,然后向栈顶移动一位
59 int StackPush(Stack *s, StackElmt e)
60 {
61 if(NULL == s)
62 return FAILE;
63
64 if(s->size >= LEN)
65 {
66 printf("the Stack is full \n");
67 return FAILE;
68 }
69
70 *(s->top) = e;
71 (s->top)++;
72 (s->size)++;
73
74 return SUCCESS;
75 }
76
77 //出栈函数,top先向栈底移到一位,然后移出当前它所指向的元素
78 int StackPop(Stack *s, StackElmt *e)
79 {
80 if(NULL == s)
81 return FAILE;
82
83 if(s->size == 0)
84 {
85 //printf("the Stack is empty \n");
86 return FAILE;
87 }
88
89 (s->top)--;
90 *e = *(s->top);
91 (s->size)--;
92
93 return SUCCESS;
94 }
95
96 int main()
97 {
98 char ch = '\0';
99 char str[2];
100 char *a1= "1+2*3-6/3"; // 存放中缀表达式
101 //char *a1="1+2+3*4";
102 char a2[LEN]={'\0'}; // 存放后缀表达式
103 Stack s;
104 int i,j;
105 int a,b;
106 int res = 0;
107 int stack[LEN] ={0};
108
109 i = j = a = b = 0;
110 StackInit(&s);
111
112 while(*(a1+i) != '\0') //遍历中缀表达式
113 {
114 printf("%c",*(a1+i));
115
116 if(*(a1+i) == '+' || *(a1+i) == '-')
117 {
118 if(s.size != 0)
119 {
120 while( s.size >= 0 && !StackPop(&s,&ch))
121 {
122 *(a2+j) = ch;
123 ch = '\0';
124 j++;
125 }
126 StackPush( &s,*(a1+i) );
127 }
128 else
129 StackPush(&s,*(a1+i));
130 }
131 else if( *(a1+i) == '*' || *(a1+i) == '/')
132 {
133 if(s.size != 0)
134 {
135 if(!StackPop(&s,&ch))
136 {
137 if(ch == '+' || ch == '-')
138 {
139 StackPush(&s,ch);
140 StackPush( &s,*(a1+i) );
141 }
142 else
143 {
144 StackPush(&s,ch);
145 while( !StackPop(&s,&ch) && (ch == '*' || ch == '/') )
146 {
147 *(a2+j) = ch;
148 ch = '\0';
149 j++;
150 }
151 StackPush( &s,*(a1+i) );
152 }
153 }
154 }
155 else
156 StackPush(&s,*(a1+i));
157 }
158 else //从中缀表达式中读取的字符是数字,保存到数组中
159 {
160 *(a2+j) = *(a1+i);
161 j++;
162 }
163
164 i++;
165 }
166
167 while( s.size >= 0 && !StackPop(&s,&ch)) //栈中还有运算符的话,需要全部取出,放到后缀表达式中
168 {
169 *(a2+j) = ch;
170 ch = '\0';
171 j++;
172 }
173 *(a2+j) = '\0';
174
175 i=j=0;
176 StackDestroy(&s);
177 StackInit(&s);
178
179 while(*(a2+i) != '\0') //遍历后缀表达式
180 {
181 if(*(a2+i) == '+')
182 {
183 j--;
184 a = stack[j];
185 j--;
186 b = stack[j];
187
188 stack[j]= a+b;
189 j++;
190 }
191 else if(*(a2+i) == '-')
192 {
193 j--;
194 a = stack[j];
195 j--;
196 b = stack[j];
197
198 stack[j]= b-a;
199 j++;
200 }
201 else if(*(a2+i) == '*')
202 {
203 j--;
204 a = stack[j];
205 j--;
206 b = stack[j];
207
208 stack[j]= a*b;
209 j++;
210 }
211 else if(*(a2+i) == '/')
212 {
213 j--;
214 a = stack[j];
215 j--;
216 b = stack[j];
217
218 stack[j]= b/a;
219 j++;
220 }
221 else
222 {
223 str[0] =*(a2+i);
224 str[1] ='\0';
225 stack[j]= atoi(str);
226 j++;
227 }
228
229 i++;
230 }
231 res =stack[0];
232
233 printf(" = %d ",res);
234 printf("\n");
235 return SUCCESS;
236 }

从代码中可以看到,我们用了两次栈,一次是在中缀表达式转换成后缀表达式的过程中,栈用来存放运算 符。另外一次是在后缀表达式求值的过程中,栈用来存放参与运算的数字。

各位看官,关于表达式求值的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

22

一起talk C栗子吧(第二十二回:C语言实例--队列一)

各位看官们,大家好,上一回中咱们说的是表达式求值的例子,该例子使用了栈,这一回咱们说的是栈的兄弟:队列。闲话休提,言归正转。让我们一起talk C栗子吧!

我们在这里说的队列是一种抽象的数据结构,大家不用想的太抽象了,哈哈,其实它和我们日常生活中所 见的队列一样。不管怎么样,我们还是举一个容易理解的例子:大家在假期出去旅游的时候,都有过排队 买门票的经历吧。游客们在售票点的窗口前排成了一长串队列,售票人员先把门票卖给排在队列前面的游 客,买到门票的游客拿着门票兴高采烈地离开了队列,刚来到售票点的游客排在队列尾部默默地等着购买 门票。在这个例子中,游客们为了购买门票在售票点旁边排成一条长队,这条长队可以看作是队列,队列 里的游客可以看作是队列中存放的元素。买到门票的游客离开队列,可以看作是从队列中删除元素,想要 购买门票的游客排到队列里,可以看作是向队列中插入元素。我这么,大家还觉得队列抽象吗?如果觉 得抽象的话,下次旅游购买门票时多留意一下就可以。

我们来说一下队列的特点:

  • 1.队列有头也有尾。比如刚才例子中,先购买到门票的游客可以看作是队列头部。刚刚排到队列里的游客可以看作是队列的尾部。
  • 2.从队列中删除元素只能在队列头部进行。比如刚才例子中购买到门票的游客离开队列,可以看作是从队列头部删除了一个元素。
  • 3.向队列中插入元素只能在队列尾部进行。比如刚才例子中想要购买门票的游客排到队列里,可以看作是向队列中插入一个元素。
  • 4.队列中的元素遵守”先进先出“的规则。比如刚才例子中先排队的游客可以先购买到门票。

看官们,详细的代码如下,大家请参考。这个队列是通过顺序存储的方式实现的,具体到代码中是使用了一个数组来从充当队列。

1 /* **************************
2 * Head file of Queue
3 * *************************/
4 #ifndef QUEUE_H
5 #define QUEUE_H
6
7 #include<stdio.h>
8
9 #define SUCCESS 0
10 #define FAILE 1
11
12 #define LEN 5 //队列的长度先定义为5,需要时可自行修改
13
14 typedef int QueueElmt; //把int当作队列中元素的类型,实际中可以使用其它的类型或者自己定义一个元素类型
15 typedef struct _Queue{
16 QueueElmt *front;
17 QueueElmt *rear;
18 }Queue;
19
20 QueueElmt QUEUE[LEN] = {0}; //顺序存储方式的队列
21
22 //声明函数原型
23 int QueueInit(Queue *q);
24 int QueuePrint(Queue *q);
25 int EnQueue(Queue *q,QueueElmt e);
26 int DeQueue(Queue *q,QueueElmt *e);
27
28 #endif /*QUEUE_H*/

1 /* **************************
2 * Soure file of Queue
3 * *************************/
4
5 #include"Queue1.h"
6
7 //实现Queue的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
8 int QueueInit(Queue *q)
9 {
10 if(NULL == q)
11 return FAILE;
12
13 q->front = q->rear = &QUEUE[0];
14
15 return SUCCESS;
16 }
17
18 int QueuePrint(Queue *q)
19 {
20 QueueElmt *temp = NULL;
21
22 if(NULL == q)
23 return FAILE;
24
25 if(q->front == q->rear)
26 {
27 printf("Queue is empty \n");
28 return SUCCESS;
29 }
30
31 printf("Elmt of Queue:");
32 temp = q->front;
33 while(temp != q->rear)
34 printf("%d ",*temp++);
35 printf("\n");
36
37 return SUCCESS;
38 }
39
40 int EnQueue(Queue *q,QueueElmt e)
41 {
42 if(NULL == q)
43 return FAILE;
44
45 if(LEN > (q->rear - q->front))
46 {
47 *(q->rear) = e;
48 q->rear++;
49
50 return SUCCESS;
51 }
52 else
53 return FAILE;
54 }
55
56 int DeQueue(Queue *q,QueueElmt *e)
57 {
58 if(NULL == q)
59 return FAILE;
60
61 if(0 < (q->rear - q->front))
62 {
63 *e = *(q->front);
64 *(q->front) = 0;
65 q->front++;
66
67 return SUCCESS;
68 }
69 else
70 return FAILE;
71 }
72
73 int main()
74 {
75 int i = 0;
76 int result =0;
77 QueueElmt e;
78 Queue queue;
79
80 QueueInit(&queue);
81 QueuePrint(&queue);
82
83 while(i<LEN)
84 EnQueue(&queue,(++i));
85
86 result = EnQueue(&queue,9);
87 if(FAILE == result)
88 printf("EnQueue is failed \n");
89
90 QueuePrint(&queue);
91
92 DeQueue(&queue,&e);
93 printf("%d is deleted from Queue \n",e);
94 QueuePrint(&queue);
95
96 DeQueue(&queue,&e);
97 printf("%d is deleted from Queue \n",e);
98 QueuePrint(&queue);
99
100 DeQueue(&queue,&e);
101 printf("%d is deleted from Queue \n",e);
102 QueuePrint(&queue);
103
104 DeQueue(&queue,&e);
105 printf("%d is deleted from Queue \n",e);
106 QueuePrint(&queue);
107
108 DeQueue(&queue,&e);
109 printf("%d is deleted from Queue \n",e);
110 QueuePrint(&queue);
111
112 DeQueue(&queue,&e);
113 printf("%d is deleted from Queue \n",e);
114 QueuePrint(&queue);
115
116 result = DeQueue(&queue,&e);
117 if(FAILE == result)
118 printf("DeQueue is failed \n");
119 return result;
120 }

各位看官,关于队列的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。

jk_book.png

jk_weixin.png

更多信息请访问 book_view.png

http://wiki.jikexueyuan.com/project/c-example/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论