【C/C++笔试练习】——常量指针和指针常量、结构体内存分配、统计输入的字母个数、排序子序列、倒置字符串

C/C++笔试练习

1.常量指针和指针常量

(1)常量指针和指针常量的定义

  请找出下面程序中有哪些错误()

int main()
{
	int i = 10;
	int j = 1;
	const int *p1;//(1)
	int const *p2 = &i; //(2)
	p2 = &j;//(3)
	int *const p3 = &i;//(4)
	*p3 = 20;//(5)
	*p2 = 30;//(6)
	p3 = &j;//(7)
	return 0;
}

  A 1,2,3,4,5,6,7    B 1,3,5,6
  C 6,7        D 3,5

  

  “常量指针”和“指针常量”是两种特殊类型的指针,它们有着各自的特性和用途。

  (1)常量指针(Constant Pointer):

  常量指针是指向常量的指针。这意味着你不能通过这个指针来改变它所指向的值,但你可以改变这个指针本身所指向的地址。例如:

int a = 5;  
int b = 10;  
int * const ptr = &a;  
*ptr = 10;  // 正确,可以修改ptr所指向的值  
ptr = &b;   // 错误,不能修改ptr所指向的地址

  (2)指针常量(Pointer Constant):

  指针常量是指常指针,即指针本身是个常量,不能改变它的指向,但它所指向的值可以改变。例如:

int a = 5;  
int b = 10;  
const int * ptr = &a;  
*ptr = 10;  // 错误,不能修改ptr所指向的值  
ptr = &b;   // 正确,可以修改ptr所指向的地址

  
  判别常量指针和指针常量我们可以通过const和*的位置来判断:

  int const * p:const 在 *p 前面为常量指针

  int * const p:* 在const前面为指针常量

在这里插入图片描述

  (6)int const *p2 = &i; 这里定义了一个指向 const int 的指针 p2,然后试图修改它指向的值 *p2 = 30;,这是不允许的,因为 *p2 是一个常量,此时const修饰的是p2指向的值,所以不能被修改。

  (7)int *const p3 = &i; 这里定义了一个 const 指针 p3,然后试图改变它的指向 p3 = &j;,这是不允许的,因为 p3 是一个常量指针,此时const修饰的是p3,是一个指针,所以不能改变它的指向。

   答案选:C

             

(2)判别常量指针和指针常量

   下面3段程序代码的效果一样吗()

int b;
(1)const int *a = &b;
(2)int const *a = &b;
(3)int *const a = &b;

   A (2)=(3)       B (1)=(3)
   C (1)=(2)       D 都不一样

在这里插入图片描述
  通过上面的概念我们可以得到:(1)是常量指针(2)是常量指针(3)是指针常量

   答案选:C

             

(3)常量指针和指针常量的特性

   请声明一个指针,其所指向的内存地址不能改变,但内存中的值可以被改变。

A.const int const *x = &y;
B.int * const x = &y;
C.const int *x = &y;
D.int const *x = &y;
E.const int * const x = &y;

在这里插入图片描述
   结合第(1)(2)对于常量指针和指针常量的介绍

   答案选:B

             

2.结构体内存分配

(4)计算结构体大小

   在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是()

struct A
{
	int a;
	short b;
	int c;
	char d;
};

struct B
{
	int a;
	short b;
	char c;
	int d;
};

   A 16,16       B 13,12
   C 16,12       D 11,16

结构体内存对齐

在这里插入图片描述

   答案选:C
  

(5)位段的内存分配计算

  在32位cpu上选择缺省对齐的情况下,有如下结构体定义:

struct A{
unsigned a : 19;
unsigned b : 11;
unsigned c : 4;
unsigned d : 29;
char index;
};

  则sizeof(struct A)的值为()

  A 9     B 12
  C 16     D 20

在这里插入图片描述
  为了放下unsigned类型元素,系统申请了四个字节即32个比特位,此时可以放下a和b总共30比特位,接下来的c占4比特位,前四个字节放不下了,所以再开辟四个新的字节空间放入c,接下来的的d占了29个比特位,第二个字节已经有了4个比特位,29+4=33>32放不下,所以再开辟四个字节。放入上面的5个元素时,struct A一共占13个字节,根据结构体对其规则,结构体的大小必须为最大对齐数的整数倍,所以还要申请3个字节,使其成为4的整数倍。

   答案选:C

             

3.完善程序

