第8章 善于利用指针

某不知名学校C语言作业 老师又又又又没给答案 题目不给输入输出 数据也小 算了 居然发现自己都快习惯了 这一章又是指针 对于很少用指针的我 头皮发麻

算了

直接看题吧

 

第一题

一维实型数组

编写函数计算一维实型数组前n个元素的最大值、最小值和平均值。数组、n、最大值、最小值和平均值均作为函数形参,函数无返回值;在主函数中输入数据,调用函数得到结果。(要求用指针方法实现)

分析 数组我们会了 函数封装会了 比大小也会了 主要是怎么用指针 简单一点说就是:

定义指针是int *p 其中p是一个地址 *p是地址的内容  &a表示取a的地址

同时 a[99] a作为数组名 代表数组的首地址 因此可以直接当作指针用

fun函数里面是形参 主函数里面是实参 要想通过函数fun改变主函数的实参 就要传入实参的地址

#include<stdio.h>
int n;//设成全局变量 因为求平均数时候要用到

void fun(float a[], float* max, float* min, float* avg)
{
    int i;
    *min = *max = *avg = a[0];//这一步将三个数初始化为第一个数
    for (i = 1; i < n; i++) {
        if (a[i] < *min) {//遍历如果发现有比第一个数小的
            *min = a[i];//那min就是这个数
        }
        if (a[i] > *max) {//最大值同理
            *max = a[i];
        }
        *avg += a[i];//所有数相加
    }
    *avg = *avg/ n;//这就是为什么要全局变量
}
int main()
{
	scanf("%d",&n);
    float a[99];//防止数组溢出
    float avg, min, max;//题目要求浮点数
    
    for (int i = 0; i < n; i++)
        scanf("%f", &a[i]);
    fun(a, &max, &min, &avg);//数组名也是一种特殊的指针
    printf("max:%.2f\nmin:%.2f\naveg:%.2f\n", max, min, avg);//这里被卡输出了 我习惯平均数用avg 题目是aveg 
    return 0;
}

第二题

元素之和

利用指向行的指针变量求5×3数组各行元素之和。

分析 这其实没必要用指针 这道题考的应该是通过指针移动来遍历二维数组

一维的移动方法是*(指针 + 偏移量) 那么二维就是*(*(p+行偏移量) + 列偏移量)

#include<stdio.h>

void getsum(int (*p)[3])//传入一个二维数组地址
{
    int t;
    int i,j;
    for(i=0;i<5;i++)//有5行
    {
        t = 0;
        for(j=0;j<3;j++)//有3列
        {
            t += *(*(p+i) + j);//遍历方法 指针移动
        }
        printf("row i:%d\n",t);
    }
}



int main()
{
	int arr[5][3];
	for(int i=0;i<5;i++){
		for(int j=0;j<3;j++){
			scanf("%d",&arr[i][j]);
		}
	}
	getsum(arr);

    return 0;
}

第三题

字符指针

使用字符指针编写程序,输入一个长度为n的字符串a,在字符串a的i (0<i<n)处插入字符x,输出插入后的字符串a。(n,x,i的值可自由输入)。例如:输入nw world在1处插入e输出new world。

分析:考的也是用指针遍历数组元素 因为在C里面字符串也是一个字符数组

多判断了插入位置不对的情况 不过学校作业数据都很小 应该不用判断也行

#include <stdio.h> 
#include <string.h>//函数strlen()获取字符串长度

void insert(char str[],char c,int n) {//原来字符串 插入字符 插入位置
	int i = 0;
	if((n - 1) >= strlen(str)) {//如果插入位置超出字符串长度 直接放最后面
			*(str+n-1) = c;//str本身就是首地址指针 要*才能等于地址内容
	}
	if((n - 1) >= 0 && (n-1) < strlen(str)) {//如果插入范围在字符串内
		for(i = strlen(str); i >= n; i--) {
			*(str+i) = *(str+i-1);//把每一个字符串的字符往后移一位 空出位置给插入的字符
		}
		*(str+n-1) = c;//插入
	}
}
int main() {
	char s[100],c;
	gets(s);//用scanf万能一点 这里我试试gets
	int n,i;
	scanf("%d %c",&n,&c);
	insert(s,c,n);
	for(i = 0; i < strlen(s); i++) {
		printf("%c",s[i]);//本来用puts 发现卡输出了
	}
	return 0;
}

第四题

实现字符比较函数

