【C语言进阶】 假期测评③

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【C语言进阶】 假期测评③

day01

1. 改变形参不影响实参

以下程序执行后的输出结果为()

#include <stdio.h>
void func(char *p) {
    
     p = p + 1; }
int main()
{
    
    
char s[] = {
    
    '1', '2', '3', '4'};
func(s);
printf("%c", *s);
return 0;
}

A: 2 B: 编译错误 C: 1 D: 无法确定

【答案解析】C
调用函数func时传的是s的值,==形参p的改变,并不会改变s本身,== *s拿到的还是首地址的字符'1'

2. 二维数组省略

已知数组D的定义是 int D[4][8]; 现在需要把这个数组作为实参传递给一个函数进行处理。下列可以作为对应的形参变量说明的是【多选】( )
A: int D[4][]
B: int *s[8]
C: int(*s)[8]
D: int D[][8]

【答案解析】CD
数组D是一个二维数组,函数传参时数组名退化为首元素地址,就是第一行的地址,是一维数组的地址,为int(*)[8]类型,C正确,
B选项是指针数组的,这里不行;
==若想写成数组的形式,则列不能省行可以省,(对于多维数组,较低维度都是不可省略的)==
D选型格式是对的,A选项不对

3. 查找质数

博客讲解
单纯的使用枚举法会超出时间限制
在这里插入图片描述
在这里插入图片描述

day02

4. 位运算

day03

5. 字符串赋值给指针

设有定义: char p; ,以下选项中不能正确将字符串赋值给字符型指针 p 的语句是【多选】( )
A: p=getchar(); B: scanf("%s",p); C: char s[]="china"; p=s; D: `
p="china";`

【答案解析】ABD
A选项,首先类型就不匹配,==getchar()函数返回值是int== ,只能赋值给整型,此时p为char类型。
B选项,p指针在定义的时候没有分配内存,这行代码在运行的时候会报野指针错误。
C选项,指针p指向数组s。
D选项,
p代表p指向内存的内容, 这里要使用p = "china"才正确
在这里插入图片描述

6. 指针类型的判断

若有定义语句: char s[3][10],(*k)[3],*p; 则以下赋值语句错误的是()
1.p = s;
2.p = k;
3.p = s[0];
4.k = s;
A: 124 B: 1234 C: 12 D: 234

【答案解析】A
题目主要就考指针类型是否一样,char s[3][10]中s运算时会退化为数组指针,类型为char (*)[10],所指向的每个数组长度为10;
char (*k)[3]很明显k就是一个数组指针,类型也为 char (*)[3],所指向的每个数组的长度为3;
==char *p类型为char *指针,s[0]代表二维数组第一行,运算时会退化为第一行首元素地址,类型为char *==
==在没有强制类型转换的情况下,只有类型完全相同的指针才能相互赋值==

7. 判断两字符串元素是否相等

在这里插入图片描述

day04

8. 指针++移动

运行以下C语言代码,输出的结果是( )

#include <stdio.h>
int main()
{
    
    
char *str[3] ={
    
    "stra", "strb", "strc"};
char *p =str[0];
int i = 0;
while(i < 3)
{
    
    
printf("%s ",p++);
i++;
}
return 0;
}

A: stra strb strc B: s t r C: stra tra ra D: s s s

【答案解析】C
==p是char类型,每次++,后移一个地址,== char p = str[0]相当于char *p = "stra",p先指向其中的字符's',printf输出遇到0停止,第一次输出"stra",p++后,指向字符't',第二次输出"tra",第三次输出"ra"

9. 循环判断

程序的结果是什么( )
A: abdcccd B: abdd C: abcc D: abddcccd

#include<stdio.h>
char* f(char* str, char ch)
{
    
    
    char* it1 = str;
    char* it2 = str;
    while (*it2 != '\0')
    {
    
    
        while (*it2 == ch)
        {
    
    
            it2++;
        }
        *it1++ = *it2++;
    }
    return str;
}
int main() {
    
    
    char a[10];
    strcpy(a, "abcdcccd");
    printf("%s", f(a, 'c'));
    return 0;
}

