C语言:选择+编程(每日一练Day16)

目录

选择题:

题一:

题二:

题三:

题四:

题五:

编程题:

题一:数对

思路一:

题二:截取字符串

思路一:

本人实力有限可能对一些地方解释和理解的不够清晰,可以自己尝试读代码,或者评论区指出错误,望海涵!

感谢大佬们的一键三连! 感谢大佬们的一键三连! 感谢大佬们的一键三连!


选择题:

题一:

1、指出下列代码的缺陷【多选】( )
float f[10];
// 假设这里有对f进行初始化的代码
for(int i = 0; i < 10;)
{
        if(f[++i] == 0)
        break;
}

A: for(int i = 0; i < 10;)这一行写错了

B: f是float型数据直接做相等判断有风险
C: f[++i]应该是f[i++]

D: 没有缺陷

答案解析:

        一般float型只能精确到小数后六位(即1e-6),将float型数据的绝对值与1e-6比较,来判断是否相等(为零)。float的精度误差在1e-6;double精度误差在1e-15;所以要判断一个float型数:if(fabs(f)<1e-6);要判断一个double型数:if(fabs(f)<1e-15);若满足,则为零。考虑B选项是对的。若要判断float a,b是否相等,要看if(fabs(a-b)<1e-6)是否为真。C选项,考虑的是数组越界问题。

题二:

2、请指出以下程序的错误【多选】( )
void GetMemory(char **p, int num)
{
        if(NULL == p && num <= 0)//1
                return;
        *p = (char*)malloc(num);
        return;
}

int main()
{
        char *str = NULL;
        GetMemory(&str, 80); //2
        if(NULL != str)
        {
                strcpy(&str, "hello"); //3
                printf(str); //4

        }

        return 0;
}

A: 1    B:  C: 3    D: 4

答案解析:

        第1处两种情况之一成立都是要返回的,应该用或,此处用与错误。在语句GetMemory(&str,100);中传入str的地址,在语句char*str=NULL;中str初始化为空指针,但是str指针变量也有地址,所以参数char**p里面的p保存的是指针变量str的地址,所以调用GetMemory函数之后,动态开辟的空间的地址存放在了str中,在函数返回之后没有释放内存,但是这不会导致程序错误,只会导致内存泄漏。第3处用&str是错的,应该直接用str,是刚申请下来的空间首地址,可以用来接收字符串的copy。

题三:

3、请问下列代码的输出结果有可能是哪些【多选】( )
#include
typedef union
{
        int a;
        struct
        {
                short b;
                short c;
        };
}X;
int main()
{
        X x;
        x.a = 0x20150810;
        printf("%x,%x\n", x.b, x.c);
        return 0;
}

