C语言练习题(15) 有如下代码,则 *(p[0]+1) 所代表的数组元素是( )(非常详细的讲解)

1:有如下代码,则 *(p[0]+1) 所代表的数组元素是( )

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

A: a[0][1] B: a[1][0] C: a[1][1] D: a[1][2]

解析 C

a[3][2]={{1,2},{3,4},{5,6}}

p[0]代表3,即第二部分的第一个元素 p[0]+1即代表4,即p[0]的下一个元素 故*(p[0]+1)表示4,即a[1][1].

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

A: 任何指针都可以转化为void * B: void *可以转化为任何指针
C: 指针的大小为8个字节 D: 指针虽然高效、灵活但可能不安全


解析 ABD

指针大小和系统位数有关,16位系统是2个字节,32位系统是个4字节,64位系统是8个字节。

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

struct T
{
char name[20];
int age;
int sex;
} a[5], *pa=a;

A: scanf(“%s”,a[0].name); B: scanf(“%d”, &pa[0].age);
C: scanf(“%d”,&(pa->age)); D: scanf(“%d”, pa->age);


解析 D
在这里插入图片描述

BC:scanf输入时,要将值放到地址里,所以要加上&,所以B、C正确。

A:name属于字符数组的数组名,相当于数组的首地址,所以A正确。

D:pa->age属于输出语句获取值的形式,所以D错误。age是一个int型,没有做取地址操作。scanf(“%d”,pa->age)相当于pa[0]->age,传的是值不是地址。

此题的重点如下:

.和->都是用于访问结构体成员的运算符。它们的使用方式如下:

① . 运算符:

用于直接访问结构体变量的成员。 格式:结构体变量名.成员名 示例:a[0].name
②-> 运算符:

用于通过指向结构体的指针访问结构体成员。 格式:指针->成员名 示例:pa->age 区别:

. 运算符用于直接访问结构体变量的成员,而-> 运算符用于通过指针访问结构体变量的成员。 当我们有一个结构体变量时,使用.运算符直接访问其成员。 当我们有一个指向结构体的指针时,使用-> 运算符来访问结构体的成员。

通过.运算符访问结构体成员时,需要使用结构体变量名。通过->运算符访问结构体成员时,需要使用指向结构体的指针。

4:如下函数 fun 计算 prod=123*…*n ,并返回计算结果值。但当 n>12 时,返回值不正确。要找出该程序的错

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

A: 监视变量prod的值,在prod *= i;行处设置断点,然后单步运行,直到发现错误原因
B: 监视变量prod的值,在return prod;行处设置断点,程序中断后,即可发现错误原因
C: 在prod=1;处设置断点,然后在函数调用堆栈中即可发现错误原因
D: 监视变量i的值,在for (i=1; i<=n; i++)行处设置断点,然后单步运行,直到发现错误原因

解析 A

通过监视变量prod的值,在prod *=i;行处设置断点,可以观察每一步乘法操作后的结果,进而找到错误发生的位置。当n>12时,由于整数溢出的问题,prod的值会变得不正确。在找到错误原因后,可以采取相应的修复措施,例如使用long long类型来存储prod的值,以避免溢出问题。

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。请在程序的下画线处填入正确的内容并将下画线删除,使程序得出正确的结果( )

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 _________;
}

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

解析 D

在函数中,定义了两个整型变量"i"和"j",并初始化"j"为0。

然后使用循环遍历数组元素,从下标0开始,逐个判断数组元素是否为奇数。当满足条件时,将该元素移动到数组的前端,即将其赋值给"a[j]",然后"j"自增1。

最后,返回"j",即移动后的奇数元素个数。

6:现在有一个长度为 n 的正整数序列,其中只有一种数值出现了奇数次,其他数值均出现偶数次,请你找出那个出现奇数次的数值。

数据范围:1≤n≤2×10 ^6
输入描述:第一行:一个整数n,表示序列的长度。第二行:n个正整数ai,两个数中间以空格隔开。
输出描述:一个数,即在序列中唯一出现奇数次的数值。
示例1
输入:
5
2 1 2 3 1
输出:3

示例2
输入:
1
1
输出:1

#include<stdio.h>
int main()
{
    int sz,i;
    scanf("%d",&sz);
    int count,m=0;
    for(i=0;i<sz;i++)
    {
        scanf("%d",&count);
        m=m^count;
    }
    printf("%d",m);
    return 0;
}

