【C零基础详解】求一批整数中出现最多的个位数字 (20分)【一维数组的函数指针调用】

给定一批整数,分析每个整数的每一位数字,求出现次数最多的个位数字。例如给定3个整数1234、2345、3456,其中出现最多次数的数字是3和4,均出现了3次。

输入格式:

输入在第1行中给出正整数N(≤1000),在第二行中给出N个不超过整型范围的非负整数,数字间以空格分隔。

输出格式:

在一行中按格式“M: n1 n2 …”输出,其中M是最大次数,n1、n2、……为出现次数最多的个位数字,按从小到大的顺序排列。数字间以空格分隔,但末尾不得有多余空格。

输入样例:

3
1234 2345 3456

输出样例:

3: 3 4

通关代码:

#include <stdio.h>

#define MAXS 1000
void Cutnum(int x, int *count, int N) //拆解并统计一个数
{
    //while不能判断0会直接跳过
    do
    {
        count[x % 10]++;
        x /= 10;
    } while (x);
}

int findmax(int x[], int N) //找到数组的最大值
{
    int max = *x;

    for (int i = 0; i < N; i++)
        if (x[i] > max)
            max = x[i];

    return max;
}

void Putnum(int count[], int N, int max) //按照规定输出数组
{
    printf("%d:", max); //输出出现最多的次数
    for (int i = 0; i < N; i++)
        if (count[i] == max)
            printf(" %d", i); //输出出现最多次的数字
}

int main()
{

    int x[MAXS], N; //定义数组和整数个数
    scanf("%d", &N);

    for (int i = 0; i < N; i++)
        scanf("%d", &x[i]); //读取整数

    int count[10] = {0}; //计数数组分别代表0-9出现的次数

    int i = 0;
    for (i = 0; i < N; i++) //分解所有的数
        Cutnum(*(x + i), count, N);
    int max = findmax(count, 10);
    Putnum(count, 10, max);

    return 0;
}

零基础解析:

3.0 思路分析

整个程序的编写思路还是比较清晰的,需要完成以下步骤:

  1. 必要的数据的输入
  2. 将一个数拆分,并且统计每个数字出现的频率
  3. 找到出现最多的次数
  4. 找到并且输出出现次数最多的数

一些在前边提到过的内容,在此就不在赘述。其实核心部分的循环和选择语句也曾有过说明,此处重点谈谈数组的指针用法。在定义好变量和输入之后,函数变成了下边的样子:

#include <stdio.h>
#define MAXS 1000
int main()
{
    int x[MAXS], N; //定义数组和整数个数
    scanf("%d", &N);
    for (int i = 0; i < N; i++)  //可以在循环内部定义i
        scanf("%d", &x[i]); //读取整数
    int count[10] = {0}; //计数数组分别代表0-9出现的次数

    return 0;
}
3.1 数组名和首地址

通过数组的学习,我们需要至少知道两个东西,这是接下来理解的关键(对于int x[10]

  1. &表示对值取地址,*表示取地址对应的值;
  2. x&x[0]都表示数组x[10]的首地址;
  3. x表示首地址的时候,x+i不在是数学意义上的,而是x移动i个位置后的地址

通过一段程序,可以很好的理解这些东西:

#include <stdio.h>
int main()
{
    int x[5] = {2,8,6,5,7}; 
    printf("&x[0]:%d x:%d\n&x[1]:%d x+1:%d", &x[0], x, &x[1], x+1);
    return 0;
}

程序的运行结果为

&x[0]:6618624 x:6618624
&x[1]:6618628 x+1:6618628

不难看出:

  • &x[0]x对应的是同一个值
  • x+1也不再是数学意义上的x+1【如果是的话x+1 = 6618624+1 = 6618625与实际输出不符合】
  • 而且x+1的值与&x[1]的值相同,也就是x【首地址】,移动1位后的地址

在接受了上述结论之后,可以较好的理解接下来的程序。

3.2 参数的传递

个人理解的数组作为参数传入函数,实际上是将地址传入了子函数。因此在子函数中对数组做出的改动,在返回主函数后依然存在。
这和一般意义上的子函数是形式参数的效果是不一样的,反而和指针的效果是相同的。

所以传递数组实际上是传递数组的首地址(字符串同样适用),换句话说,数组的传递实际上是地址的传递。因此以下可以有以下形式:

  1. 子函数接收:指针

    • 数组类型 *数组名void Cutnum(int x, int *count, int N) 。其中需要传入数组count
    • 数组类型 数组名[]void Putnum(int count[], int N, int max)。同样需要传入数组count
  2. 传入子函数:首地址

    • 数组名表示的首地址Cutnum(*(x + i), count, N);。其中*(x+i)是值,count是数组count的首地址。
    • 直接表示的首地址:上一例子可以改为,Cutnum(*(x + i), &count[0], N);不过这个操作过于诡异,如果自己这样写会显得自己很不正常。
void Cutnum(int x, int *count, int N) //*count传递
{
    //while不能判断0会直接跳过
    do
    {
        count[x % 10]++;
        x /= 10;
    } while (x);
}

void Putnum(int count[], int N, int max) //count[]传递
{
    printf("%d:", max); 
    for (int i = 0; i < N; i++)
        if (count[i] == max)
            printf(" %d", i);
}
3.3 数组元素的调用

使用数组的根本目的,还是对数组里的元素进行运算和处理,有两种方法可以调用数组里的元素,对其进行处理:

  1. 常用调用方法x[i]:这是大家最常用且习惯的用法。
  2. 指针方法调用*(x+i):在我们知道x+i表示的数组x的第i个元素的地址之后,取该地址对应的值只需要加上*即可。

需要注意的是必须要加括号,因为*运算符的优先级更高,也就是说:

  • x[i] = *(x+i)
  • x[0] + i = *x + i

在知道这些以后,就能很好的理解下边这段代码:


void Cutnum(int x, int *count, int N) 
{
    do
    {
        count[x % 10]++;  //x[i]表示
//也可以写:*(count+x%10)++;
        x /= 10;
    } while (x);
}

int main()
{
	    int x[MAXS], N; 
    scanf("%d", &N);

    for (int i = 0; i < N; i++)
        scanf("%d", &x[i]); 

    int count[10] = {0}; 

    int i = 0;
    for (i = 0; i < N; i++) 
        Cutnum(*(x + i), count, N);  //*(x+i)表示
 //也可以写Cutnum(x[i], count, N);
	
	return 0;
}
3.4 总结

总结起来就一句话:

  1. 子函数接收的是指针变量,可选择以下两种方法【即保证是指针变量】
    • void test(int *x)
    • void test(int x[])
  2. 传递进入子函数的是地址,可选择以下两种方法【x本身是地址,&是取值对应的地址】
    • test(x);
    • test(&x[0]);
  3. 调用参与运算的是数组的元素(值):可选择以下两种方法【*表示取地址对应的值】
    • x[i]
    • *(x+i) 【注意优先级】
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值