C语言刷题——指针概念

Posted wangjiushun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言刷题——指针概念相关的知识,希望对你有一定的参考价值。

1.关于指针的概念,错误的是:( )

A.指针是变量,用来存放地址

B.指针变量中存的有效地址可以唯一指向内存中的一块区域

C.野指针也可以正常使用

D.局部指针变量不初始化就是野指针

解析:

答案是:C

野指针不可以正常使用。

知识点:

1、指针就是地址,但口语中说的指针通常指的是指针变量。

2、指针变量:指针变量是用来存放地址的,地址是唯一标识一个内存单元的。(我们通过&取出变量的起始地址,把地址存放到一个变量中,这个变量就是指针变量)。

3、野指针

        (1)概念:野指针就是指针指向的位置是不可知的——就像一条野狗。

        (2)野指针成因:

                ①指针未初始化;

                ②指针越界访问;

                ③指针指向的空间释放。

        (3)如何规避野指针

                ①指针初始化(没有明确初始化的指针初始化NULL(本质是0))

                ②小心指针越界

                ③指针指向空间释放,及时置NULL

                ④避免返回局部变量的地址

                ⑤指针使用前检查有效性

                补充:NULL本质是0,在C++可以直接写0,但是C不可以,C要写成NULL

              //为什么要写成NULL,变量一旦赋值为NULL你就知道这是一个指针,让你容易识别

              //0地址是用户不能使用的,使用的话程序会崩溃。

2.以下系统中,int类型占几个字节,指针占几个字节,操作系统可以使用的最大内存空间是多大( )

A.32位下:4,4,2^32 64位下:8,8,2^64

B.32位下:4,4,不限制 64位下:4,8,不限制

C.32位下:4,4,2^32 64位下:4,8,2^64

D.32位下:4,4,2^32 64位下:4,4,2^64

解析:

答案是:C

①int类型在32位64位平台下都是4字节;
②指针在32位平台是4字节,在64位平台下是8字节;
③操作系统可以使用的内存空间:地址空间的个数32位平台是2^32个,64位平台是2^64个

3.下面代码的结果是:( )

#include <stdio.h>

int main()

    int arr[] =  1,2,3,4,5 ;
    short* p = (short*)arr;//arr是int*类型,将int*强制转换为short*
    int i = 0;
    for (i = 0; i < 4; i++)
    
        *(p + i) = 0;
    

    for (i = 0; i < 5; i++)
    
        printf("%d ", arr[i]);
    
    return 0;

A.1 2 3 4 5

B.0 0 3 4 5

C.0 0 0 0 5

D.1 0 0 0 0

解析:

答案是:B

知识点:

指针的类型:

①指针的解引用:指针的类型决定了,对指针解引用操作时有多大的权限;

②指针+-整数:指针的类型决定指针向前或向后走一步有多大。

指针类型的意义:指针的不同类型,其实提供了不同的视角去观察和访问内存。

图解:

4.下面关于指针运算说法正确的是:( )

A.整形指针+1,向后偏移一个字节

B.指针-指针得到是指针和指针之间的字节个数

C.整形指针解引用操作访问4个字节

D.指针不能比较大小

解析:

答案是:C

A.整形指针+1,向后偏移4个字节

B.指针减指针,指针必须指向同一块内存空间,得到是两个指针之间的元素个数

D.指针能比较大小

知识点:

1.指针的类型:

        指针的类型决定了,指针+-整数的步长,指针解引用操作时的权限。

2.指针的运算
①指针+-整数:指针的类型决定了指针向前或向后走一步有多大;
②指针-指针:a.前提:两个指针要指向同一块内存空间(数组)
            b.指针减指针的绝对值,得到的是两个指针之间的元素个数。
③指针的关系运算(比较指针的大小):
     标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与第一个元素之前的那个内存位置的指针进行比较。

5.在小端机器中,下面代码输出的结果是:( )

#include <stdio.h>

int main()

    int a = 0x11223344;
    char* pc = (char*)&a;
    *pc = 0;
    printf("%x\\n", a);
    return 0;

A.00223344

B.0

C.11223300

D.112233

解析:

答案是:C

 在VS2019是小端,如下内存中的表示:

二、编程题

1.写一个函数打印arr数组的内容,不使用数组下标,使用指针。

arr是一个整形一维数组。

分析:

        使用函数打印数组,需要两个参数:

                ①数组的首元素地址;②数组的元素个数。

#include<stdio.h>

void print(int* p, int sz)

	//数组元素只能逐个引用,而不能一次引用整个数组(字符串除外)
	//逐个使用数组中的每一个元素时,通常借助for循环语句
	int i = 0;
	for (i = 0; i < sz; i++)
	
		printf("%d ", *(p + i));
	
	printf("\\n");


int main()

	int arr[] =  0 ,1 ,2, 3, 4, 5 ,6, 7, 8, 9, 10 ;
	//计算数组元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	//调用函数实现
	//打印数组:①知道数组的地址②知道数组的元素个数
	print(arr, sz);

	return 0;

2.点击链接,做题

字符逆序__牛客网 (nowcoder.com)

分析:

代码1:数组的形式

#include <stdio.h>
#include<string.h>

//使用数组的方式实现
void reverse(char* str)

    //左下标从0开始
    int left = 0;
    //右下标=元素个数-1
    int right = strlen(str) - 1;
    //循环交换--条件:left<right
    while (left < right)
    
        //交换
        char tmp = *(str + left);
        *(str + left) = *(str + right);
        *(str + right) = tmp;
        //循环调整——趋于循环结束的语句
        left++;
        right--;
    

int main()

    char arr[10000] =  0 ;
    //注:scanf默认读取的时候遇到空格就结束
    //输入字符串
    gets(arr);
    //调用函数实现
    reverse(arr);
    //输出
    puts(arr);
    return 0;

代码2:指针的形式

#include <stdio.h>
#include<string.h>

//使用指针的方式实现
void reverse(char* str)

    //左边的起始地址
    char* left = str;
    //右边的地址
    char* right = str + strlen(str) - 1;

    while (left < right)//指针的关系运算
    
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    

int main()

    char arr[10000] =  0 ;
    gets(arr);
    //调用函数实现
    reverse(arr);
    //输出
    puts(arr);
    return 0;


3.用C语言在屏幕上输出菱形图案:

分析:关键在于找出行数与空格、*之间的关系。

#include<stdio.h>

int main()

	int line = 0;
	scanf("%d", &line);
	//上-line行
	int i = 0;
	for (i = 0; i < line; i++)
	
		//打印一行
		//先打印空格
		int j = 0;
		for (j = 0; j < line - 1 - i; j++)
		
			printf(" ");
		
		//再打印*
		for (j = 0; j < 2 * (i+1) - 1; j++)
		
			printf("*");
		
		printf("\\n");
	
	//下--line-1行
	for (i = 0; i < line - 1; i++)
	
		//打印一行
		//先打印空格
		int j = 0;
		for (j = 0; j <= i; j++)
		
			printf(" ");
		
		//再打印*
		for (j = 0; j < 2 * (line-1-i) - 1; j++)
		
			printf("*");
		
		printf("\\n");
	
	return 0;

 如输入6,运行结果:

 4.求出0~100000之间的所有“水仙花数”并输出。

“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1^3+5^3+3^3,则153是一个“水仙花数”。

分析:

判断一个数i是否为水仙花数

1.计算出i是几位数——n

2.计算i的十进制的n次方之和,并判断是否等于i本身

补充:水仙花数其实就是自幂数

#include<stdio.h>
#include<math.h>

int main()

	int i = 0;
	for (i = 0; i <= 100000; i++)
	
		//判断i是否为水仙花数
		//1.计算出i是几位数--n(注:使用一个中间变量tmp,防止i被改变)
		int n = 1;//一个数最小是一位
		int tmp = i;
		while (tmp > 9)
		
			tmp /= 10;
			n++;
		
		//2.计算i的十进制的n次方之和,并判断是否等于i本身
		tmp = i;
		int sum = 0;
		while (tmp)
		
			sum += (int)pow(tmp % 10, n);//pow是算次方的函数,返回类型为double
			tmp /= 10;
		
		if (sum == i)
		
			printf("%d ", i);
		
	
	return 0;