【答案解析】D
内层while循环的作用让指针it2跳过字符'c',第一次越过后停在原字符串第一个'd'上,而在之前it1和it2是同步的,赋值不会改变字符串内容,==此时it1停在第一个'c'上,it1++ = it2++;语句将'c'替换为'd',字符串变更为"abddcccd",同时指针it1加加停在第四个字符'd'上,it2再次跳过字符'c',停在最后一个'd'上,赋值后,字符串不变,== 再后移外层循环遇到0结束

day05

10. 忘记释放内存后果

假设C语言程序里使用 malloc 申请了内存,但是没有 free 掉,那么当该进程被kill之后,操作系统会( )
A: 内存泄露 B: segmentation fault C: core dump D: 以上都不对

【答案解析】D
==不管用户程序怎么用malloc,在进程结束的时候,用户程序开辟的内存空间都将会被回收。只有在进程运行的过程中,忘记释放内存才会造成内存泄漏==

11. 联合体的性质

设有以下定义,则下面叙述中正确的是【多选】()

union D
{
    
    
int d1;
float d2;
}d;

A: 变量d与各成员的地址相同
B: d.d1和d.d2具有相同的地址
C: 若给d.d2赋10后,d.d1中的值是10
D: 若给d.d1赋10后,d.d2中的值是10

【答案解析】AB
虽然d1,d2地址相同,但存储的是二进制,==浮点型的10和整型的10,二进制是不同的,所以读取出来的结果也是不同的==
C,D所要表达的意思就是以浮点数/整型存储再以整型/浮点数的形式读取,显然结果不同

12. 移位操作:<< >>区别

在这里插入图片描述

day06

13. 内存管理函数性质

关于内存管理,以下有误的是( )
A: malloc在分配内存空间大小的时候是以字节为单位
B: 如果原有空间地址后面还有足够的空闲空间用来分配,则在原有空间后直接增加新的空间,使得增加新空间后的空间总大小是:newSize
C: 如果原有空间地址后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存,并把先前内存空间中的数据复制到新的newSize大小的空间中,然后将之前空间释放
D: free函数的作用是释放内存,内存释放是标记删除,会修改当前空间的所属状态,并且会清除空间内容

【答案解析】D
选项A:malloc函数用来动态地分配内存空间,其原型void malloc (size_t size); size 为需要分配的内存空间的大小,以字节(Byte)计。
选项B:realloc函数,其原型extern void
realloc(void *mem_address, unsigned int newsize);如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address。realloc是从堆上分配内存的,当扩大一块内存空间时,realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,即如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize,得到的是一块连续的内存。
选项C:realloc函数,如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存,并把原来大小内存空间中的内容复制到newsize中,返回新的mem_address指针,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。
==选项D:free函数,作用是释放内存,内存释放是标记删除, 只会修改当前空间的所属状态,并不会清除空间内容==(在代码实现过程中,free结束,通常后面要加上xxx = NULL)

14. 柔性数组

如下程序输出的结果是什么( )

#include <stdio.h>
typedef struct List_t
{
    
    
struct List_t* next;
struct List_t* prev;
char data[0];
}list_t;
int main()
{
    
    
printf("%d",sizeof(list_t));
return 0;
}

A: 4byte B: 8byte C: 5byte D: 9byte

【答案解析】B
==题目中的char data[0]或写成char data[],即为柔性数组成员;==
在计算机结构体大小的时候data不占用struct的空间,只是作为一个符号地址存在。因此sizeof的值是两个指针所占字节,即4+4=8字节

15. free/malloc 性质

以下有关C语言的说法中,错误的是( )
A: 内存泄露一般是指程序申请了一块内存,使用完后,没有及时将这块内存释放,从而导致程序占用大量内存,但又不使用不 释放
B: 可以通过malloc(size_t)函数调用申请超过该机器物理内存大小的内存块
C: 无法通过内存释放函数free(void*)直接将某块已经使用完的内存直接还给操作系统,free函数只是将动态申请内存的使用权释放
D: 可以通过内存分配函数malloc(size_t)直接申请物理内存

