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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 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: 2    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 <stdio.h>
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<stdio.h>
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)

示例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 <stdio.h>
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)

示例1

       输入:

       abABCcDEF

       6

       输出:

       abABCc

思路一:

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

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

       第三步:打印完后换行。

#include <stdio.h>
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;
}

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

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

                                             

目录
相关文章
|
16天前
|
存储 算法 Linux
C语言 多进程编程(一)进程创建
本文详细介绍了Linux系统中的进程管理。首先,文章解释了进程的概念及其特点,强调了进程作为操作系统中独立可调度实体的重要性。文章还深入讲解了Linux下的进程管理,包括如何获取进程ID、进程地址空间、虚拟地址与物理地址的区别,以及进程状态管理和优先级设置等内容。此外,还介绍了常用进程管理命令如`ps`、`top`、`pstree`和`kill`的使用方法。最后,文章讨论了进程的创建、退出和等待机制,并展示了如何通过`fork()`、`exec`家族函数以及`wait()`和`waitpid()`函数来管理和控制进程。此外,还介绍了守护进程的创建方法。
C语言 多进程编程(一)进程创建
|
16天前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。
|
16天前
|
Linux C语言
C语言 多进程编程(四)定时器信号和子进程退出信号
本文详细介绍了Linux系统中的定时器信号及其相关函数。首先,文章解释了`SIGALRM`信号的作用及应用场景,包括计时器、超时重试和定时任务等。接着介绍了`alarm()`函数,展示了如何设置定时器以及其局限性。随后探讨了`setitimer()`函数,比较了它与`alarm()`的不同之处,包括定时器类型、精度和支持的定时器数量等方面。最后,文章讲解了子进程退出时如何利用`SIGCHLD`信号,提供了示例代码展示如何处理子进程退出信号,避免僵尸进程问题。
|
16天前
|
消息中间件 Unix Linux
C语言 多进程编程(五)消息队列
本文介绍了Linux系统中多进程通信之消息队列的使用方法。首先通过`ftok()`函数生成消息队列的唯一ID,然后使用`msgget()`创建消息队列,并通过`msgctl()`进行操作,如删除队列。接着,通过`msgsnd()`函数发送消息到消息队列,使用`msgrcv()`函数从队列中接收消息。文章提供了详细的函数原型、参数说明及示例代码,帮助读者理解和应用消息队列进行进程间通信。
|
16天前
|
缓存 Linux C语言
C语言 多进程编程(六)共享内存
本文介绍了Linux系统下的多进程通信机制——共享内存的使用方法。首先详细讲解了如何通过`shmget()`函数创建共享内存,并提供了示例代码。接着介绍了如何利用`shmctl()`函数删除共享内存。随后,文章解释了共享内存映射的概念及其实现方法,包括使用`shmat()`函数进行映射以及使用`shmdt()`函数解除映射,并给出了相应的示例代码。最后,展示了如何在共享内存中读写数据的具体操作流程。
|
16天前
|
消息中间件 Unix Linux
C语言 多进程编程(二)管道
本文详细介绍了Linux下的进程间通信(IPC),重点讨论了管道通信机制。首先,文章概述了进程间通信的基本概念及重要性,并列举了几种常见的IPC方式。接着深入探讨了管道通信,包括无名管道(匿名管道)和有名管道(命名管道)。无名管道主要用于父子进程间的单向通信,有名管道则可用于任意进程间的通信。文中提供了丰富的示例代码,展示了如何使用`pipe()`和`mkfifo()`函数创建管道,并通过实例演示了如何利用管道进行进程间的消息传递。此外,还分析了管道的特点、优缺点以及如何通过`errno`判断管道是否存在,帮助读者更好地理解和应用管道通信技术。
|
16天前
|
Linux C语言
C语言 多进程编程(七)信号量
本文档详细介绍了进程间通信中的信号量机制。首先解释了资源竞争、临界资源和临界区的概念,并重点阐述了信号量如何解决这些问题。信号量作为一种协调共享资源访问的机制,包括互斥和同步两方面。文档还详细描述了无名信号量的初始化、等待、释放及销毁等操作,并提供了相应的 C 语言示例代码。此外,还介绍了如何创建信号量集合、初始化信号量以及信号量的操作方法。最后,通过实际示例展示了信号量在进程互斥和同步中的应用,包括如何使用信号量避免资源竞争,并实现了父子进程间的同步输出。附带的 `sem.h` 和 `sem.c` 文件提供了信号量操作的具体实现。
|
4月前
|
C语言
c语言编程练习题:7-10 算术入门之加减乘除
对于输入的两个整数,按照要求输出其和差积商。
98 0
|
10月前
|
存储 C语言 数据格式
【手把手带你刷题】-C语言编程入门篇(四)
【手把手带你刷题】-C语言编程入门篇(四)
63 0
|
10月前
|
机器学习/深度学习 存储 C语言
【手把手带你刷题】-C语言编程入门篇(三)
【手把手带你刷题】-C语言编程入门篇(三)
60 0