运行结果:

5.求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,

例如:2+22+222+2222+22222

/*
	分析:a=2  k=0 sum=0
		k=0*10+2=2
		k=2*10+2=22
		k=22*10+2=222
		k=222*10+2=2222
		k=2222*10+2=22222
		循环:第i项为k,则i+1项 = k*10+a;sum += k;
*/

#include<stdio.h>

int main()

	int a = 0;
	int n = 5;
	scanf("%d", &a);
	//计算
	int i = 0;
	int k = 0;
	int sum = 0;
	for (i = 0; i < n; i++)
	
		k = k * 10 + a;
		sum += k;
	
	//输出
	printf("%d\\n", sum);

	return 0;

牛客网C语言刷题(指针篇)

✅作者简介:大家好我是:嵌入式基地,是一名嵌入式工程师,希望一起努力,一起进步!
📃个人主页:嵌入式基地
🔥系列专栏:牛客网C语言刷题专栏
💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习


牛客网C语言刷题(指针篇)

习题一:获取字符串长度

描述

  • 键盘输入一个字符串,编写代码获取字符串的长度并输出,要求使用字符指针实现。

输入描述

  • 键盘输入一个字符串

输出描述

  • 输出字符串的长度

示例

输入:
helloworld
输出:
10

解析

  • 定义一个指针指向字符串开头。
  • 只要指针对应元素不是’\\n’,将指针后移,同时长度加1。

代码实现

#include <iostream>
using namespace std;

int main() 

    char str[100] =  0 ;
    cin.getline(str, sizeof(str));

    int len=0;
    char *p=str;
    //只要指针没有指向换行符位置
    while(*p!='\\0')
        //长度加1,指针p后移
        len++;
        p++;
    
    cout<<len<<endl;

    return 0;

习题二:复制部分字符串

描述

  • 键盘输入一个长度为len(1 <= len < 30)的字符串,再输入一个正整数 m(1 <= m <= len),将此字符串中从第 m 个字符开始的剩余全部字符复制成为另一个字符串,并将这个新字符串输出。要求用指针处理字符串。

输入描述

  • 键盘输入一个长度为len(1 <= len < 30)的字符串,再输入一个正整数 m(1 <= m <= len)

输出描述

  • 输出复制的新字符串

示例

输入:
helloworld
6
输出:
world

解析

题目所给的代码中,输入的字符串是一个字符数组,采用getline函数输入,这样会在输入的末尾增加一个’\\0’表示字符串的结束,如果长度小于数组长度,输入所有字符后加’\\0’,如果长度大于数组长度,截断输入的前面部分再在最后加’\\0’。

我们准备一个新串来保存复制后的字符串,因为原串大小不会超过30,因此新串的大小也不会超过30.

题目要求使用指针,我们可以用两个指针,指针p一开始指向原串的第m个位置,指针q一开始指向新串的起始位置。然后利用指针p遍历原串,到末尾的’\\0’结束,遍历过程中像指针q指向的地址复制指针p指向元素的值,然后指针同步后移。

代码实现

#include <iostream>
using namespace std;

int main() 

	char str[30] =  0 ;
	cin.getline(str, sizeof(str));
    int m;
	cin >> m;
	// write your code here......
    char copystr[30] =  0 ;
    char* p = str + m - 1; //指向字符数组第m个元素
    char* q = copystr;
    while(*p != '\\0') //直到字符串结果
        *q = *p; //复制
        p++;; //两边指针都后移
        q++;
    
    cout << copystr << endl;
	return 0;


习题三:编写函数实现两数交换(指针方式)

描述

  • 键盘输入一个长度为len(1 <= len < 30)的字符串,再输入一个正整数 m(1 <= m <= len),将此字符串中从第 m 个字符开始的剩余全部字符复制成为另一个字符串,并将这个新字符串输出。要求用指针处理字符串。

输入描述

  • 键盘输入2个整数 m 和 n

输出描述

  • 输出交换后m 和 n 的值,中间使用空格隔开

示例

输入:
2
3
输出:
3 2