【答案解析】D
==free释放的内存不一定直接还给操作系统,可能要到进程结束才释放。malloc不能直接申请物理内存,它申请的是虚拟内存==

16. 读写文件

若要用 fopen 函数打开一个新的二进制文件,该文件既能读也能写,则文件方字符串应是( )
A: "ab++" B: "wb+" C: "rb+" D: "ab"

【答案解析】B
==w+以纯文本方式读写,而wb+是以二进制方式进行读写。==
mode说明:
w打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
wb只写方式打开或新建一个二进制文件,只允许写数据。
wb+读写方式打开或建立一个二进制文件,允许读和写。
r打开只读文件,该文件必须存在,否则报错。
r+打开可读写的文件,该文件必须存在,否则报错。
rb+读写方式打开一个二进制文件,只允许读写数据。
a以附加的方式打开只写文件
a+以附加方式打开可读写的文件。
ab+读写打开一个二进制文件,允许读或在文件末追加数据。
加入b字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件

17. 十进制乘法转换成二进制移位

详细解法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

day07

18. fputc函数返回值

若调用 fputc 函数输出字符成功,则其返回值是( )
A: EOF B: 1 C: 0 D: 输出的字符

【答案解析】D
==fputc()写入成功时返回写入的字符,失败时返回EOF即-1,返回值类型为int也是为了容纳这个负数==

19. 5的倍数

【答案解析】
在这里插入图片描述

在这里插入图片描述

20. 强转的意义

在这里插入图片描述
在这里插入图片描述

day08

21. #define的替换

以下代码的输出结果是( )

#include <stdio.h>
#define a 10
void foo();
int main()
{
    
    
printf("%d..", a);
foo();
printf("%d", a);
return 0;
}
void foo(){
    
    
#undef a
#define a 50
}

A: 10..10 B: 10..50 C: Error D: 0

【答案解析】A
define在预处理阶段就把main中的a全部替换为10。另外,不管是在某个函数内,还是在函数外,define都是从定义开始直到文件结尾,所以==如果把foo函数的定义放到main上面的话,则结果会是50..50==

22. 数据推导:建表

在这里插入图片描述
【答案解析】
在这里插入图片描述
这道题其实本身并不难,有了具体的公式直接循环往后推导就可以得到结果。但是当测试用例有多个的情况下,每次重新计算第k个数据,效率就要差很多了,毕竟每个数都要从头重新计算一遍。
==因此程序进入后首先可以先生成一个较大的数列,后边测试用例中需要第几个直接取出即可。==

#include <stdio.h>
int main()
{
   
   
    long n;
    long arr[100000] = {
   
    1, 2 };
    //先生成数列,注意这里存入的是取模后的结果,否则数据会越界
    for (int i = 2; i < 100000; i++) {
   
   
        arr[i] = (arr[i - 1] * 2 + arr[i - 2]) % 32767;
    }
    scanf("%d", &n);//获取测试用例个数
    for (int i = 0; i < n; i++) {
   
   
        int num;
        scanf("%d", &num);
        printf("%ld\n", arr[num - 1]);//循环打印每个测试用例的对应结果就行
    }
    return 0;
}

在这里插入图片描述

相关文章
|
5月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
5月前
|
数据库 C语言
C语言进阶 文件操作知识(上)
C语言进阶 文件操作知识(上)
37 3
|
5月前
|
存储 C语言
C语言进阶 文件操作知识(下)
C语言进阶 文件操作知识(下)
37 2
|
5月前
|
存储 编译器 数据库
【再识C进阶5(上)】详细介绍C语言文件操作——文件是用于存储数据
【再识C进阶5(上)】详细介绍C语言文件操作——文件是用于存储数据
|
5月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
47 0
|
6月前
|
编译器 C语言 C++
从C语言到C++_21(模板进阶+array)+相关笔试题(下)
从C语言到C++_21(模板进阶+array)+相关笔试题
47 2
|
6月前
|
C语言
C语言进阶:进阶指针(下)
C语言进阶:进阶指针(下)
48 2
|
6月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
63 1
|
6月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
76 1
|
6月前
|
C语言
C语言进阶:指针的进阶(上)
C语言进阶:指针的进阶(上)
61 1