解析
为什么利用异或运算可以算出一个数组中出现奇数次的数字?

利用异或运算可以找出一个数组中出现奇数次的数字,是因为异或运算具有以下两个性质:

任何数字与0进行异或运算,结果仍为该数字本身。即:a ^ 0 = a 任何数字与自身进行异或运算,结果为0。即:a ^ a = 0

基于这两个性质,我们可以得出以下结论:
①对于一个数组中的数字,在数组中出现偶数次的数字进行异或运算,结果为0。因为每个数字都会与相同的数字进行两次异或运算,结果抵消为0。
②对于一个数组中的数字,在数组中出现奇数次的数字进行异或运算,结果为这些数字的异或结果。
③所以,当我们将数组中所有数字进行异或运算,最终得到的结果就是出现奇数次的数字。其他出现偶数次的数字在异或运算中都抵消为0,不会对最终结果产生影响。

因此,通过利用异或运算,我们可以从一个数组中找出出现奇数次的数字。

7:给定一个长度为n的数组nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。

1.峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于
2.假设 nums[-1] = nums[n] = −∞
3.对于所有有效的 i 都有 nums[i] != nums[i + 1]
4.你可以使用O(logN)的时间复杂度实现此问题吗?
数据范围:1≤nums.length≤2×10 ^5
−2^ 31 <=nums[i]<=2 ^31−1
如输入[2,4,1,2,7,8,4]时,会形成两个山峰,一个是索引为1,峰值为4的山峰,另一个是索引为5,峰值为8的山峰,如下图所示:
在这里插入图片描述
示例1
输入:[2,4,1,2,7,8,4]
返回值:1
说明:4和8都是峰值元素,返回4的索引1或者8的索引5都可以

示例2
输入:[1,2,3,1]
返回值:2
说明:3 是峰值元素,返回其索引 2

核心代码:

int findPeakElement(int* nums, int numsLen) 
{
    if (numsLen <= 1) 
    {
        return 0; // 数组长度为0或1,假定第一个元素为峰值
    }
    
    int i;
    for (i = 0; i < numsLen; i++) 
    {
        if ((i == 0 || nums[i-1] < nums[i]) && (i == numsLen-1 || nums[i] > nums[i+1])) 
        {
            return i; // 找到峰值元素
        }
    }
    
    return -1; // 没有找到峰值元素
}

完整代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int findPeakElement(int* nums, int numsLen)
{
    if (numsLen <= 1)
    {
        return 0; // 数组长度为0或1,假定第一个元素为峰值
    }
    int i;
    for (i = 0; i < numsLen; i++)
    {
        if ((i == 0 || nums[i - 1] < nums[i]) && (i == numsLen - 1 || nums[i] > nums[i + 1]))
        {
            return i; // 找到峰值元素
        }
    }
    return -1; // 没有找到峰值元素
}

long long main() 
{
    int nums[1000] = { 0 };
    int numsLen = 0;
    scanf("%d", &numsLen);
    for (int j = 0; j < numsLen; j++)
    {
        scanf("%d", &nums[j]);
    }
    int peakIndex = findPeakElement(nums, numsLen);
    printf("峰值为: %d\n", peakIndex);
    return 0;
}

解析

①函数findPeakElement接受一个整型数组nums和数组的长度numsLen作为参数。在函数内部,它首先检查数组长度是否小于或等于1,如果是,则返回0,假设第一个元素为峰值。

②然后,使用一个循环遍历整个数组。对于每个元素,检查其是否满足峰值的条件:要么它是第一个元素且大于其后一个元素,要么它是最后一个元素且大于其前一个元素,或者它既大于其前一个元素又大于其后一个元素。如果满足条件,则返回该元素的索引,表示找到了峰值元素。

③ 如果循环结束后没有找到峰值元素,则返回-1,表示没有找到。

④在主函数main中,首先声明一个大小为1000的整型数组nums,并初始化为全0。然后通过scanf函数从标准输入读取一个整数numsLen,表示数组的长度。接下来,使用一个循环从标准输入读取numsLen个整数,将它们存储在数组nums中。

⑤最后,调用findPeakElement函数,并将返回的峰值元素的索引赋值给peakIndex。然后使用printf函数打印出峰值元素的索引。

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chris·Bosh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值