练习(含atoi的模拟实现,自定义类型等练习)

news2025/6/12 21:09:52

一、结构体大小的计算及位段

结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客)

1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少?

#pragma pack(4)

struct A
{
    int a;
    short b;
    int c;
    char d;
};
struct B
{
    int a;
    short b;
    char c;
    int d;
};

#pragma pack()
int main()
{
    printf("%d\n",sizeof(A));//16
    printf("%d\n",sizeof(B));//12
    return 0;
}

2.在VS2022下,默认对齐数为8字节,这个结构体所占的空间大小是多少字节

typedef struct
{
    int a;
    char b;
    short c;
    short d;
}aa_t;
int main()
{
    printf("%d\n",sizeof(aa_t));//12
    return 0;
}

3.当A=2,B=3时,pointer分配了几个字节空间?

(位段的几个成员共用一个字节,如果一个字节内剩余的空间(比特位)不足以放下下一个成员,会浪费掉这些空间,重新在开辟一个字节来继续存放)

#define A 2
#define B 3
#define MAX_SIZE A+B
struct A
{
    unsigned char a : 4;// 1byte
    unsigned char b : 2;             ————> 3byte
    unsigned char c;// 1byte
    unsigned char d : 1;// 1byte
};
int main()
{
    struct A* pointer = (struct A*)malloc(sizeeof(struct A) * MAX_SIZE);
    // sizeeof(struct A) * MAX_SIZE = 3*2+3 = 9
    return 0;
}

当然我们也可以打印出来看看:

4.以下代码的结果是什么?

int main()
{
    unsigned char puc[4];
    struct S
    {
        unsigned char a;// 1byte
        unsigned char b : 1;//1byte
        unsigned char c : 2;          ————> 2byte
        unsigned char d : 3;
    };
    s = (struct S*)puc;
    memset(puc,0,4);     //00000000 00000000 00000000 00000000
    s->a = 2;//010       //00000010 00101001 00000000 00000000 
    s->b = 3;//011-1     //   02       29       00       00
    s->c = 4;//100-00
    s->d = 5;//101

    printf("%02x %02x %02x %02x\n",puc[0],puc[1],puc[2],puc[3]);// %02x 表示打印2位十六进制位
                                //  02      29    00     00
    return 0;
}

二、枚举、联合体

枚举、联合体 详解请看:自定义类型:枚举、联合_m语言定义枚举量-CSDN博客)

1.以下代码的结果是什么?

联合的大小至少是最大成员的大小,当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

union Un
{
    short s[7];// 14   2/8-short类型的整型,大小为2字节,小于默认对齐数8,取2
    int n;//4  4/8-取4       14/4 - 最大成员的大小并不是最大对齐数的整数倍,因此,最终是取值为16
};
int main()
{
    printf("%d\n",sizeof(union Un));//16
    return 0;
}

2.以下代码的结果是什么?

枚举成员如果不赋初始值,默认从0开始,每增加一次加1,如果中间有成员进行赋值,那么在这个成员之前的就还是从0开始,在这个成员之后的,就在赋值的数的基础上每次增加1

enum e
{
    x1,
    y1,
    z1 = 255,
    a1,
    b1
};
int main()
{
    enum e A = y1;
    enum e B = b1;
    printf("%d %d\n",A,B);//1 257

    return 0;
}

三、动态内存函数分析错误并改正

(详解请看:动态内存管理2+柔性数组-CSDN博客

动态内存管理-CSDN博客)

指出以下代码错误的地方并进行改正

void GetMemory(char* p)
{
    p = (char*)malloc(100);
}
void Test()
{
    char* str = NULL:
    GetMemory(str);
    strcpy(str,"hello world");
    printf(str);
}
int main()
{
    Test();
    return 0;
}

错误:1.这个代码传给GetMemory函数的参数是值传递,而我们知道对形参的改变是不会影响实参的,所以即使GetMemory函数返回,str依然为NULL

2.使用动态内存函数进行空间开辟,没有对malloc函数的返回值进行判断

3.存在内存泄露,使用完之后没有进行free释放

改正:

void GetMemory(char** p) //使用一个二级指针变量进行接收
{
    *p = (char*)malloc(100); 
}
void Test()
{
    char* str = NULL:
    GetMemory(&str);//改为址传递(一级指针)
    if(str != NULL)  //对返回值进行判断
    {
        strcpy(str,"hello world");
        printf(str);
    }
    free(str); //释放
    str = NULL;
}
int main()
{
    Test();
    return 0;
}

四、大小端

在X64环境下,小端字节序存储,以下代码输出的结果是什么?

int main()
{
    union
    {
        short k;
        char i[2];
    }*s,a;
    s = &a;
    s->i[0] = 0x39;
    s->i[1] = 0x38;
    printf("%x\n",a.k);//3839

    return 0;
}

五、找单身狗

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

版本1:有一个数组,其中只有一个数字出现1次,其余数字都是出现2次
例如:1 2 3 4 5 1 2 3 4

版本2:一个数组中只有两个数字出现一次,其他数字都出现两次
例如:1 2 3 4 5 1 2 3 4 6

而我们要解决的就是版本2的内容

可以将这个数组分成两个数组,分别找出两个数组各自数字中出现一次的数字
//1 1 3 3 5
//2 2 4 4 6

或者
//1 1 4 4 5
//2 2 3 3 6

分组要领:就是要将2个单身狗必须放在2个组里面,同时每个组剩余的数字都是成对出现的