编写一个函数,实现两个字符串的比较。即自己写一个strcmp函数,函数原型为 strcmp(char *p1,char *p2) 设p1指向字符串s1,p2指向字符串s2.要求当s1=s2时,返回值为0;若s1≠s2,返回他们二者第一个不同字符的ASCII码差值;如果s1>s2,则输出正值;若s1

分析:题目都打不全 要命 考的还是用指针遍历数组 指针可以用也可以不用 但是为了练习 还是用吧

#include<stdio.h>

int cmp(char*p1,char*p2){
	int i=0;
	while(*(p1+i)==*(p2+i))//如果每个字符相等相等
	if(*(p1+i++)=='\0')return 0;//就会在字符1结束的时候返回0
	return (*(p1+i)-*(p2+i));//ASCII码差值
	

}
int main()
{
	char str1[99],str2[99],*p1,*p2;
	scanf("%s%s",str1,str2);
	p1=&str1[0];//分别取首元素地址 其实多余了 直接用数组名就行 不过这样好像更容易理解
	p2=&str2[0];
	int k=cmp(p1,p2);
    printf("%d\n",k); 

    return 0;
}

这样直接用数组名也行

#include<stdio.h>

int cmp(char*p1,char*p2){
	int i=0;
	while(*(p1+i)==*(p2+i))
	if(*(p1+i++)=='\0')return 0;
	return (*(p1+i)-*(p2+i));
	

}
int main()
{
	char str1[99],str2[99],*p1,*p2;
	scanf("%s%s",str1,str2);
	
	
	int k=cmp(str1,str2);//直接用也行 
    printf("%d\n",k); 

    return 0;
}

第五题

合并字典

将两个按字典顺序排序的名字登记表合并,删除重复出现的名字使得每个名字在登记表中只出现一次,输出名字登记表内容。 两个登记表分别为 S1={“jixiang”,”lihua”,”lihua”,”lijian”,”wanger”,”zhanglin”} S2={“chenming”,”lihua”,”lijian”,”liutian”,”zhouqi”,”zhouqi”}

分析:考的是字符串查重 排序 我的做法是新开一个数组s3 这是我第一时间想到的做法 不过做着做着发现有点麻烦 应该有更简单的做法

#include<stdio.h>

#include<string.h>//用到函数strcpy复制 strlen测量长度

int choose(char (*s1)[10],char (*s2)[10],char (*s3)[10])//分别传入三个数组 第三个用来记录

{

   int n=0,i=0,j=0;

   char t[10];//临时数组

   while(s1[i][0] && s2[j][0]) {//如果字符串还存在

         if(strcmp(s1[i],s2[j])<0) strcpy(t,s1[i++]);//字符串1小 则复制字符串1 

       else strcpy(t,s2[j++]);

             while(strcmp(s1[i],t)==0) i++;//如果相等 i++ 等价于忽略相同字符串

             while(strcmp(s2[j],t)==0) j++;

             strcpy(s3[n++],t); //把t中临时存的字符串复制s3  

   }

   while(s1[i][0])//开始漫长的 算出s3的长度

     if(strcmp(s1[i],s3[n-1])) strcpy(s3[n++],s1[i++]);

     else i++;

   while(s2[j][0])

     if(strcmp(s2[j],s3[n-1])) strcpy(s3[n++],s2[j++]);

     else j++;

   return n;//感觉我这样做太麻烦了 应该有更好的方法

}

int main()

{

   char s1[10][10]={"jixiang","lihua","lihua","lijian","wanger","zhanglin"};

   char s2[10][10]={"chenming","lihua","lijian","liutian","zhouqi","zhouqi"};

   char s3[20][10]={0};

   int k,n;                       

   n=choose(s1,s2,s3);

   for(k=0;k<n;k++) printf("%s ",s3[k]);

   return 0;

}

第六题

定义两个整型变量,再定义两个指针变量指向整型变量,通过指针变量访问整型变量

分析:大水题 要指针指向用取地址符就好 p=&a;

# include <stdio.h>

int main()
{
	int a,b;
	scanf("%d%d",&a,&b);
	int *p1=&a; int *p2=&b;
	
	printf("*pointer_1=%d,*pointer_2=%d",*p1,*p2);//小心卡输出

	return 0;
}

第七题

用指针方法对10个整数按由大到小顺序排序

分析:排序应该已经学过了 选择 冒泡这两种应该比较容易理解 其实用快排应该更好 不过应该刚学指针理解起来有点困难(其实是我不会用指针写) 所有我们就用选择排序吧

#include<stdio.h>

