atoi函数解析以及自定义类型经典练习题

2024-04-06 16:04

本文主要是介绍atoi函数解析以及自定义类型经典练习题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 今天也是清明节,但奈何学校只放一天假,那就只能来简简单单写个博客了,今天要写的自己对atoi函数的理解吧。还有发现了几道自定义类型的经典练习,像结构体,联合体也是有的,就写到博客分享一下。

常常会回顾努力的自己,所以要给自己的努力留下足迹。

为今天努力的自己打个卡,留个痕迹吧

                                                                                                        2024.04.04     小闭


目录

atoi的概念

代码演示atoi细节:

自定义类型经典练习题


atoi的概念

在 C 语言中, atoi 函数是一个用于将字符串转换为整数的库函数。它的全称是 atoi ,代表"ASCII to Integer",即把字符串表示的 ASCII 码值转换为整数。

 atoi 函数的声明如下:
 

int atoi(const char *str);


 
参数:
 
-  str :指向要转换的字符串的指针。字符串中如果前面为空格该函数会省略掉前面的空格,直到遇到第一个数字字符。


返回值:
 
- 如果转换成功, atoi 函数返回转换后的整数。

- 如果 str 为空指针或不符合整数表示形式, atoi 函数返回 0。
 

函数的细节:

  •   atoi 函数只转换字符串的前一部分,直到遇到非数字字符或字符串结束。
  •   atoi 函数不检查字符串是否超出整数范围,如果转换的结果超出了整数范围,结果可能不正确。
  •  由于 atoi 函数不检查字符串的有效性,可能会导致缓冲区溢出等安全问题。因此,在使用 atoi 函数时,应该确保输入的字符串是有效的整数表示形式。

    下面是就简单给大家举一个示例代码的例子,演示了如何使用 atoi 函数将字符串转换为整数:
     
     
    #include <stdio.h>
    #include <stdlib.h>int main() {// 定义一个字符串char str[] = "12345";int num;// 将字符串转换为整数num = atoi(str);// 输出转换后的整数printf("转换后的整数为:%d\n", num);return 0;
    }

     
     
    在这个示例中,定义了一个字符串 str ,它表示一个整数"12345"。然后,调用 atoi 函数将字符串转换为整数,并将结果存储在变量 num 中。最后,使用 printf 函数输出转换后的整数。
     
    需要注意的是, atoi 函数返回的是一个整数值,如果需要将结果存储在非整数类型的变量中,需要进行类型转换。


代码演示atoi细节:

int main() {// 定义一个字符串char str[] = "   -12 aaee345";int num;// 将字符串转换为整数num = atoi(str);// 输出转换后的整数printf("转换后的整数为:%d\n", num);return 0;
}

这里再字符串没遇到数字字符时会过滤掉空格,直到遇到数字字符”+“,”-“号,这时在这之后再遇到任何不是数字字符的字符都会直接结束函数。

如上方代码,在省略完函数前方的空格后,函数遇到-,1,2.后,在遇到空格直接结束函数,所以这里的结果为-12.

再看一下一段代码:

int main() {// 定义一个字符串char str[] = "  -  12 aaee345";int num;// 将字符串转换为整数num = atoi(str);// 输出转换后的整数printf("转换后的整数为:%d\n", num);return 0;
}

这个只要按照我上面的说法也是很简单判断的,这里函数先是省略掉前面的空格然后识别到”-“,之后是空格,不是数字字符,直接结束函数,因为在此之前没有读取到任何数字字符所以这里的结果就是0.

总结:在atoi函数遇到第一个”+“,”-“,或数字字符后在遇到任何非 数字字符的函数则直接结束函数。


自定义类型经典练习题

诸君请看题呀

一、


#include <stdio.h>
#include <stdlib.h>#define A 2
#define B 3
#define MAX_SIZE A+Bstruct _Record_Struct
{unsigned char a : 4;unsigned char b : 2;unsigned char c;unsigned char d : 1;
}s;int main()
{size_t num=sizeof(s)* MAX_SIZE;printf("%d\n", num);return 0;
}

 大家伙觉得这道题的打印结果是什么呢,注意这道题除了考验一下我们对结构体位段知识的掌握,还设了一个坑点哦。

