20201022-成信大-C语言程序设计-20201学期《C语言程序设计B》C-trainingExercises15

本文提供多个C语言程序设计实例,包括求矩阵最大值及其位置、显示指定列元素、计算特定和等,通过实际操作加深对二维数组的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

20201022-成信大-C语言程序设计-20201学期《C语言程序设计B》C-trainingExercises15

P216

在这里插入图片描述

/*
编写一程序P216.C实现以下功能
  求任意的一个m×m矩阵的最大数及其所在的行列数,m(2<=m<=20)及矩阵元素从键盘输入(只考虑int型)。
    编程可用素材:
        printf("Please input m: ");
        printf("\nPlease input array:\n");
        printf("\nmax=…,i=…,j=…\n");
  程序的运行效果应类似地如图1所示,图1中的红色部分是从键盘输入的内容。

Please input m: 5
Please input array:
1    45   67  235   464
35   6    89  32342 8
347  9346 47  95    746
46   785  436 19434 634
3235 567  24  8465  25

max=32342,i=1,j=3
图1 程序运行效果示例


思路:
    1. 最简单的搜索方式:比较得结果
        记录最大值
        记录行号
        记录列号
    2. 注意:
        矩阵到了C语言下,一般用二维数组来表示,但行和列标的索引是从0开始的,因数二进制计数,0不能浪费
        而人在数数时,是从1开始有计数的。
*/

#include <stdio.h>

#define N 20   // m(2<=m<=20) 按题目要求,给定常量

int main(void)
{
    int i,j;
    int arr[N][N];  // 使用二维数组
    int m;
    int max, iMark, jMark;  // 搜索过程中进行标记和记录

    printf("Please input m: ");
    scanf("%d", &m);

    // 输入矩阵
    printf("\nPlease input array:\n");
    for ( i = 0; i < m; i++)
    {
        for ( j = 0; j < m; j++)
        {
            scanf("%d", &arr[i][j]);
        }
    }
    // 搜索矩阵,找最大,并标记。默认0行0列最大
    max = arr[0][0];    
    iMark = jMark = 0;
    for ( i = 0; i < m; i++)
    {
        for ( j = 0; j < m; j++)
        {
            if (max < arr[i][j] )       // 如果有更大的,则更新标记和记录
            {
                max = arr[i][j];
                iMark = i;
                jMark = j;
            }
        }
    }
    
    // 输出
    printf("\nmax=%d,i=%d,j=%d\n", max, iMark, jMark);

    return 0;
}

P262

在这里插入图片描述

/*
  编写一程序P262.C实现以下功能
  先从键盘读入整数m和n(约定(2<=m<=20、2<=n<=20)),再从键盘读入m行(每行n个,即一个m×n矩阵)整数,
    然后从键盘读入一个列序号,按示例格式显示该列的内容。
    编程可用素材:
        printf("请输入 m 和 n: ");
        printf("请输入 %d 行, 每行 %d 列整数:\n"…);
        printf("请输入要显示列的列号: ");
        printf("\n该列的内容为: ");
  程序的运行效果应类似地如图1所示,图1中的红色部分是从键盘输入的内容。

请输入 m 和 n: 5 6
请输入 5 行, 每行 6 列整数:
31   42   36  74  2358 88
1447 32   57  37  43   47
97   51   257 7   445  459
33   65   44  3   425  43
68   3425 82  789 123  2134
请输入要显示列的列号: 2


该列的内容为: 36 57 257 44 82
图1 程序运行效果示例
*/

#include <stdio.h>

#define N 20

int main(void)
{
    int i, j;
    int arr[N][N];
    int m, n;       // m行,n列
    int col;        // 操作列号

    printf("请输入 m 和 n: ");
    scanf("%d%d", &m, &n);
    printf("请输入 %d 行, 每行 %d 列整数:\n", m, n);
    for ( i = 0; i < m; i++)
    {
        for ( j = 0; j < n; j++)
        {
            scanf("%d", &arr[i][j]);    // 对每一个元素取地址进行初始化
        }
        
    }
    
    printf("请输入要显示列的列号: ");
    scanf("%d", &col);

    printf("\n该列的内容为: ");
    for ( i = 0; i < m; i++)           // 列固定,按行遍历
    {
        printf("%d ", arr[i][col]);
    }
    
    return 0;
}

P748

在这里插入图片描述

/*
  编写一程序P748.C实现以下功能
  从键盘上输入矩阵的阶数n(n<=14), 矩阵中元素的值等于其位置的行数和列数之和的n倍(行列的值从0开始计数),如n=3时,矩阵为
        0   3   6
        3   6   9
        6   9   12
  先输出该矩阵(显示时每个数宽度为4、右对齐),然后计算输出sum1和sum2的值:
        sum1为矩阵中所有不靠边元素之和、
        sum2为矩阵的一条对角线元素之和。
    编程可用素材:
        printf("Enter n: ");
        printf("\nsum1=…\nsum2=…\n");
  程序的运行效果应类似地如图1所示,图1中的3是从键盘输入的内容。

Enter n: 3
   0   3   6
   3   6   9
   6   9  12

sum1=6
sum2=18
图1 程序运行效果示例
*/

