1、指出程序中的错误,说明原因并修正
1.1
int *p,*q; p=malloc(sizeof(int)*20); q=malloc(sizeof(int)*10); … q=p; … free(p); free(q);
分析:
错误1,q原本储存一片int类型的内存区域的地址,在没有释放这片地址时就修改了q的内容,使这片区域无法收回,导致内存泄漏。
错误2,p与q指向同一片内存区域,在使用free(p)后该内存区域已经释放,不能再free一遍。改正:将free(q)放在q=p前面(改正有多种说法,这里选择其中一种)
1.2
//交换字符串 void swap(char *p, char *q) { char *temp; //p、q所指的值的交换 *temp=*p; *p=*q; *q=*temp; }
分析:该代码首先创建了形参p和q接受两个char类型的地址,在代码内部交换的这两个形参的内容,没有对外界产生任何影响。
该代码的修改如下:
void swap(char *p, char *q) { char temp[100]; strcpy(temp,p); //strcpy函数:复制字符串 strcpy(p,q); strcpy(q,temp); }
2、简答题
2.1 arr为整型数组,N为数组长度,enumb为整型变量,下列函数负责找出arr数组中等于enumb的元素所在位置。指出程序的三种异常,并说明原因。
for(i=N-1;arr[i]!=enumb;--i) printf(“%d”,i);
分析:
首先for循环后面应该有分号,否则每次循环都有输出。
其次如果arr数组中没有enumb,i就会变为负号,数组溢出。
最后,若i一直减小,i会减小直到溢出。
2.2 if(B) s1 else s2;是什么结构?使用显示结构语言该如何表示?并标出条件跳转和强制跳转
分析:条件分支结构
if(b) goto L1;//条件跳转 goto L2;//强制跳转 L1: s1 L2: s2
2.3 C语言中,常量存储在哪里?静态局部变量和静态全局变量存储在哪里?
分析:常量存储在常量区,静态局部变量和静态全局变量存储在全局数据区。
3填空题
3.1 下面程序是对链表进行选择排序,填上空缺的部分
list selectsort(list head){ list p = (struct node*)malloc(sizeof(node)); p->next = head; head = p;//新建一个头结点 p = head->next; list k = head, q = head; while (p->next) { q = p->next; k = q; //k记录最小值位置
//找到最小元素位置 while (q) { if (q->data < k->data) { k = q; } q = q->next; }
//交换元素位置 if (p->next != k) { int r = p->next->data; p->next->data = k->data; k->data = r; } p = p->next; //填空一 } p = head; head = head->next; //填空二 free(p); //释放头结点 return head; //填空三 }
3.2 快速排序法求某个数组前n个元素第k大的数
int find_k(int *a, int n,int k) { int i, j, t; int low = 0,high = n - 1; do { i = low; j = high; t = a[low]; do { while (a[j]>t) j--; while (a[i]<t) i++; if () swap(&a[j], &a[i]); else ; } while (i<j); if (i == k) return t; if (i>k) ; if (i<k) ; } while (low<high); ; }
分析:该题目使用快排划分的第一种写法,原理是利用每次快排划分之后总能确定一个元素的最终位置。该程序可能仍然存在问题,最大的数字是第0个。
int find_k(int *a, int n,int k) { //从大到小排序 int i, j, t; int low = 0,high = n - 1; do { i = low; j = high; t = a[low]; do { while (a[j]<t) j--; while (a[i]>t) i++; if (i<j) swap(&a[j], &a[i]); else break; //填空1 } while (i<j); if (i == k) return t; if (i>k) high = i - 1; //填空2 if (i<k) low = i + 1; //填空3 } while (low<high); return a[low]; //填空4 }
3.3约瑟夫环问题 【见2015年】
int a[N + 1]; int *p = a, i,j,k; for(i = 0; i<N + 1; i++) *(p+i) = i; ; ; for( i = 0; k != 1; p++) { if() p = a + 1; if() i++; if() { k--; i = 0; *p = 0; } } for(i = 0; i<N + 1; i++) { if() printf("%d ",a[i]); }
分析:与15年约瑟夫环区别
int a[N + 1]; int *p = a, i,j,k;
//赋值0~N for(i = 0; i<N + 1; i++) *(p+i) = i; p = a + 1; //填空1 k = N; //填空2 for( i = 0; k > 1; p++) //k为剩下的人数 { if(p>a + N) p = a + 1; if(*p != 0) //碰到元素为0说明已经杀死,不参与计数 i++; //i报数 if(i == 3) { k--; i = 0; *p = 0; } }
//打印输出 for(i = 0; i<N + 1; i++) { if(a[i] != 0) printf("%d ",a[i]); }
3.4 完美乘法,若a*b=c,且abc中0~9的数字各出现一次,填写程序空缺处。
int f[10],s[3]; int n=0; for (int a = 12; a<999; a++) { int t = 0; //清空数字计数 for (int x = 0; x<10; x++) f[x] = 0; for (int b = 345; b<9999; b++) { int c ; ; //填空一 s[0] = a; s[1] = b; s[2] = c; //计算abc中出现数字的次数 for (int x = 0; x < 3; x++) { int y = s[x]; while () { int t = y % 10; f[t]++; ; //填空二 } } //检查是否每个数都个出现一次 for (int x = 0; x<10; x++) { if () ; //填空三 } if () printf("%d*%d=%d ",a,b,c);
;//填空四 } }分析:
int f[10],s[3]; int n=0; for (int a = 12; a<999; a++) { int t = 0; //清空数字计数 for (int x = 0; x<10; x++) f[x] = 0; for (int b = 345; b<9999; b++) { int c = a*b; s[0] = a; s[1] = b; s[2] = c; //计算abc中出现数字的次数 for (int x = 0; x < 3; x++) { int y = s[x]; while (y > 0) { int t = y % 10; f[t]++; y = y / 10; } } //检查是否每个数都个出现一次 for (int x = 0; x<10; x++) { if (f[x] != 1) t++; } if (t == 0) printf("%d*%d=%d ",a,b,c); n++; //统计循环次数 } }
4编程题
4.1 将字符串逆转,函数原型void reverse(char *str);,要求空间复杂度为O(1)
#include <stdio.h> #include <stdlib.h> #include <string.h> void reverse(char *str) { int i = 0, len = strlen(str); for (; i < len / 2; i++) { char a = str[i]; str[i] = str[len - i - 1]; str[len - i - 1] = a; } } int main() { char ch[] = "helloworld"; reverse(ch); printf("逆转后:%s",ch); return 0; }
4.2 比较两个身份证字符串的生日大小。函数原型int isbothsame(char str1[19], char str2[19]);
#include <stdio.h> #include <stdlib.h> int isbothsame(char str1[19], char str2[19]) { int low = 6, hight = 13; while (low<hight &&str1[low] == str2[low])low++; //low记录不相同的位置 return str1[low] - str2[low]; //负数表示str1的年长 } int main() { char a[] = "412824199605281234",b[] = "41282519960825789x"; if(isbothsame(a,b) < 0) printf("a年长!"); else printf("b年长!"); return 0; }
4.3 计算1-x+x^2/2!-x^3/3!+…+x^n/n! 【见2015年】
void main() { int n, x, j, i = 1; float sum = 1, k = -1; printf("Input n and x: "); scanf("%d %d", &n, &x); while (i <= n) { k = -1; for (j = 1; j <= i; j++) { k = -1*k*x; } for (j = 1; j <= i; j++) { k = k/ j; } sum += k; i++; } printf("%f ", sum); }
动态规划改进:
void main() { int n,x,i=1; float sum = 1,k = -1; printf("Input n and x: "); scanf("%d %d", &n, &x); while (i <= n) { k = -1 * k*x / i; sum += k; i++; } printf("%f", sum); }
4.4一个链表,找出其中数据项最大的结点,然后将其移动到链表尾部(结点node由整型data和节点指针next构成),不允许申请新的结点
#include <stdio.h> #include <stdlib.h> typedef struct slist { int data; struct slist *next; }; void movemax(struct slist *L) { struct slist *p = L->next, *pre = L, *max = p; //找到最大值的位置 while (p) { if (p->data>max->data)max = p; pre = p; p = p->next; } //此时p指向NULL,pre指向最后一个结点 //最大值和最后一个节点交换 int temp = pre->data; pre->data = max->data; max->data = temp; } int main() { //建立单链表【尾插法】 int a[] = {1,4,7,8,5,2,9,6,3}; struct slist *p,*head = (struct slist*)malloc(sizeof(struct slist)); head ->next = NULL; int i; p = head; for(i = 0;i < 9;i++) { struct slist *node = (struct slist*)malloc(sizeof(struct slist)); node ->data = a[i]; node ->next = p ->next; p ->next = node; p = node; } printf("找到最大值后移: "); movemax(head); //输出 p = head ->next; while(p != NULL) { printf("%d ",p ->data); p = p->next; } return 0; }