这里要知道打印结果就需要先知道位段结构体的大小 ,那么这里我们来求一求这个位段结构体的大小。如下图:这里求位段结构体的大小之前已发过文章,还没看过的小伙伴可以先去看看唔传送门:http://t.csdnimg.cn/XMm4oicon-default.png?t=N7T8http://t.csdnimg.cn/XMm4o

这里我们成功求到这个结构体的大小,然后再看到这里,size_t num=sizeof(s)* MAX_SIZE;

在开头我们定义了

#define A 2
#define B 3
#define MAX_SIZE A+B

那我们一想,那不就是结构体大小再乘上MAX_SIZE不就可以了,然后3*5=15.然后答案真的是15吗。

很显然我之前说的坑点就是在这里,在这里答案是9.为什么呢?

在这里size_t num=sizeof(s)* MAX_SIZE;等价于size_t num=sizeof(s)* 2+3;

大家再看看这样后结果是不是就是9了,这里#define 只是单纯的变名,所以当用到时我们要将其变的东西原样抄下来即可。故这里的答案为9.


二、

int main()
{unsigned char s[4];struct tagPIM{unsigned char a;unsigned char b : 1;unsigned char c : 2;unsigned char d : 3;}*p;p = (struct tagPIM*)s;memset(s, 0, 4);p->a = 2;p->b = 3;p->c = 4;p->d = 5;printf("%02x %02x %02x %02x\n", s[0], s[1], s[2], s[3]);return 0;
}

这道题也是一道有关结构体位段的题目,而且还是具有一点难度的,那么接下来就一一解剖一下这道题吧。

首先上面的代码定义了一个char类型数组和结构体,并且创建了一个结构体指针,然后这道题重点就来了。

这里上面的题目当中开始把数组地址(数组名s)强制转化为结构体指针赋值给 struct tagPIM *p

然后再开始以位段结构体的形式进行对内存里赋值,这里的内存也是数组的内存,也是会影响函数的。

赋值阶段:

代码先是利用memset函数将数组中的4个字节的内存全部赋值为0。

再然后进行了这样的赋值

    p->a = 2;
    p->b = 3;
    p->c = 4;
    p->d = 5;

这里我们的成员a没有限定成员的大小所以依旧占据内存的一个字节,所以s[0]为2。

然后到下面重点了,我们画图来理解。

如上面所说这里我们已经算出第二个字节的内存里存储的数据,因为后面两个字节并未赋值到,所以还为0,综上所述这里打印的结果应该为02 29 00 00。 


三、写一个用联合体判断当前机器的是大端还是小端储存。

参考代码如下:

int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;
}int main()
{int ret = check_sys();if(ret == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}

正如上面所写,我们定义一个联合体并创建,成员一个为int类型,一个为char类型,我们知道联合体共用一块内存,而且char的内存是在低地址处。那么这时我们就先给int数据赋值一个1.

我们要知道1为一个整形十六进制为 00 00 00 01,那么此时最后两个数01为低位,我们只需要取地址的数据看是否为1,就可以判断出机器是大端还是小端

此时我们就看机器是大端还是小端,就可以返回char c,处的数据,这里为低地址的内存,如果此时数据为1,说明该机器把低位是数据放到低地址处,所以为小端储存模式。反之则为大端。


 文章已到末尾

常常会回顾努力的自己,所以要给自己的努力留下足迹。

为今天努力的自己打个卡,留个痕迹吧

                                                                                                           2024.04.04     小闭

                            

这篇关于atoi函数解析以及自定义类型经典练习题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/880255

相关文章

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

如何自定义Nginx JSON日志格式配置

《如何自定义NginxJSON日志格式配置》Nginx作为最流行的Web服务器之一,其灵活的日志配置能力允许我们根据需求定制日志格式,本文将详细介绍如何配置Nginx以JSON格式记录访问日志,这种... 目录前言为什么选择jsON格式日志?配置步骤详解1. 安装Nginx服务2. 自定义JSON日志格式各

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

Spring MVC使用视图解析的问题解读

《SpringMVC使用视图解析的问题解读》:本文主要介绍SpringMVC使用视图解析的问题解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC使用视图解析1. 会使用视图解析的情况2. 不会使用视图解析的情况总结Spring MVC使用视图

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高