void sort(int x[],int n)//排序函数 
{
  int i,j,k,t; 
  for(i=0;i<9;i++)
  {
    k=i;//把i的值赋给k 
    for(j=1+i;j<10;j++)
    {
      if(x[j]>x[k])//如果前一个数大 
      {
        k=j;
      } 
    } 
    t=x[k]; //实现交换 
    x[k]=x[i];
    x[i]=t;
  }
}



int main() 
{
  
  int i,*p,a[10];//定义整型变量、指针变量、数组 
  p=a;//给a赋值  数组名也是指针因此直接相等 
  
  for(i=0;i<10;i++)
  {
    scanf("%d",p++);
  } 
  
  sort(a,10);//调用sort排序 
  
  for(p=a,i=0;i<10;i++)//输出排序后的数 
  {
    printf("%d ",*p);
    p++;
  }
  printf("\n");//换行 
  return 0;
}

第八题

根据序号输出学生成绩(指针函数实现)

有3个学生,每个学生有4门课程的成绩。要求用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现 学号分别为012 成绩则为{60,70,80,90},{56,89,67,88},{34,78,90,66}

分析:如果你做到这了 你会发现 其实很多题根本不用指针 那指针的意义是什么?

指针 可以让我们更高效去访问某些数据 特别是跟多维数组在一起的时候 如果是一个二维数组 正常要用两个循环 三维数组三个 但是如果有指针 就可以快速随意的指向数组的某一个元素

这道题也是考的指针去遍历数组 如果不用指针 那也可以用if直接写

#include<stdio.h>
float* search(float(*p)[4], int n)
{
	float* ptemp;
	ptemp = *(p + n);
	return (ptemp);//返回你要访问的第几行
}
int main()
{
	float score[][4] = { {60,70,80,90} ,{56,89,67,88} ,{34,78,90,66} };
	float* p;
	int j;
	scanf("%d", &j);
	p = search(score, j);
	for (int i = 0; i < 4; i++)//每行四个数
	{
		printf("%.2f ", *(p + i));
	}
	printf("\n");
    return 0;
}

第九题

按首字母升序输出国家名称

把输入的5个国家的名字按字母的升序输出 China Japan Korea American England

分析:用strcmp函数就能比较字符串大小了 然后再依次交换 就完成了选择排序 思路不难 主要是要求用指针实现

#include <stdio.h>
#include <string.h>
void fun(char *a[],int lenth)
{
	char *t;
	int i,j;
	for(i=0;i<lenth-1;i++)
	{
		for(j=0;j<lenth-1-i;j++)
		{
			if(strcmp(*(a+j),*(a+j+1))>0)//strcmp返回的是int类型
			{
				t = *(a+j);//等价于交换函数
				*(a+j) = *(a+j+1);
				*(a+j+1) = t;
			}
		}
	}
}
int main()
{
	char *a[5]={ "China","Japan","Korea","American","England" };
	int b=5;
	fun(a,b);
	int i;
	for(i=0;i<b;i++)
	{
		printf("%s ",a[i]);
	}
	return 0;
}

第十题

将数字按序插入数组

有10-90这9个整数,已按升序存放于长度为10的一维数组中。要求将一整数35插入其中,并保持数组元素仍然有序。

相关知识

通过定义动态数组来存储数值并计算

分析:这道题好像不用动态数组做不出来 必须要用malloc去定义一个动态数组

在C++里面就是vector 因为很少写这个malloc定义的动态数组 所有我也不是很会 幸好班上有大佬教了我用法 勉勉强强能过 但是不知道数据大了行不行

#include <stdio.h>


int main() {
	int i, temp;
	int* s;

	//分配动态空间
	s = (int*)malloc(sizeof(int[10]));//s就是我们定义的int类型的动态数组了


	//初始化10-90
	for (i = 0; i < 9; i++) {
		s[i] = (i + 1) * 10;
	}

	//排序
	s[9] = 35;
	for (i = 9; i >= 0; i--) {
		if (s[i] < s[i-1]) {//老一套的选择排序
			temp = s[i];
			s[i] = s[i - 1];
			s[i - 1] = temp;
		}
	}
	for (i = 0; i < 10; i++) {
		printf("%d ", s[i]);
	}

	//释放内存
	free(s);//这个是个习惯 虽然做题不释放也可能对 但以后去工作一定会给打死
	return 0;
}

okk 作业做完了 还有可爱的期中考试和期末考等着我呢

真是快乐的大学牲啊

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年12月14日
下一篇 2023年12月14日

相关推荐