HOME/Articles/

面向对象程序设计-延期开学作业4简析

Article Outline

这个作业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++)
        for (___2___, k = 0; substr[k] == str[j]; k++, j++)
            if (substr[___3___] == '\0') {
                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数组,所以递归传递还得传an表示数组的元素个数,所以也原封不动传下去。只有i需要每次递归递增一个,等同于for循环的向后遍历一个位置。pk存放的是最大值的下标的地址,所以也原封不动传下去,如果有更大的修改pk指向的值就是了。

7. 连接字符串s1和s2

原题目:

/*下面函数的功能是将两个字符串s1 和s2 连接起来,请填空使程序完整。*/
void conj(char *s1, char *s2) {
    char *p = s1;
    while (*s1)  ____1____;
    while (*s2) {
        *s1 = ____2____;
        s1++, s2++;
    }
    *s1 = '\0';
    ____3____;
}

答案:

第一空:s1++

第二空:*s2

第三空:s1=p

解析:

第一空:这里的拼接,是把s2直接拼在s1后面,效果等同于strcat(s1, s2)。第一个while的作用就是把指针s1指向s1字符串的末尾,所以填s1++

第二空:把s2的字符逐一复制到s1的后面,很简单。

第三空:这里我困惑了很久,因为一开始定义的指针p根本没用上。后来明白了,因为s1本来指向第一个字符串开头,但是复制操作完成以后s1指针已经移到整个字符串末尾了,函数外面不能用。这里就用上了pp记录了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的原创文章,遵循 CC 4.0 BY-SA 版权协议。

允许转载,转载时请附上原文链接:https://switernal.cn/2020/02/13/面向对象程序设计延期开学作业4简析/