编程之路,从0开始:补充篇
Hello大家好!很高兴和大家又见面啦!给生活添点passion,开始今天的编程之路!
我的博客:<但凡.
我的专栏:《编程之路》、《题海拾贝》、《数据结构与算法之美》
欢迎点赞,关注!
这篇文章拖了很久,甚至是在编程之路这个系列完结之后才发出来,主要是想把之前遇到的有意思的小问题一次性给大家说清楚,并做一些拓展。
目录
1、scanf和gets
1.1输入带有空格的字符串
1.2scanf的返回值
2、取模问题
2.1负数取模
2.2取模运算的应用
3、assert断言
4、进制转化
4.1其他进制转十进制
4.2十进制转其他进制
4.3、其他进制转其他进制
5、随机数生成技巧
6、C/C++程序内存区域划分
1、scanf和gets
我们先尝试运行以下代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{char p[10] = "";scanf("%s",p);printf("%s", p);gets(p);printf("%s", p);return 0;
}
我们输入asd fgh,输出asd fgh。
之所以讨论一下scanf和gets,是因为他们有一定的区别。不知道大家在写代码的时候发现没有,用scanf输入字符串时如果字符串中有空格,他打印的时候不会打印空格及以后的内容。但gets是可以打印出有空格的字符串的。
知道这个特点后,我们分析一下上面的代码。首先我们输入asd fgh,scanf只能接收到asd,剩下的空格和fgh以及我们输入的\n(回车)他都放入了缓冲区。然后执行gets时我们不用输入,gets直接从缓冲区读取这些内容,然后打印出来。
1.1输入带有空格的字符串
我们可以用gets函数输入字符串:
#include<stdio.h>
int main()
{char p[100] = "";gets(p);printf("%s",p);return 0;
}
那么我们如何让scanf也能输出含有空格的字符串呢?我们可以这样写:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{char p[100] = "";scanf("%[^\n]",p);printf("%s",p);return 0;
}
输出结果:

这样我们可以让scanf读取到\n之后再停止。另外如果在vs中使用scanf的话需要写上#define _CRT_SECURE_NO_WARNINGS (如上代码),不然的话需要写scanf_s。
我们还可以使用fgets来输入字符串。但是要将文件指针换成stdin(标准输入流):
#include<stdio.h>
int main()
{char p[100] = "";fgets(p, 100, stdin);printf("%s",p);return 0;
}
输出结果:

此外,输入字符串的方式还可以使用getchar和循环一个一个的输入,只是这样麻烦一些。其实在c++中,我们还可以使用cin来输入字符串,而且在c++中我们更常使用string字符串。当然了很久以后我们还会分享c++的知识,这里只是简单提一下。
1.2scanf的返回值
在vs中使用scanf时经常会出现这个警告:

我们去cplusplus上看一下scanf这个函数的原型:

我们发现,其实scanf是有返回值的,而它的返回值就是输入数据的个数。当然了,我们在使用它的时候用到的概率不大。
2、取模问题
2.1负数取模
不知道大家想过没有,一个负数取模结果是正数还是负数呢?
#include<stdio.h>
int main()
{int a = -10;printf("%d",a%3);return 0;
}
输出结果:

很明显,负数取模结果是负数。那么问题又来了,如果我让10%(-3)呢?
输出结果:
经过我们实验可以知道,负数也是支持取模的,但是负数求模结果的正负号由第⼀个运算数(操作数)的正负号决定。
2.2取模运算的应用
我们可以写一个程序,判断一个数是奇数还是偶数:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{int a = 0;scanf("%d", &a);if (a % 2 == 1){printf("奇数\n");}elseprintf("偶数\n");return 0;
}
这个程序对于正数判断奇数偶数没有问题,但是它不能判断负数是奇数还是偶数。
这个时候我们就可以使用奇数二进制末尾都是1这个特性,进行&运算:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{int a = 0;scanf("%d", &a);if (a & 1 == 1){printf("奇数\n");}elseprintf("偶数\n");return 0;
}
因为&运算是当这个二进制位都为1时,他才为1。那么我们让一个数&1不就能保证其他位都是0,我们只判断最后一个位是不是1了呢?
3、assert断言
这个东西我之前用到过,但是忘了说。
assert 是一个宏,用于在运行时检查一个条件是否为真,如果条件不满足,则运行时将终止程序的执行并输出一条错误信息。
在使用时,我们需要包含头文件:
#include<assert.h>
它常用于判断一个地址为不为空或一个数是不是0。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
int main()
{int* p = NULL;assert(p);return 0;
}
结果:

