【C语言】转圈报数问题(三种方法--指针,数组)

题目:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

方法一:

cpp 复制代码
#include <stdio.h>
#define N 10

int main()
{
    int a[N];    // 用数组保存参与报数的人员编号
    int i, j, m, out, count;

    // 初始化编号,从1开始连续编号
    for (i = 0; i < N; i++) {
        a[i] = i + 1;
    }

    i = 0;    // i表示当前参与报数的人员在数组中的下标
    m = 3;    // 每次报数的个数
    out = 0;    // 记录已经退出报数的人数
    count = 0;    // 记录当前已经报数的次数

    // 当还有人参与报数时循环
    while (out < N) {
        // 如果这个人还没退出
        if (a[i] != 0) {
            count++;    // 增加报数次数
            // 如果报数次数达到了m
            if (count == m) {
                printf("%d ", a[i]);    // 输出该人员编号
                a[i] = 0;    // 标记该人员已经退出
                out++;    // 增加退出人数
                count = 0;    // 将报数次数清零
            }
        }
        i++;    // 指向下一个人员
        // 如果已经扫描完一圈,则重新开始
        if (i == N) {
            i = 0;
        }
    }

    return 0;
}

程序中,首先定义了一个长度为10的数组,用于保存参与报数的人员编号。然后初始化编号,从1开始连续编号。接着设定了3个变量:i表示当前参与报数的人员在数组中的下标,m表示每次报数的个数,out表示已经退出报数的人数,count表示当前已经报数的次数。

接下来,使用while循环来模拟报数的过程。首先判断当前参与报数的人员是否已经退出,如果还没退出,则增加报数次数count。如果报数次数达到了m,则输出该人员编号,标记该人员已经退出(将其编号置为0),增加退出人数out,并将报数次数count清零。接着将下标i指向下一个人员,如果已经扫描完一圈,则将下标重新指向第一个人员。最终,当所有人都退出报数时,程序结束。

方法二 (万能):

c 复制代码
#include <stdio.h>

int main()
{
    int n, m;
    printf("请输入参与游戏的人数:");
    scanf("%d", &n);
    printf("请输入报数的上限:");
    scanf("%d", &m);
    int a[n];
    for(int i = 0; i < n; i++)
    {
        a[i] = i + 1;
    }
    int k = 0;
    while(n > 0)
    {
        k += m - 1;
        if(k >= n)
        {
            k %= n;
        }
        printf("%d ", a[k]);
        for(int i = k; i < n - 1; i++)
        {
            a[i] = a[i + 1];
        }
        n--;
    }
    return 0;
}

运行该程序,按照提示输入参与游戏的人数和报数的上限,程序就会自动进行转圈报数,并输出出局人员的编号。

方法三(指针):

以下是C语言指针处理的代码实现:

c 复制代码
#include<stdio.h>
#include<stdlib.h>

int main()
{
    int n, k = 0, m = 3;
    printf("请输入参与游戏的人数:");
    scanf("%d", &n);
    int *a = (int*)malloc(n*sizeof(int)); // 动态分配内存空间
    for(int i = 0; i < n; i++)
    {
        *(a + i) = i + 1; // 初始化,编号从1开始
    }
    while(n > 1)
    {
        k = (k + m - 1) % n;
        for(int i = k + 1; i < n; i++)
        {
            *(a + i - 1) = *(a + i);
        }
        n--;
    }
    printf("最后留下的是编号为%d的人\n", *a);
    free(a); // 释放内存空间
    return 0;
}

首先使用动态分配内存空间,然后初始化参与者编号,随后通过指针实现转圈报数,最后输出留下的人员编号,并释放内存空间。

相关推荐
code_pgf17 小时前
C/C++ 中 `typedef` 关键字详解
c语言·c++
小龙报20 小时前
【优选算法】1. 水果成蓝 2.找到字符串中所有字母的异位词
java·c语言·数据结构·数据库·c++·redis·算法
小肝一下21 小时前
7. 库制作与原理
linux·c语言·操作系统·bash·shell·动静态库
春生野草1 天前
C基础--八大排序(个人笔记)
c语言·笔记·排序算法
IT方大同1 天前
C语言分支与循环语句
c语言·开发语言·算法
呜喵王阿尔萨斯1 天前
C/C++ const -- 多义混乱
c语言·开发语言·c++
人邮异步社区2 天前
怎么把C语言学到精通?
c语言·开发语言
xiaobobo33302 天前
C语言中宏定义宏名和宏值之间的关系
c语言·宏定义·语义型
a4493153622 天前
MacBook USB-C不充电故障诊断:从PD握手到主板供电链路
c语言·开发语言·macos·电脑
a4493153622 天前
iPhone 充电故障的全链路诊断——从 Lightning/USB-C 接口到 Tristar 充电 IC
c语言·macos·ios·电脑·硬件架构·iphone