(6)统计输入大写字母的出现次数

   以下 C++ 函数的功能是统计给定输入中每个大写字母的出现次数(不需要检查输入合法性,所有字母都为大写),则应在横线处填入的代码为()

void AlphabetCounting(char a[], int n) 
{
	{
		int count[26] = {}, i, kind = 10;
		for (i = 0; i < n; ++i)
		_________________;
		for (i = 0; i < 26; ++i) {
		printf("%c=%d", _____, _____);
	}
}

  A ++count[a[i]-‘Z’]     B ++count[‘A’-a[i]]
   ‘Z’-i           ‘A’+i
   count[‘Z’-i]       count[i]

  C ++count[i]      D ++count[‘Z’-a[i]]
   i           ‘Z’-i
   count[i]        count[i]

   们需要统计给定输入中每个大写字母的出现次数。给定的输入是一个字符数组a,数组长度为n。

   首先,我们定义一个长度为26的整型数组count,用来存储每个大写字母出现的次数。数组下标0对应字母’A’,下标1对应字母’B’,以此类推,下标25对应字母’Z’。

   接下来,我们遍历输入字符数组a中的每个字符。对于每个字符,我们可以将其与字符’Z’做差,得到对应的数组下标,然后将对应的计数器加1。

   最后,我们遍历计数器数组count,输出每个字母和其出现的次数。

   答案选:D

             

4.编程题

(7)排序子序列

排序子序列

  解题思路:

  (1)应该依次比较整个数组

  (2)a[i+1]>a[i] ,则进入非递减序列判断, 直到遍历到下一个值不大于等于为止count++,然后进行下一位置的判断

  (3)a[i+1]<a[i],则进入非递增序列判断, 直到遍历到下一个值不小于等于为止count++,然后进行下一位置的判断

  (4)a[i+1] == a[i]不进行操作,++i进行下一位置遍历,因为相等既可以属于非递增序列,也可以属于非递减序列。

#include <iostream>
#include<vector>
using namespace std;

int main() {
    int n=0;
    cin>>n;
    vector<int> v(n,0);
    for(int i=0;i<n;i++)
    {
        cin>>v[i];
    }
    //遍历整个vector
    int i=0;
    int count=0;
    while(i<n)//如果有递增或者递减情况改变,计数器++
    {
        if(v[i]>v[i+1])//递减序列
        {
            while(i<n&&v[i]>=v[i+1])
            {
                i++;//满足递减情况就一直向后移动
            }

            //不满足了直接退出,count++
            count++;
            i++;//寻找下一段子序列的情况
        }
        else if(v[i]<v[i+1])//递增序列
        {
            while(i<n&&v[i]<+v[i+1])
            {
                i++;//满足递增情况就一直向后移动
            }

            count++;
            i++;
        }
        else//相等的元素直接向后走
        {
            i++;
        }
    }
    cout<<count;
    return 0;
}

             

(8)倒置字符串

倒置字符串

  解法一:

  先将整个字符串逆置过来,再遍历字符串,找出每个单词,对单词逆置。这里我们使用了stl算法中的reverse,所以这里使用迭代器遍历string。

#include <algorithm>
#include <iostream>
using namespace std;
 
int main() {
    string str;
    getline(cin,str);
    reverse(str.begin(),str.end());//整体反转
    //再进入循环单个反转
    string::iterator start=str.begin();
    while(start!=str.end())
    {
        auto end=start;
        while(*end!=' '&&end!=str.end())
        {
            end++;//找单个单词
        }
 
        //找到后反转单个单词
        reverse(start,end);
 
        //更改start和end的位置,使其指向下一个位置
        if(end!=str.end())
        {
            start=end+1;
        }
        else
        {
            start=end;
        }
    }
    cout<<str;
    return 0;
}

  
  解法二:

  直接利用cin>>s接收输入,遇到空格就结束了,自然就分割开了每个单词,其次将每次接收到的单词拼接到之前串的前面就逆置过来了。

#include <iostream>
#include <string>
using namespace std;

// cin读取string时自动会被空格分隔开,用另一个字符串存储进行逆序输出
int main()
{
	string s1, s2;
	cin >> s2;
	while (cin >> s1)
	s2 = s1 + " " + s2;
	cout << s2 << endl;
	return 0;
}
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鳄鱼麻薯球

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

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

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

打赏作者

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

抵扣说明:

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

余额充值