-
Notifications
You must be signed in to change notification settings - Fork 0
Description
这个作业4写起来相当难受,很大程度上来源于填空题只给出了一个函数,声明了一些奇奇怪怪的变量,也没有任何注释,题目要求也极其不明确,做题和解谜差不多,所以写篇博客简要分析一下。 注:填空第3题的第2空提交了几次还是不知道答案是多少 单选题 1. A 解析:函数名本身就是一个指针,指向函数的入口地址,这一点和数组比较像 2. B 解析:字符串本身也是一个指针,注意这个language是一个指针数组,因此每个元素相当于一个地址。 3. D 解析:这题比较奇怪,C和D都能编译成功。不过不选C的原因可能是因为这是一个野指针。注意,C选项是一个数组指针,但是没有初始化,打印出来的地址比较奇怪。 4. C 解析:注意运算符优先级问题。 5. C 解析:可以参考我写的C / C++ 指针数组和数组指针这篇文章中第一部分:优先级方面。这里不过多解释。 6. C 解析:同上,参考我写的C / C++ 指针数组和数组指针这篇文章。这里不过多解释。 7. A 解析:注意二维数组中要取两层地址才能获得元素的值。 8. D 解析:指针概念搞清楚。 填空题 1. 程序运行的结果 答案: 2,4,5,7,6,0,11,9,7,3, 解析: IDE跑一下抄下结果。 2. 程序运行的结果 答案: string_a=I am a teacher. string_b=You are a student. string_a=I am a teacher. string_b=I am a teacher. 解析: IDE跑一下抄下结果。 3. 字符串转换为整数 原题目: /下面函数的功能是将一个整数字符串转换为一个整数,例如:”-1234”转换为1234,请填空使程序完整。/ int chnum(char p) { int num=0,k,len,j ; len = strlen(p) ; for ( ;1; p++) { // len>0 k=2; // 不会 j=(--len) ; while (3) // j-- k = 10; num += k ; } return (num); } 答案: 第一空:len>0 第二空:(不会) 第三空:j-- 解析: 第一空:首先关注到下面有一行:j=(–len);,大致可以知道最后len一定会减到0。结合程序大致分析,要完成整个转换,那肯定得走len次,所以这里通过合理猜测,得出填len>0 第二空:试了几次都不对,我填的是p-'0',在IDE测试可以用,但这里答案不对,不知道为什么。这样填的理由是:因为注意到for循环中每次都进行p++,也就是把字符串指针往后移一个位置,所以p取出来的是当前位置的字符,通过与'0'相减,可以得出两个字符相对ASCII码的差值,正好是当前位的数字。 第三空:由于我们从第一位开始往后移动指针p,因此每一位要乘上10的len - 1次方才能加到最终的数字上,而上面定义了j就是我们要的len - 1,所以此处填j--。 4. 统计子串在母串中出现的次数 原题目: /函数的功能使统计子串substr 在母串str 中出现的次数,请填空使程序完整。/ int count(char *str, char *substr) { int i, j, k, num = 0; for (i = 0; 1; i++) // i<strlen(str) for (2, k = 0; substr[k] == str[j]; k++, j++) // j=i if (substr[3] == '\0') { // k+1 num++; break; } return (num); } 答案: 第一空:i<strlen(str) 第二空:j=i 第三空:k+1 解析: 变量解释: int i; // 控制外层for循环遍历母串的下标 int j; // 控制内层for循环母串下标 int k; // 控制子串下标 int num; // 子串数量 第一空:这个很好理解,从第一个字符开始遍历,直到最后一个字符,所以一共循环strlen(str) - 1次。 第二空:找字串,就是从母串当前(第i个字符)开始,往后k个字符都跟子串一样,这样就算找到一个子串。所以内层for循环是从i开始的,因此填j=i 第三空:子串长度为k,所以判断子串中k+1的位置是不是\0,如果是,就说明子串结束,找到一个子串,num++;如果不是,就break跳出内层for循环,开始下一个外层for循环。 5. 整数转字符数组 原题目: /下面函数的功能是用递归法将一个整数存放到一个字符数组中,存放时按逆序存放,如483 存放成“384”,请填空使程序完整。/ void convert(char *a, int n) { int i; if ((i = n / 10) != 0) convert(1, i); // a+1 *a = 2 ; // n+'0' } 答案: 第一空:a+1 第二空:n%10+'0' 解析: 第一空:a是一个指针,指向传入的字符串的起始地址,因此递归时每次把指针往后移一个位置,即a+1,直到最后一位。 第二空:和反位数算法有点像,不太想写了。提一下'0',和上面第3题里面的作用一样,通过ASCII码来进行字符和整数间相互转换。 6. 递归法求数组中的最大值及下标 原题目: /下面函数的功能是用递归法求数组中的最大值及下标值,请填空使程序完整。/ void findmax(int *a,int n,int i,int *pk) { if (i<n) { if (a[i]>a[*pk]) 1; // pk=i findmax(2) ; // a, n, i+1, pk } 答案: 第一空:pk=i 第二空:a,n,i+1,pk 解析: 第一空:通过分析,我们可以发现既然求最大值,pk这个指针指向的变量就是用来存最大值下标的,因此根据内层if来看,如果数组a中第i个元素比第pk个大,那么就把i赋值给pk。 第二空:分析+猜。因为是找数组中的最大元素,那数组就那一个a数组,所以递归传递还得传a,n表示数组的元素个数,所以也原封不动传下去。只有i需要每次递归递增一个,等同于for循环的向后遍历一个位置。pk存放的是最大值的下标的地址,所以也原封不动传下去,如果有更大的修改pk指向的值就是了。 7. 连接字符串s1和s2 原题目: /下面函数的功能是将两个字符串s1 和s2 连接起来,请填空使程序完整。/ void conj(char *s1, char *s2) { char *p = s1; while (*s1) 1; //s1++ while (*s2) { *s1 = 2; //*s2 s1++, s2++; } *s1 = '\0'; 3; //s1=p } 答案: 第一空:s1++ 第二空:*s2 第三空:s1=p 解析: 第一空:这里的拼接,是把s2直接拼在s1后面,效果等同于strcat(s1, s2)。第一个while的作用就是把指针s1指向s1字符串的末尾,所以填s1++。 第二空:把s2的字符逐一复制到s1的后面,很简单。 第三空:这里我困惑了很久,因为一开始定义的指针p根本没用上。后来明白了,因为s1本来指向第一个字符串开头,但是复制操作完成以后s1指针已经移到整个字符串末尾了,函数外面不能用。这里就用上了p,p记录了s1的起始地址,现在重新赋给s1就好。(用后归位) 8. 找出长度最大的字符串 原题目: /下面函数的功能是从输入的十个字符串中找出长度最大的那个串,请填空使程序完整。/ void fun(char str[10][81],char **sp) { int i; *sp = 1; //str[0] for (i=1; i<10; i++) if (strlen (*sp)<strlen(str[i])) 2; //**sp=i } 答案: 第一空:str[0] 第二空:*sp=str[i] 解析: 第一空:这里需要引入二维数组的行指针,具体可以参考C / C++ 指针数组和数组指针这篇文章中行指针部分内容,这里不过多解释。这里需要把行指针sp指向二维数组str的第0行。 第二空:本质上就是遍历数组找最大值的算法,这里只要把if判断那一行的strlen( )括号里的东西赋值就行了。 结语 答案不重要(虽然算平时分),不过最好能理解里面的知识点。 C和C++基础语法几乎完全一致,所以理解了C语言,学习C++会更得力一些。 有遗忘的部分多翻翻书,或者在菜鸟教程 - C语言教程查看相关部分。 《C Primer Plus》就是这时候作工具书查找语法点使用的,而不应该作为睡前读物。 版权声明:内容为Switernal.cn的作者「Sanders」的原创文章。 允许转载,转载时请附上原文链接。