c语言学习笔记9

一、getchar()和putchar(变量)

简介

getchar()

  1. 读取字符,getchar()的功能最主要是c语言中读取字符的一个函数,能够提取单个字符;
  2. 输入单个字符,getchar()的功能还可以从键盘中输入一个单个的字符,并且把单个的字符输入到计算机中;
  3. 返回值是char类型,可以返回int类型的值(ascii码值);
  4. 如果读取错误或文件结束就会返回EOF(其值为-1)(全称为end of file)。

putchar(变量)

输出变量对应的字符

实际应用

正常情况下file输入进去只有f输出
#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?

  1. time是这样声明的:time_ttime(time_t*timer)。

  2. 用法是你先自己定义一个time_t变量,让后把变量的地址传给它。函数会返回自1970年1月1日0点走过的秒数,同时把这个返回值保存在你传进来的那个time_t*指向的变量里面。

  3. 如果你传进来NULL的话,就不保存。

通过利用时间戳生成的数字来当种子,使种子随系统时间不断变化。

由于程序进行过快,会导致非常短的时间内时间戳不再变化,但可以通过挪动程序位置来避免。

example

伪随机的猜数游戏_HS-Cai的博客-CSDN博客利用time()、srand()、rand()函数伪随机的猜数游戏https://blog.csdn.net/qq947467490/article/details/126918972

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----逐语句(可以进入函数内部)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值