4、进制转化
常见的进制有二进制,八进制,十进制,十六进制...,那么这些进制之间如何转化呢?
4.1其他进制转十进制
· 其实我们数字的每一位都有自己的权重。比方说十进制123,就等一1*(10^2)+2*(10^1)+1*(10^0)。
我们可以利用这个方法将二进制转化为十进制:
比如101转化为十进制就是1*(2^2)+0*(2^1)+1*(2^0)=5。
同样的道理我们也可以把八进制和十六进制转化为十进制。
现在我们来写一个程序将x进制转化为十进制:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<math.h>//使用pow
int main()
{int x = 0;printf("请输入想要转化的数的进制:");scanf("%d", &x);if (x > 36){printf("输入错误\n");return 0;}char s[100] = "";//因为有可能含有大写字符,所以定义为char类型数组printf("请输入被转化数:");scanf("%s", &s);int len = strlen(s);int ret = 0;int j = 0;while(len--)//每次进入循环len自减1{if(s[len]<'9'){ret=ret+(s[len] - '0')* pow(x,j);//当操作数为数字时j++;}else{ret=ret+ (s[len] - 'A'+10) * pow(x, j);//当操作数为字母时j++;}}printf("%d", ret);return 0;
}
输出结果:


当大于十进制时,被转化的数中就会含有ABC这样的大写字母,所以我们在进行计算时要分情况讨论。另外当进制大于36时输入错误,因为最大就10加二十六个字母,也就是说最大进制就是36(除非他用其他的字符继续表示)。
在c++中,我们可以对stoi函数进行改造,使他支持进制转换。当然这里只是拓展一下,想了解的朋友自行了解哈~
4.2十进制转其他进制
我们这里那十进制转二进制举例:

