《C语言—从入门到项目实践》Issue分析及总结
在学习《C语言—从入门到项目实践》总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
《C语言—从入门到项目实践》(超值版)——聚慕课教育研发中心 编著
Issue分析及总结
第四章 数制与数据类型
问题描述:4.7.3中定义复杂的声明别名中(2)(3)不理解?
未解决!
第11章 指针——重点
注意事项:
1)刚定义的指针变量并未指向某个具体的位置(称为悬空指针)。使用悬空指针容易破坏系统,导致系统瘫痪。
2)指针变量只能存放指针(地址),不要将一个非零数(或任何其他非地址类型的数据)赋给一个指针变量。
备注:0除外,如int *p=0;——>表示指针指向空指针,C语言中用NULL表示空指针,表示没有指向任何对象。
3)引用一个数组元素有两种方法:下标法,即采用array[i]形式直接访问数组元素;指针法,即采用*(array+i)或*(pointer+i)形式间接访问数组元素。其中,array是数组名,pointer是指向数组的指针变量。
4)字符数组可以用数组名来一次性的输出它的全部元素(printf("%s",string);),其他类型的数组都不行(只能逐个元素输出)。
1.问题描述:指针的类型与指针所指向的类型的区别?
答:指针的类型是指针本身的类型,指针所指向的类型是:把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩余部分。如:int *ptr——>指针的类型是:int *;指针所指向的类型是int。
2.问题描述:数组指针和指针数组的区别?
答:如果指针p指向二维数组的某一行,则p+1就指向类该二维数组的下一行。这样的指针称为数组指针。如:int array[2][3]={1,2,3,4,5,6};int (*p) [3];——>表明指针p指向一个含有3个元素的一维整型数组,p的值就是该一维数组的首地址。
所以数组指针也称指向一维数组的指针,亦称行指针。
11-9.c
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 int main(void) 4 { 5 int array[2][3] = { 1,2,3,4,5,6 }; /*定义一个二维数组*/ 6 int i, j; 7 int(*p)[3]; /*定义一个数组指针*/ 8 p = array; /*p指向array下标为0那一行的首地址*/ 9 for (i = 0; i<2; i++) 10 { 11 for (j = 0; j<3; j++) 12 printf("array[%d][%d]=%d\n", i, j, p[i][j]); 13 } 14 return 0; 15 }
问题:p[i][j]输出是怎么回事???这是下标输出,还可以使用*(p[i]+j)或*(*(p+i)+j)或*(p+i)[j],即*(p+i)就等价于p[i]。*(p+i)是指针法,p[i]是下标法。
不能使用p[i]或*p[i]或*(p+i),因为这些都只能找到行,找不到列,所以当i等于0,(p[i]或*p[i]或*(p+i))都输出0,当i等于1,(p[i]或*p[i]或*(p+i))都输出1
一维数组指针
11-16.c
1 #include <stdio.h> 2 main() 3 { 4 int array[10], *pointer=array, i; 5 printf("Input 10 numbers: "); 6 for(i=0; i<10; i++) 7 scanf("%d", pointer+i); /*使用指针变量来输入数组元素的值*/ 8 printf("array[10]: "); 9 for(i=0; i<10; i++) 10 printf("%d ", *(pointer+i)); /*使用指向数组的指针变量输出数组*/ 11 printf("\n"); 12 }
int array[10], *pointer=array;——>pointer+i和array+i都是数组元素array[i]的地址,或者说它们都指向array数组的第i个元素。*(pointer+i)和*(array+i)就是pointer+i或array+i所指向的数组元素,即array[i]。
多维数组指针——以二维为例
11-17.c
1 #include <stdio.h> 2 int main(void) 3 { 4 int array[2][3]={1,2,3,4,5,6}; 5 int i,j,*p; 6 p=&array[0][0];//等价于p=array 7 printf("使用下标访问数组元素\n"); 8 for(i=0;i<2;i++) 9 { 10 for(j=0;j<3;j++) 11 printf("array[%d][%d]=%d\n",i,j,array[i][j]); 12 } 13 printf("使用数组名访问数组元素\n"); 14 for(i=0;i<2;i++) 15 { 16 for(j=0;j<3;j++) 17 printf("array[%d][%d]=%d\n",i,j,*(*(array+i)+j)); 18 } 19 printf("使用指针名访问数组元素\n"); 20 for(i=0;i<2;i++) 21 { 22 for(j=0;j<3;j++) 23 printf("array[%d][%d]=%d\n",i,j,*(p+3*i+j)); 24 } 25 return 0; 26 }
注意此处二维数组指针当采用指针名访问数组元素(*(p+3*i+j)))和之前的数组指针(*(*(p+i)+j))的不同,因为之前定义的差别!!!
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 main() 4 { 5 static int day_tab[2][13] = { 6 { 0,31,28,31,30,31,30,31,31,30,31,30,31 }, //没有闰年的月份天数 7 { 0,31,29,31,30,31,30,31,31,30,31,30,31 } }; //闰年的月份天数 8 int y, m, d; 9 scanf("%d%d%d", &y, &m, &d); 10 printf("%d\n", day_of_year(day_tab, y, m, d)); /*实参为二维数组名*/ 11 } 12 day_of_year(day_tab, year, month, day) 13 int *day_tab; /*形式参数为指针*/ 14 int year, month, day; 15 { 16 int i, j; 17 i = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; 18 for (j = 1; j<month; j++) /* day_tab+i*13+j:对二维数组中元素进行地址变换 */ 19 day += *(day_tab + i * 13 + j); 20 return(day); 21 }
说明:此代码会发出一个警告:c(10): warning C4013: “day_of_year”未定义;假设外部返回 int
还可参看:数组指针和指针数组的区别——https://www.cnblogs.com/mq0036/p/3382732.html
3.问题描述:*(p1-1)的值与变量b的值相同,是巧合吗?
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 int main(void) 4 { 5 int a = 1, b = 10; 6 int *p1, *p2; 7 p1 = &a; /*指针赋值*/ 8 p2 = &b; 9 printf("p1地址是%d,p1存储的值是%d\n", p1, *p1); /*输出*/ 10 printf("p2地址是%d,p2存储的值是%d\n", p2, *p2); /*输出*/ 11 printf("p1-1地址存储的值是%d\n", *(p1 - 1)); /*地址-1后存储的值*/ 12 printf("p1地址中的值-1后的值是%d\n", *p1 - 1); /*值-1后的值*/ 13 printf("*(p1-1)的值和*p1-1的值不同\n"); 14 return 0; 15 }
答:不是巧合。原因是a和b是局部变量,局部变量存储在栈中,而栈是向低地址扩展的存储空间(如果是堆就相反了),又因为int类型占用4个字节,所以a的地址比b的地址大4个字节,p1-1表示a的地址减少4个字节后的地址,也就是p2所指向的变量b,所以是10。
第17章 动态数据结构——重点
1.问题描述:17.2中的链表的建立
代码注释及说明:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include "stdio.h" 3 #include "malloc.h" 4 #define NULL 0 /*令NULL为0,用它表示空地址*/ 5 /*LEN代表struct stu结构体类型数据的长度*/ 6 #define LEN sizeof (struct stu) 7 struct stu 8 { 9 long int num; 10 float score; 11 struct stu *next; 12 }; 13 int n; 14 struct stu *creat() /*此函数带回一个指向链表头的指针*/ 15 { 16 struct stu *head, *p1, *p2; 17 n = 0; /*n为结点的个数*/ 18 p1 = p2 = (struct stu *)malloc(LEN); /*开辟一个新单元,p1指向p2,共同指向这个新单元*/ 19 scanf("%ld,%f", &p1->num, &p1->score);//如:输入:1,1.5——>p1指向该节点,p2也指向该节点 20 head = NULL;//头指针为空 21 while (p1->num != 0) 22 { 23 n = n + 1;//链表节点个数的递增 24 if (n == 1)head = p1;//如果是第一个节点,令头指针head指向p1 25 else p2->next = p1;//如果不是第一个节点,令p2的next指针指向p1 26 p2 = p1;//p2指针向后移动,p2指向p1(刚输入的节点) 27 p1 = (struct stu *)malloc(LEN);//p1指向刚开辟的一个新单元 28 scanf("%ld,%f", &p1->num, &p1->score);//如:输入:1,1.5——>p1指向该节点 29 } 30 p2->next = NULL;//输入完毕,令p2的next域指向空(链表的结尾) 31 return(head); /*返回链表的头地址*/ 32 } 33 void main() 34 { 35 creat();//此处可以调用create函数创建的链表 36 }
思路:p1指向新插入的节点,p2的next域指向链表新插入的节点p1——>实现链接上节点p1,p2通过指向p1实现不断后移。
2.问题描述:17.10中的迷宫问题求解的思路,怎么找到出口,路过的下标为什么会少一个?
思路:1)通过探测一个位置的右,下,左,上的位置(标志位)是否为0,而判定下一步是否可以移动到这个点;2)对走过的点,将其标志位设置为0,并将此点入栈;3)如果此点四周都无法走通,出栈,判断刚出栈的点是否可以走通,依次下去;4)如果可以走到出口位置,表示存在这样的路径,如果走不到(即最后栈为空),表明不存在这样的路径。
因为涉及到对已经走过的点的出栈,所以(3行6列)出栈后后续路径可以走通了,输出了路径,最后不存在(3,6)
第18章 C语言经典排序法——重点
1.问题描述:此章的程序用(.c)后缀命名后运行总是报错,如不存在iostream.h等,struct SqList &L报错存在正文时不允许未命名的原型函数
说明:此章的代码不支持C,需要用(.cpp)命名。
2.问题描述:18-3.c中对数组进行快速排序,运行报错?
代码注释及说明:
1 #include <stdio.h> 2 int partions(int arr[],int low,int high)// 划分函数 3 { 4 int prvotkey= arr[low]; //提取出低区的关键字 5 arr[0]= arr[low]; 6 while (low<high) //对低区和高区的数组下标进行比较 7 { 8 while (low<high&& arr[high]>=prvotkey) 9 --high; //高区的关键字就向前移动 10 arr[low]= arr[high]; //高区的数组元素也向前移动 11 while (low<high&& arr[low]<=prvotkey) 12 ++low; //低区的关键字向后移动 13 arr[high]= arr[low]; //低区的数组元素向后移动 14 } 15 arr[low]= arr[0]; 16 return low; 17 } 18 void qsort(int arr[],int low,int high) 19 { 20 int prvotloc; //枢轴 21 if(low<high) 22 { 23 prvotloc=partions(arr,low,high); /*将第一次排序的结果作为枢轴*/ 24 qsort(arr,low,prvotloc-1); /*递归调用排序,由low 到prvotloc-1*/ 25 qsort(arr,prvotloc+1,high); /*递归调用排序,由 prvotloc+1到 high*/ 26 } 27 } 28 void quicksort(int arr[],int n) 29 { 30 qsort(arr,1,n); /*第一个作为枢轴 ,从第一个排到第n个*/ 31 } 32 void main() 33 { 34 int a[11]={0,2,32,43,23,45,36,57,14,27,39}; 35 int b,c; 36 for (b=1;b<11;b++) 37 printf("%3d",a[b]); 38 printf("\n"); 39 quicksort(a,11); 40 for (c=1;c<11;c++) 41 printf("%3d",a[c]); 42 printf("\n "); 43 }
原因:数组越界,代码未更改!
3.问题描述:18-8.c中对数组进行快速排序,运行报错?
代码注释及说明:
1 //#define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 typedef int InfoType; /* 定义其他数据项的类型*/ 4 #define MAXSIZE 20 /* 一个用做示例的小顺序表的最大长度*/ 5 typedef int KeyType; /* 定义关键字类型为整型*/ 6 struct RedType /* 记录类型*/ 7 { 8 KeyType key; /* 关键字项*/ 9 InfoType otherinfo; /* 其他数据项,具体类型在主程中定义*/ 10 }; 11 struct SqList /* 顺序表类型*/ 12 { 13 RedType r[MAXSIZE + 1]; /* r[0]闲置或用做哨兵单元*/ 14 int length; /* 顺序表长度*/ 15 }; 16 int SelectMinKey(SqList L, int i) 17 { /* 返回在L.r[i..L.length]中key最小的记录的序号*/ 18 KeyType min; 19 int j, k; 20 k = i; /* 设第i个为最小*/ 21 min = L.r[i].key; 22 for (j = i + 1; j <= L.length; j++) 23 if (L.r[j].key<min) /* 找到更小的*/ 24 { 25 k = j; 26 min = L.r[j].key; 27 } 28 return k; 29 } 30 void SelectSort(SqList &L) 31 { /* 对顺序表L作简单选择排序*/ 32 int i, j; 33 RedType t; 34 for (i = 1; i<L.length; ++i) 35 { /* 选择第i小的记录,并交换到位*/ 36 j = SelectMinKey(L, i); /* 在L.r[i..L.length]中选择key最小的记录*/ 37 if (i != j) 38 { /* 与第i个记录交换*/ 39 t = L.r[i]; 40 L.r[i] = L.r[j]; 41 L.r[j] = t; 42 } 43 } 44 } 45 void print(SqList L) 46 { 47 int i; 48 for (i = 1; i <= L.length; i++) 49 printf("(%d,%d)", L.r[i].key, L.r[i].otherinfo); 50 printf("\n"); 51 } 52 #define N 8 53 void main() 54 { 55 RedType d[N] = { { 49,1 },{ 38,2 },{ 65,3 },{ 97,4 },{ 76,5 },{ 13,6 },{ 27,7 },{ 49,8 } }; 56 SqList l; 57 int i; 58 for (i = 0; i<N; i++) 59 l.r[i + 1] = d[i]; 60 l.length = N; 61 printf("排序前:\n"); 62 print(l); 63 SelectSort(l); 64 printf("排序后:\n"); 65 print(l); 66 }
说明:L在经过一次排序后是 L {r=0x005bfa80 {{key=-858993460 otherinfo=-858993460 }, {key=13 otherinfo=6 }, {key=38 otherinfo=2 }, ...} ...} SqList &;因为存储时下标为0的节点没有存储内容,所以都是随机值。
4.问题描述:18-9.c中对数组进行树形选择排序,运行报错?
代码注释及说明:
1 #include<string.h> 2 #include<ctype.h> 3 #include<malloc.h> /*malloc()等*/ 4 #include<limits.h> /*INT_MAX等*/ 5 #include<stdio.h> /*EOF(=^Z或F6),NULL*/ 6 #include<stdlib.h> /*atoi()*/ 7 #include<io.h> /*eof()*/ 8 #include<math.h> /*floor(),ceil(),abs()*/ 9 #include<process.h> /*exit()*/ 10 //#include<iostream.h> /*cout,cin*/ 11 /* 函数结果状态代码*/ 12 #define TRUE 1 13 #define FALSE 0 14 #define OK 1 15 #define ERROR 0 16 #define INFEASIBLE -1 17 typedef int Status; /*Status是函数的类型,其值是函数结果状态代码,如OK*/ 18 typedef int Boolean; /*Boolean是布尔类型,其值是TRUE或FALSE*/ 19 typedef int InfoType; /*定义其他数据项的类型*/ 20 #define MAXSIZE 20 /*一个用做示例的小顺序表的最大长度*/ 21 typedef int KeyType; /*定义关键字类型为整型*/ 22 struct RedType /*记录类型*/ 23 { 24 KeyType key; /*关键字项*/ 25 InfoType otherinfo; /*其他数据项,具体类型在主程序中定义*/ 26 }; 27 28 struct SqList /*顺序表类型*/ 29 { 30 struct RedType r[MAXSIZE + 1]; /*r[0]闲置或用做哨兵单元*/ 31 int length; /*顺序表长度*/ 32 }; 33 34 void TreeSort(SqList &L) 35 { /*树形选择排序*/ 36 int i, j, j1, k, k1, l, n = L.length; 37 RedType *t; 38 l = (int)ceil(log(n) / log(2)) + 1; /*完全二叉树的层数*/ 39 k = (int)pow(2, l) - 1; /*l层完全二叉树的结点总数*/ 40 k1 = (int)pow(2, l - 1) - 1; /*l-1层完全二叉树的结点总数*/ 41 t = (RedType*)malloc(k*sizeof(RedType)); /*二叉树采用顺序存储结构*/ 42 for (i = 1; i <= n; i++) /*将L.r赋给叶子结点*/ 43 t[k1 + i - 1] = L.r[i]; 44 for (i = k1 + n; i<k; i++) /*给多余的叶子的关键字赋无穷大*/ 45 t[i].key = INT_MAX; 46 j1 = k1; 47 j = k; 48 while (j1) 49 { /*给非叶子结点赋值*/ 50 for (i = j1; i<j; i += 2) 51 t[i].key<t[i + 1].key ? (t[(i + 1) / 2 - 1] = t[i]) : (t[(i + 1) / 2 - 1] = t[i + 1]); 52 j = j1; 53 j1 = (j1 - 1) / 2; 54 } 55 for (i = 0; i<n; i++) 56 { 57 L.r[i + 1] = t[0]; /*将当前最小值赋给L.r[i]*/ 58 j1 = 0; 59 for (j = 1; j<l; j++) /*沿树根找结点t[0]在叶子中的序号j1*/ 60 t[2 * j1 + 1].key == t[j1].key ? (j1 = 2 * j1 + 1) : (j1 = 2 * j1 + 2); 61 t[j1].key = INT_MAX; 62 while (j1) 63 { 64 j1 = (j1 + 1) / 2 - 1; /*序号为j1的结点的双亲结点序号*/ 65 t[2 * j1 + 1].key <= t[2 * j1 + 2].key ? (t[j1] = t[2 * j1 + 1]) : (t[j1] = t[2 * j1 + 2]); 66 } 67 } 68 free(t); 69 } 70 71 void print(struct SqList L) 72 { 73 int i; 74 for (i = 1; i <= L.length; i++) 75 printf("(%d,%d)", L.r[i].key, L.r[i].otherinfo); 76 printf("\n"); 77 } 78 79 #define N 8 80 void main() 81 { 82 struct RedType d[N] = { { 49,1 },{ 38,2 },{ 65,3 },{ 97,4 },{ 76,5 },{ 13,6 },{ 27,7 },{ 49,8 } }; 83 struct SqList l; 84 int i; 85 for (i = 0; i<N; i++) 86 l.r[i + 1] = d[i]; 87 l.length = N; 88 printf("排序前:\n"); 89 print(l); 90 TreeSort(l); 91 printf("排序后:\n"); 92 print(l); 93 }
说明:需要将//#include<iostream.h> /*cout,cin*/注释掉,如果不注释,会报错:error C1083: 无法打开包括文件: “iostream.h”: No such file or directory
18-2.c也有这个问题,也需要注释掉。
4.问题描述:18-12.c中对链式进行基数排序,运行报错:error C4996: 'itoa': The POSIX name for this item is deprecated?
代码注释及说明:
1 #define _CRT_NONSTDC_NO_DEPRECATE 2 #define _CRT_SECURE_NO_WARNINGS 3 #include<string.h> 4 #include<ctype.h> 5 #include<malloc.h> //malloc()等 6 #include<limits.h> //INT_MAX等 7 #include<stdio.h> //EOF(=^Z或F6),NULL 8 #include<stdlib.h> //atoi() 9 #include<io.h> //eof() 10 #include<math.h> //floor(),ceil(),abs() 11 #include<process.h> //exit() 12 //#include<iostream.h> //cout,cin 13 /* 函数结果状态代码*/ 14 #define TRUE 1 15 #define FALSE 0 16 #define OK 1 17 #define ERROR 0 18 #define INFEASIBLE -1 19 typedef int Status; /*Status是函数的类型,其值是函数结果状态代码,如OK等*/ 20 typedef int Boolean; /*Boolean是布尔类型,其值是TRUE或FALSE*/ 21 #define MAX_NUM_OF_KEY 8 /*关键字项数的最大值*/ 22 #define RADIX 10 /*关键字基数,此时是十进制整数的基数*/ 23 #define MAX_SPACE 1000 24 25 typedef int InfoType; /*定义其他数据项的类型*/ 26 typedef int KeyType; /*定义RedType类型的关键字为整型*/ 27 struct RedType /*记录类型(同c10-1.h)*/ 28 { 29 KeyType key; /*关键字项*/ 30 InfoType otherinfo; /*其他数据项*/ 31 }; 32 typedef char KeysType; /*定义关键字类型为字符型*/ 33 34 struct SLCell /*静态链表的结点类型*/ 35 { 36 KeysType keys[MAX_NUM_OF_KEY]; /* 关键字*/ 37 InfoType otheritems; /*其他数据项*/ 38 int next; 39 }; 40 41 42 struct SLList /*静态链表类型*/ 43 { 44 SLCell r[MAX_SPACE]; /*静态链表的可利用空间,r[0]为头结点*/ 45 int keynum; /*记录的当前关键字个数*/ 46 int recnum; /*静态链表的当前长度*/ 47 }; 48 49 typedef int ArrType[RADIX]; 50 void InitList(SLList &L, RedType D[], int n) 51 { /*初始化静态链表L(把数组D中的数据存于L中)*/ 52 char c[MAX_NUM_OF_KEY], c1[MAX_NUM_OF_KEY]; 53 int i, j, max = D[0].key; /*max为关键字的最大值*/ 54 for (i = 1; i<n; i++) 55 if (max<D[i].key) 56 max = D[i].key; 57 L.keynum = int(ceil(log10(max))); 58 L.recnum = n; 59 for (i = 1; i <= n; i++) 60 { 61 L.r[i].otheritems = D[i - 1].otherinfo; 62 itoa(D[i - 1].key, c, 10); /* 将十进制整型转化为字符型,存入c*/ 63 for (j = strlen(c); j<L.keynum; j++) /*若c的长度小于max的位数,在c前补'0'*/ 64 { 65 strcpy(c1, "0"); 66 strcat(c1, c); 67 strcpy(c, c1); 68 } 69 for (j = 0; j<L.keynum; j++) 70 L.r[i].keys[j] = c[L.keynum - 1 - j]; 71 } 72 } 73 74 int ord(char c) 75 { /*返回k的映射(个位整数)*/ 76 return c - '0'; 77 } 78 79 void Distribute(SLCell r[], int i, ArrType f, ArrType e) 80 { /*静态键表L的r域中记录已按(keys[0],…,keys[i-1])有序。本算法按*/ 81 /*第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的keys[i]相同*/ 82 /*f[0..RADIX-1]和e[0..RADIX-1]分别指向各子表中第一个和最后一个记录*/ 83 int j, p; 84 for (j = 0; j<RADIX; ++j) 85 f[j] = 0; /*各子表初始化为空表*/ 86 for (p = r[0].next; p; p = r[p].next) 87 { 88 j = ord(r[p].keys[i]); /*ord将记录中第i个关键字映射到[0..RADIX-1]*/ 89 if (!f[j]) 90 f[j] = p; 91 else 92 r[e[j]].next = p; 93 e[j] = p; /*将p所指的结点插入第j个子表中*/ 94 } 95 } 96 97 int succ(int i) 98 { /* 求后继函数*/ 99 return ++i; 100 } 101 102 void Collect(SLCell r[], ArrType f, ArrType e) 103 { /*本算法按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成*/ 104 /*一个链表,e[0..RADIX-1]为各子表的尾指针*/ 105 int j, t; 106 for (j = 0; !f[j]; j = succ(j)); /*找第一个非空子表,succ为求后继函数*/ 107 r[0].next = f[j]; 108 t = e[j]; /*r[0].next指向第一个非空子表中第一个结点*/ 109 while (j<RADIX - 1) 110 { 111 for (j = succ(j); j<RADIX - 1 && !f[j]; j = succ(j)); /*找下一个非空子表*/ 112 if (f[j]) 113 { /*链接两个非空子表*/ 114 r[t].next = f[j]; 115 t = e[j]; 116 } 117 } 118 r[t].next = 0; /*t指向最后一个非空子表中的最后一个结点*/ 119 } 120 121 void printl(SLList L) 122 { /*按链表输出静态链表*/ 123 int i = L.r[0].next, j; 124 while (i) 125 { 126 for (j = L.keynum - 1; j >= 0; j--) 127 printf("%c", L.r[i].keys[j]); 128 printf(" "); 129 i = L.r[i].next; 130 } 131 } 132 133 void RadixSort(SLList &L) 134 { /*L是采用静态链表表示的顺序表。对L作基数排序,使得L成为按关键字*/ 135 /*自小到大的有序静态链表,L.r[0]为头结点*/ 136 int i; 137 ArrType f, e; 138 for (i = 0; i<L.recnum; ++i) 139 L.r[i].next = i + 1; 140 L.r[L.recnum].next = 0; /*将L改造为静态链表*/ 141 for (i = 0; i<L.keynum; ++i) 142 { /*按最低位优先依次对各关键字进行分配和收集*/ 143 Distribute(L.r, i, f, e); /*第i趟分配*/ 144 Collect(L.r, f, e); /*第i趟收集*/ 145 printf("第%d趟收集后:\n", i + 1); 146 printl(L); 147 printf("\n"); 148 } 149 } 150 151 void print(SLList L) 152 { /*按数组序号输出静态链表*/ 153 int i, j; 154 printf("keynum=%d recnum=%d\n", L.keynum, L.recnum); 155 for (i = 1; i <= L.recnum; i++) 156 { 157 printf("keys="); 158 for (j = L.keynum - 1; j >= 0; j--) 159 printf("%c", L.r[i].keys[j]); 160 printf(" otheritems=%d next=%d\n", L.r[i].otheritems, L.r[i].next); 161 } 162 } 163 164 void Sort(SLList L, int adr[]) /*改此句(类型)*/ 165 { /*求得adr[1..L.length],adr[i]为静态链表L的第i个最小记录的序号*/ 166 int i = 1, p = L.r[0].next; 167 while (p) 168 { 169 adr[i++] = p; 170 p = L.r[p].next; 171 } 172 } 173 174 void Rearrange(SLList &L, int adr[]) /*改此句(类型)*/ 175 { /*adr给出静态链表L的有序次序,即L.r[adr[i]]是第i小的记录*/ 176 /*本算法按adr重排L.r,使其有序(L的类型有变)*/ 177 int i, j, k; 178 for (i = 1; i<L.recnum; ++i) /*改此句(类型)*/ 179 if (adr[i] != i) 180 { 181 j = i; 182 L.r[0] = L.r[i]; /*暂存记录L.r[i]*/ 183 while (adr[j] != i) 184 { /*调整L.r[adr[j]]的记录到位直到adr[j]=i为止*/ 185 k = adr[j]; 186 L.r[j] = L.r[k]; 187 adr[j] = j; 188 j = k; /*记录按序到位*/ 189 } 190 L.r[j] = L.r[0]; 191 adr[j] = j; 192 } 193 } 194 195 #define N 10 196 void main() 197 { 198 RedType d[N] = { { 278,1 },{ 109,2 },{ 63,3 },{ 930,4 },{ 589,5 }, 199 { 184,6 },{ 505,7 },{ 269,8 },{ 8,9 },{ 83,10 } }; 200 SLList l; 201 int *adr; 202 InitList(l, d, N); 203 printf("排序前(next域还没赋值):\n"); 204 print(l); 205 RadixSort(l); 206 printf("排序后(静态链表):\n"); 207 print(l); 208 adr = (int*)malloc((l.recnum)*sizeof(int)); 209 Sort(l, adr); 210 Rearrange(l, adr); 211 printf("排序后(重排记录):\n"); 212 print(l); 213 }
原因:新版本的vs对旧有的函数itoa进行了安全检查,所以使用新版本的vs会提示错误,而旧版本的没问题。
解决办法:
1)使用新函数 _itoa
2)如果非要使用旧函数也是可以的,加上宏定义即可
#define _CRT_NONSTDC_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
在学习《C语言—从入门到项目实践》总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
posted on 2020-05-02 20:35 Alliswell_WP 阅读(503) 评论(0) 编辑 收藏 举报