代码实现

using namespace std;

// write your code here......
void swap(int *p, int *q);
void swapp(int &a, int &b);

int main() 

    int m, n;
    cin >> m;
    cin >> n;

    // write your code here......
//     swap(m,n); // 指针变量
    swapp(m,n);  //引用变量

    cout << m << " " << n << endl;

    return 0;

void swap(int *p, int *q)

    int temp = *p;
    *p = *q;
    *q = temp;

void swapp(int &a, int &b)

    int temp = a;
    a = b;
    b = temp;

习题四:利用指针遍历数组

描述

  • 键盘随机输入 6 个整数,将这些数据保存到数组中,利用指针遍历数组中的元素并打印。

输入描述

  • 键盘随机输入 6 个整数

输出描述

  • 输出数组中的所有元素,每个元素中间使用空格隔开
  • 例如:10 20 30 40 50 60

示例

输入:
10
20
30 
40
50
60

输出:
10 20 30 40 50 60

解析

  • 利用指针遍历数组, 数组名就是数组第一个元素的地址
  • 因此将地址范围知道,就可以访问每一个元素的值
  • 这里的指针4个字节(64位的话8个字节)作为一整块

代码实现

#include <iostream>
using namespace std;

int main() 

    int arr[6] =  0 ;
    int* ptr = arr;

    int len = sizeof(arr) / sizeof(int);

    for (int i = 0; i < len; i++) 
        cin >> arr[i];
    

    for (ptr ; ptr < arr + len ; ptr++)
    
        cout <<  *ptr<< " ";
    
    

    return 0;

习题五:牛牛的新数组求和

描述

  • 牛牛学习了指针相关的知识,想实现一个 int cal(int *array,int n) 的函数求出长度为 n 的数组的和。

输入描述

  • 第一行输入一个正整数 n ,表示数组的长度
  • 第二行输入 n 个正整数,表示数组中每个数字的值

输出描述

  • 实现 int cal(int *array,int n) 求出数组array的和

示例

输入:
5
2 8 1 9 5

输出:
25

代码实现

#include <iostream>
using namespace std;

int cal(int *array,int n)
    int *p = array;
    int sum=0;
     for(int i=0;i<n;i++)
       sum+=*p;
         p++;
       
   
    return sum;



int main() 
    int n=0;
    cin>>n;
    int array[n];
    for(int i=0;i<n;i++)
        cin>>array[i];
    
    cout<<cal(array,n);
   
    return 0;

习题六:牛牛的排序

描述

  • 牛牛试图给一个长度为 n 整数数组排序,即实现一个 void sort(int *array,int n)

输入描述

  • 第一行输入一个正整数 n ,表示数组长度。
  • 第二行输入 n 个正整数,表示数组中每个元素的值

输出描述

  • 输出排序后的数组

示例

输入:
5
2 9 8 1 3

输出:
1 2 3 8 9

代码实现

#include<stdio.h>
void sort (int*arr,int n)    //冒泡排序

    int i,j=0;
    for(i=0;i<n-1;i++)
    
        for(j=0;j<n-1-i;j++)
        
            if(arr[j]>arr[j+1])
            
                int tmp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=tmp;
               
        
    
    for(i=0;i<n;i++)
    
        
        printf("%d ",arr[i]);
    
    
    

int main()

    int n,i=0;
    scanf("%d",&n);
    int arr[100]=0;
    for(i=0;i<n;i++)
    
        scanf("%d",&arr[i]);
    
    sort(arr,n);
    return 0;


结束语

你想要的牛客都有,各种大厂面试真题在等你哦!快快通过下方链接注册加入刷题大军吧!
💬刷题神器,从基础到大厂面试题👉点击跳转刷题网站

以上是关于C语言刷题——指针概念的主要内容,如果未能解决你的问题,请参考以下文章

牛客网C语言刷题(指针篇)

没事抽空学——c语言指针操作基础概念

C语言指针是什么?1分钟彻底理解C语言指针的概念

C语言指针基本概念及其指针变量的定义是啥

“指针”是成熟的编程语言必须具有的概念吗?

C语言文件的概念和文件指针