#include <stdio.h>

#define N 14

int main(void)
{
    int n;
    int i, j;
    int arr[N][N];
    int sum1 = 0, sum2 = 0;

    printf("Enter n: ");
    scanf("%d", &n);
    
    // 矩阵元素值生成
    for ( i = 0; i < n; i++)
    {
        for ( j = 0; j < n; j++)
        {
            arr[i][j] = (i + j) * n; // 元素的值等于其位置的行数和列数之和的n倍,这是最朴素的业务算法实现
        }
    }
    
    // 先输出该矩阵(显示时每个数宽度为4、右对齐)
    for ( i = 0; i < n; i++)
    {
        for ( j = 0; j < n; j++)
        {
            printf("%4d", arr[i][j]);           // 注意值的宽度
        }
        printf("\n");                           // 二维,一定要有换行控制
    }    

    /* 
        计算输出sum1和sum2的值
            sum1为矩阵中所有不靠边元素之和、
            sum2为矩阵的一条对角线元素之和。
     */
    for ( i = 0; i < n; i++)
    {
        for ( j = 0; j < n; j++)
        {
            /* 
                对于不靠边元素的判断,有很多种逻辑判断方法
                比如:
                    1. 首行首列,尾行尾列,一定是靠边的,则取反即可
                    2. 也可以使用i>0 && j>0 && i<n-1 && j<n-1
                    3. 表达式如果太长,不建议这样写,但如果有规律,还是易读,可以这样写
                        要特别注意运算符的优先级和结合性
             */
            if( i!=0 && j!=0 && i!=n-1 && j!= n-1)  // 不靠边元素
            {
                sum1 += arr[i][j];
            }
            if(i==j)    // 对角线元素
            {
                sum2 += arr[i][j];
            }
        }
    }
    printf("\nsum1=%d\nsum2=%d\n", sum1, sum2);

    return 0;
}

P313

在这里插入图片描述

/*
  编写一程序P313.C实现以下功能
  求任意的一个m×n矩阵的鞍点——鞍点是指该位置上的元素在该行上为最大、在该列上为最小,矩阵中可能没有鞍点,但最多只有一个鞍点。
    m、n(2<=m<=20、2<=n<=20)及矩阵元素从键盘输入(只考虑int型和每行、每列中没有并列最大/最小的情况)。
  编程可用素材:
        printf("Please input m and n:");
        printf("Please input a juZhen(... hang, ... lie):\n...);
        printf("\nmei you an dian.\n");
        printf("\nyou an dian, wei: juZhen[...][...]=...\n...);

  程序的运行效果应类似地如图1和图2所示,图1中的5 6和
31 42 36 74 2358 88
32 57 37 43 47 1447
97 51 257 7 445 459
33 65 44 3 425 43
68 3425 82 789 123 2134
  及图2中的5 6和
31 42 1136 74 2358 88
32 57 4137 43 47 1447
97 51 1257 7 445 459
33 65 744 3 425 43
68 3425 2182 789 123 2134

思路:
    1. 可以直接搜行上最大,然后测这个最大是不是列上最小?
        也就是说,默认认为这个最大,就是列上最小,然后再测试它是不是最小
            成功了,则就是鞍点,程序完成,给结果;
            如果没成功,则没有鞍点,给结果;
    2. 会有一次行上的列扫描,找最大值,然后按该值所在的列,进行再一次的行扫描,判断最小
        整体上扫描行
            再行上扫描列,找最大【一定可以找到】
            再最大列上,扫描行,判断最小【不一定可以判断成功】
                有鞍
                无鞍

另一种思路:
    1. 两个矩阵并行
        a[][]为原始数据矩阵,b[][]为标记阵,初始为为全0
    2. 如果某元素a[i][j]在行上最大,则b[i][j]++,即标记为1
    3. 如果某元素a[i][j]在列上最小,则b[i][j]++,b[i][j]++即标记为2
    4. 最后,扫描b矩阵,如果有b[i][j] == 3 则,a[i][j] 即为对应的鞍点;否则,不存在鞍点
    这种思路,比较费空间

还有一种思路:
    1. 直接创建相应的数据结构,把行列及值都封装到该结构中
    2. 然后再判断,直接返回鞍点或是null
*/

#include <stdio.h>

#define N 20
#define M 20

