网站怎么优化排名,网站seo顾问,做疏通什么网站推广好,360网站seo怎么做Hello大家好#xff01;很高兴和大家又见面啦#xff01;给生活添点passion#xff0c;开始今天的编程之路#xff01; 我的博客#xff1a;但凡. 我的专栏#xff1a;《编程之路》、《题海拾贝》、《数据结构与算法之美》 欢迎点赞#xff0c;关注#xff01; 这篇… 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
#includestdio.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 fghscanf只能接收到asd剩下的空格和fgh以及我们输入的\n回车他都放入了缓冲区。然后执行gets时我们不用输入gets直接从缓冲区读取这些内容然后打印出来。
1.1输入带有空格的字符串 我们可以用gets函数输入字符串
#includestdio.h
int main()
{char p[100] ;gets(p);printf(%s,p);return 0;
} 那么我们如何让scanf也能输出含有空格的字符串呢我们可以这样写
#define _CRT_SECURE_NO_WARNINGS
#includestdio.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标准输入流
#includestdio.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负数取模 不知道大家想过没有一个负数取模结果是正数还是负数呢
#includestdio.h
int main()
{int a -10;printf(%d,a%3);return 0;
}
输出结果 很明显负数取模结果是负数。那么问题又来了如果我让10%-3呢
输出结果 经过我们实验可以知道负数也是支持取模的但是负数求模结果的正负号由第⼀个运算数操作数的正负号决定。
2.2取模运算的应用
我们可以写一个程序判断一个数是奇数还是偶数
#define _CRT_SECURE_NO_WARNINGS
#includestdio.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
#includestdio.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 是一个宏用于在运行时检查一个条件是否为真如果条件不满足则运行时将终止程序的执行并输出一条错误信息。
在使用时我们需要包含头文件
#includeassert.h
它常用于判断一个地址为不为空或一个数是不是0。
#define _CRT_SECURE_NO_WARNINGS
#includestdio.h
#includeassert.h
#includestdlib.h
int main()
{int* p NULL;assert(p);return 0;
}
结果 4、进制转化 常见的进制有二进制八进制十进制十六进制...那么这些进制之间如何转化呢
4.1其他进制转十进制
· 其实我们数字的每一位都有自己的权重。比方说十进制123就等一1*10^22*10^11*10^0。
我们可以利用这个方法将二进制转化为十进制
比如101转化为十进制就是1*2^20*2^11*2^05。 同样的道理我们也可以把八进制和十六进制转化为十进制。 现在我们来写一个程序将x进制转化为十进制
#define _CRT_SECURE_NO_WARNINGS
#includestdio.h
#includestring.h
#includemath.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){retret(s[len] - 0)* pow(x,j);//当操作数为数字时j;}else{retret (s[len] - A10) * pow(x, j);//当操作数为字母时j;}}printf(%d, ret);return 0;
}
输出结果 当大于十进制时被转化的数中就会含有ABC这样的大写字母所以我们在进行计算时要分情况讨论。另外当进制大于36时输入错误因为最大就10加二十六个字母也就是说最大进制就是36除非他用其他的字符继续表示。 在c中我们可以对stoi函数进行改造使他支持进制转换。当然这里只是拓展一下想了解的朋友自行了解哈~
4.2十进制转其他进制 我们这里那十进制转二进制举例 注画的很丑请见谅~ 其实就是让这个十进制数除以想要转化的进制记录余数然后再那除完的结果继续去除......但需要注意的是这些余数我们需要从下往上写对应上图。
所以我们就可以用递归的思想实现这个代码
#define _CRT_SECURE_NO_WARNINGS
#includestdio.h
#includestring.h
char s[38] 012345678910ABCDEFGHIJKLMNOPQRSTUVWXYZ;
void itox(int n,int x)
{if(nx){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
#includestdio.h
#includestring.h
#includemath.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(ax){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 retntoi(n,a);//将a转化为十进制itox(ret,x);//将十进制的a转化为x进制return 0;
}
测试 5、随机数生成技巧 现在我们用C语言实现随机数
#define _CRT_SECURE_NO_WARNINGS
#includestdio.h
#includetime.h
#includestdlib.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()%101就是1~10范围的随机数。
6、C/C程序内存区域划分 C/C程序内存分配的几个区域 1. 栈区stack在执⾏函数时函数内局部变量的存储单元都可以在栈上创建函数执⾏结束时 这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中效率很⾼但是分配的内 存容量有限。栈区主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等。 2. 堆区heap⼀般由程序员分配释放若程序员不释放程序结束时可能由OS操作系统 回收。分配⽅式类似于链表。 3. 数据段静态区static存放全局变量、静态数据。程序结束后由系统释放。 4. 代码段存放函数体类成员函数和全局函数的⼆进制代码。
好了今天的内容就分享到这我们下期再见