C语言刷题练习(Day2)

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

个人主页:侠客er

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

前言

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

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

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

C语言刷题练习(Day2)_第1张图片

第一题

求一串式子的值。上面题目有误,正确题目应该是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的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;
}

第二题

求大数的阶乘。

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

大数的加法

以前我们写加法都是:

#include
int main()
{
   int a,b;
   scanf("%d %d",&a,&b);
   printf("%d",a+b);
   return 0;
}

对于比较小的数字可能还可以计算,但是对于超出整形范围(-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;
}
下面带来大数加法的程序。
#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)我们先来复习一下strlen函数的基础知识。

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

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

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

(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;
}

(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;
}

或者

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;
}

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

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

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

(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; // 进位
    }

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

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

例一

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

例二

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

输出结果是

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

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);

运行结果

C语言刷题练习(Day2)_第2张图片

大数阶乘

先贴代码

#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)代码实现思路是:

以计算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;
        }
    }

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

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

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

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

你可能感兴趣的:(C语言刷题练习,c语言)