C语言基础练习——Day16

文章详细解析了C语言基础练习中的选择题,涉及浮点数比较、内存安全、数组越界、字符串截取以及数对计算,强调了编程技巧和类型精度理解
摘要由CSDN通过智能技术生成

目录

选择题

编程题

截取字符串

数对


声明:本篇是C语言基础练习的最后一篇

选择题

1、(多选题)指出下列代码的缺陷

float f[10];
// 假设这里有对f进行初始化的代码
for(int i = 0; i < 10;)
{
    if(f[++i] == 0)
        break;
}
  • A for(int i = 0; i < 10;)这一行写错了
  • B ffloat型数据直接做相等判断有风险
  • C f[++i]应该是f[i++]
  • D 没有缺陷
答案:BC
💡

解析:

一般float型只能精确到小数后六位(即1e-6),将float型数据的绝对值与1e-6比较,来判断是否相等(为零)。float的精度误差在1e-6double精度误差在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
答案:AC
💡

解析:

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

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
答案:AC
💡

解析:

对于0x20150810

如果按照大端模式存储:从低地址到高地址:20 15 08 10 输出从低地址到高地址:20 15 08 10

如果按照小端模式存储:从低地址到高地址:10 08 15 20 输出从高地址到低地址:08 10 20 15

此数以int类型赋值给联合体x.a,而以结构成员bc分开访问,分别拿到低地址的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 内存泄露
答案:AB
💡

解析:

数组下标越界:数组大小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

答案:C

解析:

💡

本题就是找规律,计算什么时候能遇到0

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

描述
输入一个字符串和一个整数 k ,截取字符串的前k个字符并输出

数据范围:字符串长度满足 1≤ n≤1000 , 1≤ kn
输入描述:
1.输入待截取的字符串
2.输入一个正整数k,代表截取的长度
输出描述:
截取后的字符串

思路解析:

本题只需要打印截取长度个字符即可

参考代码

#include <stdio.h>

int main() {
    char str[1000] = {0};
    scanf("%s", str);
    int num = 0;
    scanf("%d", &num);
    for (int i = 0; i < num; i++) {
        printf("%c", str[i]);
    }
    return 0;
}

数对

题目链接:数对_牛客题霸_牛客网

描述
牛牛以前在老师那里得到了一个正整数数对 (x, y), 牛牛忘记他们具体是多少了。
但是牛牛记得老师告诉过他 xy均不大于 n, 并且 x除以 y的余数大于等于 k
牛牛希望你能帮他计算一共有多少个可能的数对。
输入描述:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。
输出描述:
对于每个测试用例, 输出一个正整数表示可能的数对数量。

思路解析:

更优解法: 假设输入 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));

参考代码

#include <stdio.h>
int main()
{
    long n, k;
    while(~scanf("%ld %ld", &n, &k)){
        if (k == 0) {
            printf("%ld\n", n * n);//任意数对的取模结果都是大于等于0的
            continue;
        }
        long count = 0;
        for(long y = k + 1; y <= n; y++) {
            count += ((n / y) * (y - k)) + ((n % y < k) ? 0 : (n % y - k + 1));
        }
        printf("%ld\n", count);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怡晗★

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值