具体如何分组:将单身狗5和6异或(相同为0,相异为1)
// 5^6
//101
//110
//011

【1】如果我们将二进制最低位是1的数字放在一组,其他数字放在另一组:
//5 1 1 3 3
//6 2 2 4 4
【2】将将二进制第二位是1的数字放在一组,其他数字一组:
//5 1 1 4 4
//6 2 2 3 3

代码具体实现:需要一个整型数组来存放所有的数字,再有一个数组存放找到的两个单身狗,写一个函数来寻找单身狗

void find_single_dog(int arr[],int sz,int single_doe[])
{
    int ret = 0;
    int i = 0;
    for(i = 0;i < sz; i++)
    {
        ret ^= arr[i];/所有数字二进制相互进行异或之后最终的结果是 5^6 的结果(因为成对出现的数字相互抵消,仅剩5和6未被抵消),此时ret=5
    }
    //计算ret的哪一位二进制和位是1
    int pos = 0;
    for(i = 0;i < 32; i++)
    {
        if(((ret >> i) & 1) == 1)
        {
            pos = i;
            break;
        }
    }
    for(i = 0;i < sz; i++)
    {
        if(((arr[i] >> pos) & 1) == 1)
        {
            single_dog[0] ^= arr[i];//最终数字的二进制之间异或的结果是101 - > 5
        }
        else
        {
            single_dog[1] ^= arr[i];//6
        }
    }
}
int main()
{
    int arr[] = {1,2,3,4,5,1,2,3,4,6};
    int sz = sizeof(arr)/sizeof(arr[0]);
    int single_dog[2] = {0};

    find_single_dog(arr,sz,single_dog); 
    printf("%d %d\n", single_dog[0], single_dog[1]);//5 6   

    return 0;
}

六、模拟实现atoi

atoi的作用:将字符串转换为整数

int atoi (const char * str);

  • 将 C 字符串 `str` 进行解析,把其内容解读为一个整数值,并以 `int` 类型的值返回。
  • 该函数首先会尽可能多地丢弃空白字符(就像 `isspace` 函数所判定的那样),直到找到第一个非空白字符。接着,从这个字符开始,它会处理一个可选的初始正负号,随后尽可能多地读取十进制数字,并将它们解读为一个数值。
  • 字符串中在构成整数的字符之后还可以包含其他字符,这些字符会被忽略,并且不会对该函数的行为产生影响。
  • 如果 `str` 中第一个非空白字符序列不是一个有效的整数,或者由于 `str` 为空,或者它仅包含空白字符而不存在这样的序列,那么将不执行转换操作,函数会返回零。 
  • 如果转换成功,该函数会将转换后的整数值以 `int` 类型返回。
  • 如果转换后的值超出了 `int` 类型所能表示的值的范围,则会导致未定义行为。

首先我们先通过使用atoi这个函数,确定模拟实现它有哪些限制条件

#include <stdlib.h>
#include <stdio.h>

int main()
{
    //1
    int ret = atoi("  -12#34");//打印 -12
    //2
    int ret = atoi("  1234");//打印 1234(前面空白字符不打印)
    //3
    int ret = atoi("  -1234");//打印 -1234
    //4
    int ret = atoi("  -1234111111111111111111111111111111111111111111111");//打印-2147483647
    //5
    int ret = atoi(NULL);//报警告

    printf("%d\n", ret);
    return 0;
}

最终我们确定限制条件(非法条件):

1.空指针(不能对空指针进行应用)
2.空白字符(不将空白字符打印出来)//" "
3.+/- 打印出来,其他的符号不考虑
4.考虑溢出(字符串太长)

模拟实现:

#include <assert.h>
#include <ctype.h>

enum State
{
    VALID,
    INVALID
}state = INVALID;//默认表示非法
int my_atoi(const char* str)
{
    assert(str);
    //检查字符串指针是否有效,处理空字符串返回0
    if(*str == '\0')
    {
        return 0;
    }
    //跳过空白字符
    while(isspace(*str))
    {
        str++;
    }
    //处理正负号(其他符号忽略),设置flag为1或-1
    int flag = 1;
    if(*str == '+')
    {
        str++;
    }
    else if(*str == '-')
    {
        int flag = -1;
        str++;
    }
    //遍历后续字符,将数字转换为整数,同时考虑符号和溢出
    long long ret = 0;
    while(*str)
    {
        if(isdigit(*str))
        {
            ret = ret * 10 + (long long)(flag * (long long)(*str - '0'));//将一个个字符转换成整数
            if(ret > INT_MAX)
            {
                return INT_MAX;
            }
            else if(ret < INT_MIN)
            {
                return INT_MIN;
            }
        }
        else
        {
            return (int)ret;
        }
        str++;
    }

    state = VALID;
    return (int)ret;
}
int main()
{
    int ret = my_atoi("   -1234");
    if (state == VALID)
		printf("%d\n", ret);
	else
		printf("非法字符串转换,%d\n", ret);
    return 0;
}

七、文件操作

下面程序的功能是什么?

统计文件的字符数

int main()
{
    long num = 0;
    FILE* pf = NULL;
    if((pf = fopen("fname.dat","r")) == NULL)
    {
        perror("fopen");
        return 1;
    }
    while(fgetc(pf) != EOF)
    {
        num++;
    }
    printf("%d\n",num);
    fclose(pf);
    pf = NULL:

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2407872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…