int main(void)
{
    int i, j, k;
    int n, m;
    int arr[N][M];
    int flag = 0;
    int max;
    int jMark;

    printf("Please input m and n:");
    scanf("%d %d", &n, &m);
    printf("Please input a juZhen(%d hang, %d lie):\n", n, m);
    for(i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            scanf("%d", &arr[i][j]);
        }
    }

    // 寻找鞍点
    // 先找行上最大,再测是不是列上最小
    for(i = 0; i < n; i++)
    {
        // 不妨先取第i行第1列为最大
        max = arr[i][0];
        jMark = 0;          // 列号记录
        // 测试之后还有没有更大的值,如果有,则更新并记录
        for (j = 1; j < m; j++)
        {
            if (max < arr[i][j])
            {
                max = arr[i][j];
                jMark = j;  // 更新列号
            }            
        }

        // 得到行上最大之后,测试是否列上最小
        // min = arr[i][jMark];    // 就当它是最小的
        flag = 1;               // 这个最大的行值,就当它是鞍点了
        for (k = 0; k < n; k++) // 测试是否满足条件
        {
            if (arr[k][jMark] < arr[i][jMark])
            {
                flag = 0;   // 这个最大的行值,仍然不是鞍点
                break;      // 一旦不是最小的,本层循环就已经不用再测别的行了
            }
        }

        // 只有一个鞍点,一旦找到,就可以退出外层循环了
        if (flag)
        {
            printf("\nyou an dian, wei: juZhen[%d][%d]=%d\n",i,jMark,max);
            break;
        }
    }

    // 未找到鞍点
    if(!flag)
    {
        printf("\nmei you an dian.\n");
    }

    return 0;
}

P412

在这里插入图片描述

/*
  编写一程序P412.C实现以下功能
  ①程序运行时先显示Please input numbers:,再从键盘上读入一组整数(只考虑int型),数与数之间只使用空格或回车作分隔。
    数可正可负,最多10000个,但若读入的数为-222时,则表示输入结束且-222不算在该组数内。
  ②对这一组数按从小到大的顺序进行排序。
  ③将排序后的这一组数输出到屏幕上,输出格式为每行6个数,数与数之间使用逗号(,)分隔,两个逗号之间的宽度(不算逗号)为6且使用左对齐格式。注意,行尾没有逗号。
  编程可用素材:
        printf("Please input numbers: ");
        printf("\nOutput:\n");
  程序的运行效果应类似地如图1所示,其中的红色部分是从键盘输入的内容。

Please input numbers: 100 120 89 72 -19 200 500 210 235 6 24 1234 78 234 -234
        -2342 346 23524 7823 -3411 23423 -222

Output:
-3411 ,-2342 ,-234  ,-19   ,6     ,24
72    ,78    ,89    ,100   ,120   ,200
210   ,234   ,235   ,346   ,500   ,1234
7823  ,23423 ,23524
图1 程序运行效果示例
*/

#include <stdio.h>
#define N 10000

void printArray(int arr[], int n);
void sortArray(int arr[], int n);
void swap(int *a, int *b);

int main(void)
{
    int count = 0;
    int i = 0;
    int dataArr[N];

    // 输入
    printf("Please input numbers: ");
    while (1)
    {
        scanf("%d", &dataArr[i]);
        // 但若读入的数为-222时,则表示输入结束且-222不算在该组数内。
        if (dataArr[i] == -222)
        {
            break;
        }
        i++;    // 计数器一定要读入有效时,才计数
    }
    count = i;  // 这一行,可以不要,直接使用i的结果也是可以的

    // 原样输出【调试用,调试完成,记得关闭这个插旗】
    // printArray(dataArr, count);

    // 排序
    sortArray(dataArr, count);
    // 输出
    printArray(dataArr, count);

    return 0;
}


/* 
    输出功能函数
 */
void printArray(int arr[], int n)
{
    int i;
    // 输出格式为每行6个数,数与数之间使用逗号(,)分隔,两个逗号之间的宽度(不算逗号)为6且使用左对齐格式。注意,行尾没有逗号。
    printf("\nOutput:\n");

    // 前n-1个数的输出
    for (i = 1; i <= n - 1; i++)
    {
        printf("%-6d", arr[i - 1]);

        if (i % 6 == 0) // 第6列,输出回车
        {
            printf("\n");
        }
        else // 非第6列,输出逗号
        {
            printf(",");
        }
    }
    // 最后一个数,即第n个数的输出
    printf("%-6d\n", arr[n - 1]);   
}


/* 
    数组排序
        arr 为数组名
        n 为数据量
        自然为升序,即从小到大,大的往上“冒泡”了,也就是大数往后放
            泡是气泡,大气泡在小气泡上面
            自然就是人长大的顺序,从小到大到老
 */
void sortArray(int arr[], int n)
{
    int i, j;
    // 冒泡排序
    for (i = 0; i < n - 1; i++)             // 冒泡时,外层只对应趟数,N个数冒泡,需要N-1趟,因为最后一个自然有序了
    {
        for (j = 0; j < n - i - 1; j++)     // 冒泡时,内层只对应还需要参与排序的数据个数 
        {
            if (arr[j] > arr[j + 1])        // 前面大于后面,则需要交换,把大的往后面放    
            {
                swap(&arr[j], &arr[j + 1]); // 调用交换函数,注意,这里一定是传地址,才可以完成交换
            }
        }
    }
}

/* 
    交换数据
    1. 传进来的是变量的地址
    2. 但交换的是变量的值
    3. 要搞明白形参和实参,本质上是内存区的控制:
        调用时,函数是使用栈内存
        调用时,实参是堆内存
        如果使用传值方式,则无法改变实参
        只有使用传址方式,对实参内存值的改变,才会有效保留下来,才可以完成值的交换
 */
void swap(int *a, int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值