【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day15

发布于:2025-08-30 ⋅ 阅读:(11) ⋅ 点赞:(0)

🔥个人主页:@草莓熊Lotso

🎬作者简介:C++研发方向学习者

📖个人专栏: 《C语言》 《数据结构与算法》《C++知识分享》《编程工具入门指南》

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。

前言:我们距离学习完C语言已经很久了,在数据结构学完后,博主准备通过这16天的强化训练和大家一起回顾C语言的知识,今天依旧是五道选择和两道编程题,希望大家能有所收获。


目录

选择题:

编程题:

 1.寻找奇数

2.寻找峰值


选择题:

1、有如下代码,则 *(p[0]+1) 所代表的数组元素是( )
A: a[0][1] B: a[1][0] C: a[1][1] D: a[1][2]

int a[3][2] = {1, 2, 3, 4, 5, 6}, *p[3];
p[0] = a[1];

答案解析:

正确答案:C

p是一个指针数组,p[0] = a[1];此处a[1]是二维数组的第二行的数组名,数组名表示首元素的地址,a[1]是a[1][0]的地址,所以p[0]中存储的是第2行第1个元素的地址,p[0]+1就是第二行第2个元素的地址,*(p[0]+1)就是第二行第二个元素了。所以C正确


2、关于指针下列说法正确的是【多选】( )

A: 任何指针都可以转化为void * B: void *可以转化为任何指针

C: 指针的大小为8个字节 D: 指针虽然高效、灵活但可能不安全

 答案解析:

正确答案:ABD

C选项,指针占几个字节要看平台,64位环境下8个字节,32位环境下4个字节

3、以下 scanf 函数调用选项中, 错误的是( )

A.scanf("%s",a[0].name); B.scanf("%d", &pa[0].age);

C.scanf("%d",&(pa->age)); D.scanf("%d", pa->age);

答案解析:

正确答案:D

该题考察的是通过scanf函数的调用对结构体数据类型进行初始化。scanf("输入控制符", 输入参数);功能:将从键盘输入的字符转化为“输入控制符”所规定格式的数据,然后存入以输入参数的值为地址的变量中。scanf输入时要通过地址找空间, B、C用了&是正确的。name属于字符数组的数组名,相当于数组的首地址,A正确。单独的pa->age可用于输出语句获取值的形式,用在scanf中的时候需要&操作符,D错误

4,如下函数fun计算prod=1*2*3*…*n ,并返回计算结果值。但当 n>12 时,返回值不正确。要找出该程序的错误,正确的调试方法是( )

A: 监视变量prod的值,在prod *= i;行处设置断点,然后单步运行,直到发现错误原因

B: 监视变量prod的值,在return prod;行处设置断点,程序中断后,即可发现错误原因

C: 在prod=1;处设置断点,然后在函数调用堆栈中即可发现错误原因

D: 监视变量i的值,在for (i=1; i<=n; i++)行处设置断点,然后单步运行,直到发现错误原因

int fun(int n)
{
	int prod = 1, i = 0;
	for (i = 1; i <= n; i++)
	{
		prod *= i;
	} 
	return prod;
}

答案解析:

正确答案:A

依题目已知情况,当n<=12时结果是正确的,说明是随着参数的变大计算过程中哪里出了问题,故而要在prod *= i;处设断点,查看原因。错误原因是数据过大时整型溢出

5、下列给定程序中,函数 fun 的功能是:把形参a所指数组中的奇数按原顺序依次存放到 a[0]、a[1]、a[2]… 中,把偶数从数组中删除,奇数个数通过函数值返回。 例如,若a所指数组中的数据最初排列为: 9,1,4,2,3,6,5,8,7 ,删除偶数后,a所指数组中的数据为: 9,1,3,5,7 ,返回值为5。请在程序的下画线处填入正确的内容并将下画线删除,使程序得出正确的结果( )

A: 0 j++ j B: 1 j++ j+1 C: 0 j++ j+1 D: 1 j++ j

int fun(int a[], int n)
{
	int i, j;
	j = 0;
	for (i = 0; i < n; i++)
		if (a[i] % 2 == _________)
		{
			a[j] = a[i];
			_________;
		} 
	return _________;
}

答案解析:

正确答案:D

代码实现的思路应该是arr[i]是奇数的时候要存储起来,所以第一个空是1,最开始j是0,每次找到一个奇数就存储到arr[j]的位置,那接下里j需要+1,所以得第二个空是j++,当循环停止的时候,j其实就是奇数的个数。所以最后返回j,第三个空是j。所以选D。


编程题:

 1.寻找奇数

题目链接:寻找奇数_牛客题霸_牛客网

题目描述:

题目示例:

代码演示:

#include<stdio.h>
int main()
{
    int n = 0;
    int num = 0;
    int ret = 0;
    scanf("%d",&n);
    for(int i = 0; i < n; ++i)
    {
        scanf("%d",&num);
        ret ^= num;
    }
    printf("%d",ret);
}

题目解析:

  • 异或:二进制比特位相同则0, 不同则1.
  • 两个相同的数字异或得到的是0, 基于这个思路,这道题对数组中的所有数据进行逐一异或就可以解决得到奇数次的数字,因为偶数次的数字都被异或成为0了,最后单独保留了奇数次的数字。

2.寻找峰值

题目链接:寻找峰值_牛客题霸_牛客网

题目描述:

题目示例:

代码演示:

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param nums int整型一维数组
 * @param numsLen int nums数组长度
 * @return int整型
 */
int findPeakElement(int* nums, int numsLen ) {
//边界情况处理,1个元素前后都是负无穷 以及 0号位置大于1号位置,-1位置负无穷的情况
    if (numsLen == 1 || nums[0] > nums[1]) return 0;
//末尾位置数据大于上一个位置数据,而nums[numsLen]负无穷的情况
    if (nums[numsLen - 1] > nums[numsLen - 2]) return numsLen - 1;
    int left = 0, right = numsLen - 1, mid;
    while (left < right) {
        mid = left + (right - left) / 2;
        if (nums[mid] < nums[mid +
                             1])//中间比右边小,意味着右边肯定有个峰值
            left = mid + 1;
        else //否则在左边包括当前位置肯定有个峰值
            right = mid;
    } 
    return left;
}

题目解析:

  • 中间比右边大,认为从右往左半边递增,则把 right 不断向左靠拢 right=mid ,注意不能是 mid-1 ,因为这个位置有可能就是峰值点。
  • 直到遇到中间比右边小了,意味着数据开始递降了,则 left 向右偏移, left=mid+1 ; 而一旦 mid+1 位置大于了right ,意味着刚好这个 mid+1 位置,是一个左半边-右往左递降,右半边-右往左递增的点,就是一个峰值点。

往期回顾:

【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day11

【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day12

【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day13

【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day14

结语:本篇博客就到此结束了,C 语言的精髓在于对细节的掌控和对底层的理解,这需要持续实践。愿你带着这份训练中获得的思维与习惯,在编程路上走得更稳、更远。如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持。