A: 2015,810    B: 50810,201    C: 810,2015    D:`20150,810

答案解析:

        对于0x20150810如果按照大端模式存储:从低地址到高地址:20 15 08 10 输出从低地址到高地址:20 15 08 10如果按照小端模式存储:从低地址到高地址:10 08 15 20 输出从高地址到低地址:08 10 20 15此数以int类型赋值给联合体x.a,而以结构成员b和c分开访问,分别拿到低地址的2个字节和高地址的2个字节,大端下是2015和810,小端下是810和2015。

题四:

4、下面这个程序执行后会有什么错误或者效果【多选】( )
#define MAX 255
int main()
{
        unsigned char A[MAX], i;
        for(i = 0; i <= MAX; i++)
                A[i] = i;
        return 0;
}

A: 数组越界    B: 死循环    C: 栈溢出    D: 内存泄露

答案解析:

        数组下标越界:数组大小255,但是当a[255]就是256个元素,导致越界了。死循环:这个是因为无符号字符型的变量大小在0-255之间,所以说i永远不可能大于255的,是个死循环。内存泄漏:创建的临时变量,在栈中,应该会由系统自动释放,所以应该是不存在内存泄漏的问题。栈溢出:属于缓冲区溢出的一种。栈溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。

题五:

5、请问下列程序的输出是多少( )
#include
int main()
{
        unsigned char i = 7;
        int j = 0;
        for(;i > 0;i -= 3)
        {
                ++j;
        }
        printf("%d\n", j);
        return 0;
}

A: 2    B: 死循环    C: 173    D: 172

答案解析:

        本题就是找规律,计算什么时候能遇到0unsigned char 8位数据位,范围在0-255,所以-2(11111110)时,变成254;同理-1(11111111)时,变成255;最后减到0时,不满足循环条件,for停止。刚好173次。 7 4 1 ==> 共(7-1)/3+1=3次(1-3=-2,即254,继续循环)
254 251 ... 5 2 ==> 共(254-2)/3+1=85次(2-3=-1,即255,继续循环)255 252 ... 6 3 ==> 共(255-5)/3+1=85次(3-3=0,退出循环) 所以总共173次。

编程题:

题一:数对

数对_牛客题霸_牛客网 (nowcoder.com)

C语言:选择+编程(每日一练Day16)_第1张图片

示例1

        输入:

        5 2

        输出:

        7

        说明:

        满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)

思路一:

假设输入 n=10 , k=3

当 y <=k 时,意味着任何数字取模y的结果都在 [0, k-1]之间,都是不符合条件的。
当 y = k+1=4 时,x符合条件的数字有 3,7
当 y = k+2=5 时,x符合条件的数字有 3,4,8,9
当 y = k+3=6 时,x符合条件的数字有 3,4,5,9,10
当 y = k+n时,
x小于y当前值,且符合条件的数字数量是:y-k个;
x大于y当前值,小于2*y的数据中,且符合条件的数字数量是:y-k个;
从上一步能看出来,在y的整数倍区间内,x符合条件的数量就是 (n / y) * (y - k)个;
n / y 表示有多少个完整的 0 ~ y区间, y - k 表示有每个区间内有多少个符合条件的数字
最后还要考虑的是6...往后这种超出倍数区间超过n的部分的统计;
n % y 就是多出完整区间部分的数字个数,其中k以下的不用考虑,则符合条件的是 n % y - (k-1) 个;
这里需要注意的是类似于9这种超出完整区间的数字个数 本就小于k的情况,则为0。
最终公式:(n / y) * (y - k) + ((n % y < k) ? 0, (n % y - k + 1));

        第一步:定义题目需要输入的n、k,以及用于记录符合条件的个数的count;

        第二步:while循环只要两个变量都有输入就执行判断如果k==0说明所有数都满足条件,直接打印所有数对,然后回到循环起点;否则:因为k+1之前的数都不符合条件,从k+1开始记录数在y的整数倍区间内,x符合条件的数量就是 (n / y) * (y - k)个,再加上n % y 就是多出完整区间部分的数字个数,其中k以下的不用考虑,则符合条件的是 n % y - (k-1) 个。

        第三步:最后的和就是需要打印的结果。 

#include 

int main() 
{
    long n,k;
    
    while(scanf("%ld%ld",&n, &k) == 2)
    {
        //用于记录符合条件的个数
        long count = 0;
        //如果k==0说明所有数都满足条件
        if(k == 0)
        {
            printf("%ld\n", n*n);
            continue;
        }
        //从k+1之前的数都不符合条件
        for(int y = k+1;y <= n;y++ )
        {
            //在y的整数倍区间内,x符合条件的数量就是 (n / y) * (y - k)个
            count += (n / y) * (y - k);
            //n % y 就是多出完整区间部分的数字个数,其中k以下的不用考虑,则符合条件的是 n % y - (k-1) 个
            count += (n % y < k) ? 0 : (n % y - k + 1);
        }
        printf("%ld\n",count);
    }

    return 0;
}

题二:截取字符串

截取字符串_牛客题霸_牛客网 (nowcoder.com)

C语言:选择+编程(每日一练Day16)_第2张图片

示例1

        输入:

        abABCcDEF
        6

        输出:

        abABCc

思路一:

        第一步:定义满足题目要求大小的数组arr,以及截取数k;

        第二步:当输入不为空时,将前k个逐个打印;

        第三步:打印完后换行。

#include 

int main() 
{
    //满足题目条件的数组
    char arr[1000] = {0};
    int k = 0;
    //有熟人就执行
    while(scanf("%s%d", &arr, &k) != EOF)
    {
        //将前k个逐个打印
        for(int i = 0; i < k; i++)
        {
            printf("%c",arr[i]);
        }
        printf("\n");
    }
    return 0;
}

本人实力有限可能对一些地方解释和理解的不够清晰,可以自己尝试读代码,或者评论区指出错误,望海涵!

感谢大佬们的一键三连! 感谢大佬们的一键三连! 感谢大佬们的一键三连!

                                              

你可能感兴趣的:(C语言练习,c语言,开发语言,学习,深度学习,c++,笔记,算法)