一、getchar()和putchar(变量)
简介
getchar()
- 读取字符,getchar()的功能最主要是c语言中读取字符的一个函数,能够提取单个字符;
- 输入单个字符,getchar()的功能还可以从键盘中输入一个单个的字符,并且把单个的字符输入到计算机中;
- 返回值是char类型,可以返回int类型的值(ascii码值);
- 如果读取错误或文件结束就会返回EOF(其值为-1)(全称为end of file)。
putchar(变量)
输出变量对应的字符
实际应用
#include<stdio.h>
void main()
{
char ch;
int i = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch);
++i;
}
printf("%d", i);
}
手动档
利用while循环可以输入多个字符并且完全输出,但需要通过Ctrl+z来手动结束循环
注:输出完所有字符后会再跑一遍循环输出'\n'字符,或者说回车就是'\n',因此i=字符数+1
自动档
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void main()
{
char ch;
int i = 0;
while ((ch = getchar()) != EOF)
{
if (ch == '\n')
break;
//等到'\n'字符出现后自动跳出循环
putchar(ch);
++i;
}
printf("\n循环次数%d", i);
}
常见问题(scanf与getchar()并用)
现象
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void main()
{
char ch;
char password[20];
printf("请输入密码:>");
scanf("%s", password);
//数组和字符串名称本身就是地址,在scanf函数中不需要加&再来取地址
printf("确认密码是否正确(Y/N):>");
ch = getchar();
if (ch == 'Y')
printf("密码正确!");
else
printf("密码错误!");
}
//会出现输入密码后未经(Y/N)判断就直接出现密码错误
分析
回车等同于\n,当scanf函数读取到\n时就会讲将123456全部取走,但\n会留在缓冲区内,而后getchar()函数就会直接取走留在缓冲区内的\n,从而直接结束读取给ch赋值'\n',进而密码错误。
初级改进
再建立一个缓存区垃圾桶(利用再一个getchar()函数来清理掉缓冲区)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void main()
{
char ch;
char password[20];
printf("请输入密码:>");
scanf("%s", password);
getchar();//清理缓冲区
//清除了字符'\n'
printf("确认密码是否正确(Y/N):>");
ch = getchar();
if (ch == 'Y')
printf("密码正确!");
else
printf("密码错误!");
}
不足之处
注:C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束
由于空格使得scanf只取走了缓冲区内的2345,但又因为getchar()函数只能取走一个字符,所以未能清理完缓冲区
优化改进
1.scanf函数换成gets等函数可以读取空格
2.while结合
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void main()
{
char ch;
char password[20]={0};
int tmp;//垃圾桶
printf("请输入密码:>");
scanf("%s", password);
while ((tmp = getchar()) != EOF)//清理缓冲区(垃圾桶)
{
if (tmp == '\n')
break;
//可自动打破while循环,不需要按Ctrl+z来打破while循环(注:vs2022使用情况下)
}
printf("确认密码是否正确(Y/N):>");
ch = getchar();
if (ch == 'Y')
printf("密码正确!");
else
printf("密码错误!");
}
二、利用time()、srand()、rand()函数进行伪随机
函数需要的头文件
time()函数------------------------------>time.h
srand()、rand()函数----------------->stdlib.h
rand()函数
rand()函数原型:int rand(void)
rand()函数用来产生随机数,但是,rand()的内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的。
由于每次运行的程序卡着周期时间相等,因此在重新运行程序时会得到相同的随机值。
rand()会返回一个范围在0到RAND_MAX(32767)之间的伪随机数(整数)。
rand() % (n-m+1)+m
//表示[m , n]范围内的随机数生成
rand() % (n+1)
//表示生成[0,n]范围内的随机数生成
srand()函数
srand()函数原型:void srand(unsigned int seed)
注:要无符号整型,可通过(unsigned int)来进行强制转换
srand();
rand() % (n-m-1)+m;
srand()用来设置rand()产生随机数时的随机数种子。参数seed是整数,通常可以利用time(0)或geypid(0)的返回值作为seed。(种子=随机数整个周期起点)
由于要使rand()每次运行程序都会有新的随机值,所以种子也要在每次重新运行程序时进行更换,来避免由于种子相同而导致的相同周期的某时刻随机值相等。
time()函数
time()函数返回一个包含当前时间的 Unix 时间戳的整数(long int类型)
如果t是空指针,直接返回当前时间。如果t不是空指针,返回当前时间的同时,将返回值赋予t指向的内存空间。
srand((unsigned int)time(NULL));
rand() % (n-m+1)+m;
获取当前的系统时间,返回值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。
c语言调用time()函数括号里为什么要用NULL?
time是这样声明的:time_ttime(time_t*timer)。
用法是你先自己定义一个time_t变量,让后把变量的地址传给它。函数会返回自1970年1月1日0点走过的秒数,同时把这个返回值保存在你传进来的那个time_t*指向的变量里面。
如果你传进来NULL的话,就不保存。
通过利用时间戳生成的数字来当种子,使种子随系统时间不断变化。
由于程序进行过快,会导致非常短的时间内时间戳不再变化,但可以通过挪动程序位置来避免。
example
assert断言判断
示例
#include<stdio.h>
#include<assert.h>
void my_strcpy(const char* arr1, char* arr2)
{
//利用const避免arr1字符串被修改
assert(arr1 != NULL);
assert(arr2 != NULL);
//利用assert函数可以明确出问题的位置
while (*arr2 != '\0')
{
*arr2++ = *arr1++;
}
*arr2 = *arr1;
for (; *arr2++ = *arr1++;);
//\0的ASCII值为0
}
void main()
{
char arr1[] = "Hello World";
char arr2[] = "******************";
my_strcpy(arr1, NULL);
printf("%s", arr2);
}
eg:若传入空指针,可以迅速发现问题所在行列
原理
若条件成立,为真正常运行;若条件不满足,为假直接打断进程。
调试快捷键
F5----直接跳到断点位置
F9----放置断点/取消断点
F10----逐过程(会跳过所引用的函数)
F11----逐语句(可以进入函数内部)