注:画的很丑请见谅~
其实就是让这个十进制数除以想要转化的进制,记录余数,然后再那除完的结果继续去除......但需要注意的是,这些余数我们需要从下往上写(对应上图)。
所以我们就可以用递归的思想实现这个代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
char s[38] = "012345678910ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void itox(int n,int x)
{if(n>=x){itox(n / x, x);//递归}printf("%c", s[n % x]);
}
int main()
{int n = 0;printf("请输入被转化数:");scanf("%d", &n);int x = 0;printf("请输入想要转化成的进制:");scanf("%d", &x);itox(n,x);return 0;
}
还是由于可能会出现大写字母,所以我们定义一个全局的字符数组,存入一到九和A到Z。
以后我们就可以把这串代码当作一个模板,进制转化的时候直接套用就好了。
4.3、其他进制转其他进制
这个我们就可以把上面的两个代码改造一下,自己输入两个进制数,先将数转化成十进制数,再将十进制数转化为其他进制数:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<math.h>//不要忘记
char s[38] = "012345678910ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int ntoi(int n, char a[100])
{int len = strlen(a);int ret = 0;int j = 0;while (len--){if (a[len] < '9'){ret = ret + (a[len] - '0') * pow(n, j);j++;}else{ret = ret + (a[len] - 'A' + 10) * pow(n, j);j++;}}return ret;
}
void itox(int a,int x)
{if(a>=x){itox(a / x, x);//递归}printf("%c", s[a % x]);
}
int main()
{int n = 0;printf("请输入被转化数的进制:");scanf("%d", &n);char a[100] = "";printf("请输入被转化数:");scanf("%s",a);int x = 0;printf("请输入想要转化成的进制:");scanf("%d", &x);int ret=ntoi(n,a);//将a转化为十进制itox(ret,x);//将十进制的a转化为x进制return 0;
}
测试:


5、随机数生成技巧
现在我们用C语言实现随机数:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include<stdlib.h>//使用srand
int main()
{srand((unsigned int)time(NULL));printf("%d", rand()%10);return 0;
}
其实这个随机数理应是初学C语言时接触的,但是我给忘了哈哈,所以在这里再说一下,而且现在我们再看这个随机数生成操作其实是更好理解的。
首先先看srand:

我们应该把种子传入这个函数,但是如果种子不变的话数也是不变的啊!那有没有什么东西是一直改变的呢?没错,就是时间戳。
时间戳,是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数(不考虑闰秒),用于表示一个时间点。然而,这种格式对于人类阅读并不友好,因此需要转换成可读的日期和时间格式。
我们只需知道,时间戳是随着时间一直快速变化的,所以我们把它作为种子传入srand。又由于他的参数需要是unsigned int 类型的,所以我们强制转化一下。
接着调用rand(),我们想他有一个范围,就%这个范围的最大值可以了,比如如上代码是生成0~9范围的随机数。我们写成rand()%10+1就是1~10范围的随机数。
6、C/C++程序内存区域划分

C/C++程序内存分配的几个区域:
1. 栈区(stack):在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时 这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很⾼,但是分配的内 存容量有限。栈区主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等。
2. 堆区(heap):⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统) 回收。分配⽅式类似于链表。
3. 数据段(静态区):(static)存放全局变量、静态数据。程序结束后由系统释放。
4. 代码段:存放函数体(类成员函数和全局函数)的⼆进制代码。
好了,今天的内容就分享到这,我们下期再见!
相关文章:
编程之路,从0开始:补充篇
Hello大家好!很高兴和大家又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《题海拾贝》、《数据结构与算法之美》 欢迎点赞,关注! 这篇…...
使用缓存提升Web应用性能:从新手到高手的实践指南
引言 在现代Web开发中,性能优化是确保用户体验和系统稳定性的关键。使用缓存是提升网站性能的有效手段之一,可以显著减少数据库访问和计算开销。根据“网站优化第一定律”,缓存可以提升网站的响应速度,减少延迟,从而改…...
【数字电路与逻辑设计】实验一 序列检测器
文章总览:YuanDaiMa2048博客文章总览 【数字电路与逻辑设计】实验一 序列检测器 一、实验内容二、设计过程(一)作出状态图或状态表(二)状态化简(三)状态编码 三、源代码(一ÿ…...
运动模糊效果
1、运动模糊效果 运动模糊效果,是一种用于 模拟真实世界中快速移动物体产生的模糊现象 的图像处理技术,当一个物体以较高速度移动时,由于人眼或摄像机的曝光时间过长,该物体会在图像中留下模糊的运动轨迹。这种效果游戏、动画、电…...
养老护理员培训考试题库;免费题库;大风车题库
下载链接:大风车题库-文件 大风车题库网站:大风车题库 大风车excel(试题转excel):大风车excel...
Python-配置模块configparser使用指南
configparser 是 Python 标准库中的模块,用于处理配置文件(如 .ini 文件)。它适合管理程序的配置信息,比如数据库连接参数、应用程序设置等。 1. 配置文件的基本结构 配置文件通常是 .ini 格式,由 节(Sec…...
C++的HDF5库将h5图像转为tif格式:szip压缩的图像也可转换
本文介绍基于C 语言的hdf5库与gdal库,将.h5格式的多波段HDF5图像批量转换为.tif格式的方法;其中,本方法支持对szip压缩的HDF5图像(例如高分一号卫星遥感影像)加以转换。 将HDF5图像批量转换为.tif格式,在部…...
【JAVA】Java第十三节:String类(String相关方法,以及StrinBuftrer , StringBulder相关方法)
本文详细介绍了String类以及常用的String相关方法,以及StrinBuftrer , StringBulder相关方法的使用,建议有印象即可,不需要都记住,使用时去查取即可 一、创建一个String类型的变量 我们平时创建String类型的变量一般是第一种形式…...
WordPress安装或访问时出现数据库连接错误的处理方式
一、在安装时出现数据库连接错误 1、如果数据库名称、用户名或密码错误,或者主机设置不正确(如数据库服务器不是在本地localhost,而是在远程服务器,需要正确填写远程服务器的 IP 地址或域名),就会导致连接错…...
JAVA-面向对象基础
文章目录 概要封装多态抽象类接口内部类为什么需要内部类 概要 面向对象是一种编程范式或设计哲学,它将软件系统设计为由多个对象组成,这些对象通过特定的方式相互作用 封装 将数据和操作数据的方法封装在一个类中,并通过访问修饰符控制对…...
[Java]项目入门
这篇简单介绍一些入门的有关项目和行业的知识,并带着实现一个小项目。便于已经编程入门的各位准备进阶到下一个阶段。 先大致地介绍,一个完整的项目(不看客户端、服务端的分类)基本可以划分为三部分: 1.前端。比如你现在看到的CSDN页面就是一…...
opencv Mat To Heif
高效率图像文件格式(英语:High Efficiency Image File Format, HEIF;也称高效图像文件格式)是一个用于单张图像或图像序列的文件格式。它由运动图像专家组(MPEG)开发,并在MPEG-H Part 12&#x…...
二刷代码随想录第24天
93. 复原 IP 地址 确定函数is_ip的实现细节,start不能超过end,没有0开头的非0数字,每个字符都在0-9之间,每段字符小于255在原字符串s上做操作会更简单一些 class Solution { public:vector<string> result;vector<string> rest…...
Java设计模式之状态模式架构高扩展的订单状态管理
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…...
Yagmail邮件发送库:如何用Python实现自动化邮件营销?
目录 一、Yagmail简介 二、安装Yagmail 三、基本使用示例 1. 发送简单文本邮件 2. 发送HTML邮件 3. 发送带有附件的邮件 4. 多收件人处理 5. 自定义邮件头 四、高级功能 1. SMTP配置 2. 邮件模板 3. OAuth2认证 五、自动化邮件营销案例 六、错误处理和调试 七、…...
李宏毅深度学习-Pytorch Tutorial2
什么是张量? 张量(Tensor)是深度学习和机器学习中一个非常基础且重要的概念。在数学上,张量可以被看作是向量和矩阵的泛化。简单来说,张量是一种多维数组,它可以表示标量(0维)、向量…...
SaaS财务软件:赋能企业数字化转型
在数字化浪潮的推动下,企业财务管理正逐步迈向智能化、高效化的新阶段。在这个过程中,SaaS财务软件应运而生,成为许多企业的首选。以易舟云财务软件为例,这款软件不仅集成了众多先进的财务管理功能,而且在用户体验上做…...
FPGA实战篇(按键控制LDE实验)
1.按键简介 按键开关是一种电子开关,属于电子元器件类。我们的开发板上有两种按键开关:第一种是本实验所使用的轻触式按键开关,简称轻触开关。使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时开关断开ÿ…...
在Ubuntu-22.04 [WSL2]中配置Docker
文章目录 0. 进入Ubuntu-22.041. 更新系统软件包2. 安装Docker相关依赖包3. 添加Docker官方GPG密钥4. 添加Docker软件源5. 安装Docker Engine5.1 更新软件包列表5.2 安装Docker相关软件包 6. 验证Docker安装是否成功6.1 查看Docker版本信息6.2 启动Docker6.3 配置镜像加速器6.4…...
ACM:均分纸牌
主要思路 整体思路概述: 本题旨在解决给定N堆纸牌(纸牌总数是N的倍数),通过按照特定移牌规则移动纸牌,找出用最少移动次数使每堆纸牌数量相等的方法。程序采用了一种逐步调整的思路,先计算出每堆纸牌应有的…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...

