• C语言刷题练习(Day2)


    ✅作者简介:大家好我是:侠客er,是一名普通电子信息工程专业的大学学生,希望一起努力,一起进步!

    📃个人主页侠客er

    🔥系列专栏:C语言刷题练习
    🏷️非常欢迎大家在评论区留言交流,互相学习!

    前言

    (1)今天给大家分享两个非常有意思的题目,通过较长时间的研究,我觉得个人理解得算比较透彻了,与大家分享一下。

    (2)第一道题主要考查浮点数的运算,第二道题主要考查ascii码的巧用,以及字符串数组和整型数组的基础知识,虽然基础,但很是重要。

    (3)如果大家有不同的解法,欢迎在评论区中交流。

    在这里插入图片描述

    第一题

    求一串式子的值。上面题目有误,正确题目应该是1-1/4+1/7-1/10……

    通过观察式子很容易发现规律,分母每次加3,第一个数n=0,极性取决于(-1)的n次方,于是我们调用a的b次方函数pow(a,b),也不忘记包含它的math.h头文件,问题可以迎刃而解。

    #define _CRT_SECURE_NO_WARNINGS 1
    
    //1-1/4+1/7+1/10。。。
    #include 
    #include 
    int main()
    {
    	int n = 0;
    	float sum = 0.0f;
    	float a = 0.0f;
    	printf("请输入n=\n",n);
    	scanf("%d",&n);
    	for (int i = 0; i <= n; i++)
    	{
    		a = (float)(1.0f / (float)(1 + 3 * i));
    		sum = pow(-1,i)* a + sum;
    	}
    	printf("求和的结果是%f",sum);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    > 易错点:-1的n次方千万不能写成:(-1)n,在c语言中是异或操作的意思。

    本道题还有其他很多方法,下面再列举几种方法。

    方法二:

    # include 
    int main(void)
    {
        int i = 1;
        int j = 1;
        double sum = 0;  //结果肯定是小数, 所以要定义成double或float型
        while (1.0/i > 1e-6)  /*当1/i小于10的-6次方时停止循环。这个循环条件是自己定的, 定得越小最后的结果就越精确。注意1一定要写成小数的形式即1.0*/
        {
            sum += (1.0 / i) * j;
            i+=2;
            j = -j;  //实现正负交替
        }
        sum *=4;
        printf("sum = %lf\n", sum);  //double是%lf, 取6位小数是%.6
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第二题

    求大数的阶乘。

    在解决求大数的阶乘这个问题之前,我们先通过解决求大数加法这一问题进行引入,解决大数加法的问题,大数的阶乘会更加简单。

    大数的加法

    以前我们写加法都是:

    #include
    int main()
    {
       int a,b;
       scanf("%d %d",&a,&b);
       printf("%d",a+b);
       return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    对于比较小的数字可能还可以计算,但是对于超出整形范围(-2147483648~2147483647(
    在这里插入图片描述)的数字,可能就没有办法了。

    为了解决这个问题,我们采取运用字符串数组来巧妙地计算大数。

    先来看一个程序预热,下面代码的作用是将输入的字符串转化为整型打印出来。

    int main()
    {
        int i = 0,tmp = 0;
        char a[11] = { 0 }; //如果从i =10开始遍历的话,定义数组时要定义到大小为11,负责遍历到没有定义的元素,数组会溢出
        char b[11] = { 0 };
        scanf("%s",a);
        for (tmp = 0, i = strlen(a) - 1; i >= 0; i--)
            b[tmp++] = a[i] - '0';  // ASCII码里面字符数字转化为对应的十进制的数字,可以用%d打印数字
        
        // 输出结果
        for (i = 10; i >= 0; i--) //如果从i =10开始遍历的话,定义数组时要定义到大小为11,负责遍历到没有定义的元素,数组会溢出
        {
            if (b[i] != 0) 
            {
                for (i; i >= 0; i--)
                {
                    printf("%d", b[i]);
                }
                //这里用不着break,到这的时候i已经等于0了,执行到这以后,i=0;在执行大for循环地i--后,不再满足大for循环的条件,直接退出循环
               // break;
            }
        }
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    下面带来大数加法的程序。
    #include
    #include
    #define MAXLEN 10000 //定义求和结果的最大位数
    int main()
    {
        int i, up, tmp;
        char buffer[MAXLEN + 1] = { 0 }, a[MAXLEN + 1] = { 0 }, b[MAXLEN + 1] = { 0 };
    
        //逆序输入a
        scanf("%s", buffer);
        for (tmp = 0, i = strlen(buffer) - 1; i >= 0; i--)
            a[tmp++] = buffer[i] - '0';  // ASCII码里面字符数字转化为对应的十进制的数字,可以用%d打印数字
    
            //逆序输入b
        scanf("%s", buffer);
        for (tmp = 0, i = strlen(buffer) - 1; i >= 0; i--)
            b[tmp++] = buffer[i] - '0'; // ASCII码里面字符数字转化为对应的十进制的数字,可以用%d打印数字
    
        if (a[0] == 0 && b[0] == 0) // 这是加数都为零的情况
        {
            printf("0");
            return 0;
        }
    
        //计算
        for (up = 0, i = 0; i < MAXLEN; i++)
        {
            tmp = a[i] + b[i] + up; // 暂时存储数值
            a[i] = tmp % 10;
            up = tmp / 10; // 进位
        }
    
        // 输出结果
        for (i = MAXLEN; i >= 0; i--)
        {
            if (a[i] != 0)
            {
                for (i; i >= 0; i--)
                {
                    printf("%d", a[i]);
                }
               //break;//这个break其实用不着,此时i已经等于0了
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    注意点:

    (1)我们先来复习一下strlen函数的基础知识。

    a、strlen是求字符串长度的函数,不能求整型数组的长度。

    b、看看strlen求字符串长度的返回值。

    int main()
    {
        char a[] = "1234";
        printf("%d", strlen(a));  //结果是4
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (2)数字字符数组不能直接通过%d去打印数组里的每一个数字。

    //这样是不对的
    int main()
    {
        int i = 0, tmp = 0;
        char a[10] = { 0 };
        scanf("%s", a);
        for (i = strlen(a) - 1; i >= 0; i--)
        {
            printf("%d",a[i]);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (3)数字字符数组要转化为数字打印出来需要这样操作

    int main()
    {
    	char a[10] = {0};
    	int  b[10] = { 0 };
    	int i,tmp;
    	scanf("%s",a);
    	    for (tmp = 0, i = strlen(a) - 1; i >= 0; i--)
    	        b[tmp++] = a[i] - '0';  // ASCII码里面字符数字转化为对应的十进制的数字,可以用%d打印数字
    	printf("%d",b[1]);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    或者

    int main()
    {
        int i = 0,tmp = 0;
        char a[11] = { 0 }; //如果从i =10开始遍历的话,定义数组时要定义到大小为11,负责遍历到没有定义的元素,数组会溢出
        char b[11] = { 0 };
        scanf("%s",a);
        
        //逆序输入b
        for (tmp = 0, i = strlen(a) - 1; i >= 0; i--)
            b[tmp++] = a[i] - '0';  // ASCII码里面字符数字转化为对应的十进制的数字,可以用%d打印数字
        
        // 输出结果
        for (i = 10; i >= 0; i--) //如果从i =10开始遍历的话,定义数组时要定义到大小为11,负责遍历到没有定义的元素,数组会溢出
        {
            if (b[i] != 0) 
            {
                for (i; i >= 0; i--)
                {
                    printf("%d", b[i]);
                }
                //这里用不着break,到这的时候i已经等于0了,执行到这以后,i=0;在执行大for循环地i--后,不再满足大for循环的条件,直接退出循环
               // break;
            }
        }
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    (4)整型数组不能用数组名打印,只有字符数组才能用数组名打印,整型数组只能一个一个数组元素打印。

    (5)打印字符串数组时,for循环通常这样搭配

    //这样搭配的
    //tmp = 0, i = strlen(buffer) - 1;
    //tmp = 1, i = strlen(buffer);
    
    • 1
    • 2
    • 3

    (6)字符数组元素转整型元素后的加法运算,a[i]与b[i]已转化为整型元素

    	//    //计算  数组的第一位,即两个数的个位 初始进位值up = 0 计算出来应该要逆向输出 这是一个计算的好法子
        for (up = 0, i = 0; i <= len; i++)
        {
            tmp = a[i] + b[i] + up; // 暂时存储数值
            result[i] = tmp % 10;
            up = tmp / 10; // 进位
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (7)在使用数组时,一定要注意数组空间大小的申请,避免访问数组以外的元素导致出现栈溢出

    (8)注意数组的初始化操作还有sizeof与strlen的区别

    例一

    char arr1[]={'H','E','L','L','O'};
    char arr2[]="HELLO";
    sizeof(arr1);  //返回5
    sizeof(arr2);  //返回6,因为最后有一个'\0'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    例二

    char *str1 = "asdfgh";
    char str2[] = "asdfgh";
    char str3[8] = {'a', 's', 'd'};
    char str4[] = "as\0df";
    
    • 1
    • 2
    • 3
    • 4

    输出结果是

    sizeof(str1) = 4;  strlen(str1) = 6;
    sizeof(str2) = 7;  strlen(str2) = 6;
    sizeof(str3) = 8;  strlen(str3) = 3;
    sizeof(str4) = 6;  strlen(str4) = 2;
    
    • 1
    • 2
    • 3
    • 4

    sizeof能计算变量或者数据类型所占用的内存(以字节为单位)。用sizeof计算数组长度时,sizeof不关心数组内部存储的是什么类型的数据。
    所以常常用 sizeof(arr)/sizeof(arr[0]) 来计算数组的长度。其中“sizeof(arr)“计算了整个数组arr占据了多少内存(字节为单位),”sizeof(arr[0])“计算了数组中第一个元素所占多少字节,两者相除就是数组的长度。

    看下面代码及其输出结果
    	int arr1 [10] = {0};//定义了元素个数,且给第一个元素赋值为0,则其他元素均为0
    
    	int arr2 [10] = {1, 2, 3, 4, 5};//定义了元素个数,但只给前五个元素赋值,则后五个元素均为0
    
    	int arr3 [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//定义了元素个数,且给所有元素均赋值
    
    	int arr4 [10];//什么都不放,编译器会给数组的每个元素放置随机数。
    	
    	int arr5[] = {1, 2, 3};//不定义元素个数,给几个元素赋值就有几个元素。
    
    	int len1 = sizeof(arr1) / sizeof(arr1 [0]);
    	int len2 = sizeof(arr2) / sizeof(arr2 [0]);
    	int len3 = sizeof(arr3) / sizeof(arr3 [0]);
    	int len4 = sizeof(arr4) / sizeof(arr4 [0]);
    	int len5 = sizeof(arr5) / sizeof(arr5 [0]);
    
    	printf("length arr1 = %d\n", len1);
    	printf("length arr2 = %d\n", len2);
    	printf("length arr3 = %d\n", len3);
    	printf("length arr4 = %d\n", len4);
    	printf("length arr5 = %d\n", len5);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    运行结果

    在这里插入图片描述

    大数阶乘

    先贴代码

    #define _CRT_SECURE_NO_WARNINGS 1
    
    #include
    #include
    #define MAXLEN 100  //定义阶乘结果的最大位数
    int main()
    {
        int n, i, j, up, tmp;
        char arr[MAXLEN + 1] = { 1 };  //最开始arr[0] = 1,用1来乘
    
        // 输入n
        scanf("%d", &n);
    
        //计算    
        //arr[0]保存结果的个位,arr[1]保存结果的十位,以此类推
        for (i = 2; i <= n; i++)
        {
            for (up = 0, j = 0; j <= MAXLEN; j++)
            {
                tmp = arr[j] * i + up; 
                arr[j] = tmp % 10;
                up = tmp / 10;
            }
        }
        // 输出结果  逆序输出
        for (i = MAXLEN; i >= 0; i--)
            if (arr[i] != 0)
                for (i; i >= 0; i--)
                    printf("%d", arr[i]);
        return 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    代码分析

    (1)代码实现思路是:

    以计算5!为例,我们的运算思路是1乘2乘3乘4乘5,以此得到运算结果为2,6,24,120。我们巧妙通过arr[0],arr[1],arr[2]来存放运算结果的个位、十位和百位,实现代码如下:

        //计算    
        //arr[0]保存结果的个位,arr[1]保存结果的十位,以此类推
        for (i = 2; i <= n; i++)
        {
            for (up = 0, j = 0; j <= MAXLEN; j++)
            {
                tmp = arr[j] * i + up; 
                arr[j] = tmp % 10;
                up = tmp / 10;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (2)结果的输出:由于我们在计算过程中是将各位逆序存入数组的,所以我们也像大数的加法一样逆序输出结果。

        // 输出结果  逆序输出
        for (i = MAXLEN; i >= 0; i--)
            if (arr[i] != 0)
                for (i; i >= 0; i--)
                    printf("%d", arr[i]);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (3)#define MAXLEN 100 //定义阶乘结果的最大位数

    arr[MAXLEN + 1]数组用来存放运算结果。

  • 相关阅读:
    1024程序员节,今年的秋天比以往来的稍晚了一些
    也许是最客观、全面的比较 Rust 与 Go:都想把 Rust 也学一下
    JAVA面试题总结基础篇(三)
    Python手写人脸识别
    Android MediaPlayer IllegalStateException源码分析定位
    Java基础知识全览
    Leetcode - 周赛402
    C 语言与 C++ 语言中全局变量重新声明的行为差异
    【无标题】
    【C++初阶】STL详解(二)string类的模拟实现
  • 原文地址:https://blog.csdn.net/weixin_62261692/article/details/133777022