I.结构体的组成与运用
结构体有其基本的格式
我们举一个例子来看看
struct Lee
{
float height;
char sex[10];
float weight;
int tele;
};//这里的分号绝对不能忘掉!不能省略!
int main()
{
struct Lee s = {178,"male",80.1,14596238451};
printf("%f\n %s\n %f\n %d\n",s.height,s.sex,s.weight,s.tele);//调取结构体的时候必须靠名加.加属性
return 0;
}
我们看到这段代码有两部分
一部分是主函数
另一部分就是一个名为“Lee”的结构体代码
我们看到Lee后面并没有跟随小括号
这说明结构体是不用像函数那样
先获取数据,再进行计算
结构体的大括号里存在的只有属性
并不带有任何实际的数据
那我们如果要用它
就要自己补一块数据进去了
于是我们可以在主函数里看到我们的给结构体赋值了
你可能会问:s是什么?
告诉你,s其实才是结构体的真实名字
没错,我之前说Lee是结构体的名字
其实这个说法只是先让大家理解结构体
但实际上它并不是结构体的名字
那它算什么?
准确地说
Struct Lee其实更像一种类型的名字
而不是结构体的名字
我们相当于给包含“height sex weight tele”的东西给划了一类
这一类就被我们定位为“struct Lee”这一类型
而struct Lee s的意思自然就是:一个叫s的代码块,其属于struct Lee这一类
struct Lee s就成为了有赋值的一个模块
需要注意的是调取结构体的格式:(结构体的名字).(属性名字)
还有就是结构体的大括号后面跟着个分号
我们来看看另一段代码
struct Lee
{
float height;
char sex[10];
float weight;
int tele;
};
void print(struct Lee* ps)
{
printf("%f\n %s\n %f\n %d\n", (*ps).height, (*ps).sex, (*ps).weight, (*ps).weight);//这里的(*ps).可以替换成ps->。
}
int main()
{
struct Lee s = { 178,"male",80.1,14596238451 };
print(&s);
return 0;
}
它稍显复杂
但理是一样的
struct Lee的部分就不多做介绍
看看主函数干了什么
先是给一个结构体(s)赋值
然后是给print(注意不是printf)这个函数赋予了结构体s的地址这个参数
然后我们再来看看print这个函数块
它的参数是给一个叫ps的指针结构体
所以我们可以看到主函数中给print的是&s,而不是s
后面的用法也就如出一辙了
II.while语法
while的执行条件与if是相似的
都是小括号内为真就会执行
这里主要讲一下continue、break、getchar、putchar
I.continue与break
我们来看段代码
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
{
continue;
}//continue是跳过该种循环的后续步骤,然后继续下一次循环。如果这是break,则是终止整个循环。
printf("%d\n", i);
i++;
}
return 0;
}
这里while要循环
只需要i不大于10就可以了
而i++;则保障了while不会陷入死循环
这里面着重看一下continue;这行代码
它虽然是在if的大括号里
但它的功能并没有被局限住
它的作用就是跳过本次循环的后续步骤
也就是说虽然if的大括号外面还有两行代码
但它们并不会执行
而是直接开启了下一轮的循环
但这样就跳过了i++;了
我们说了i++;就是为了避免i的值不变
而造成一直都在死循环的局面
continue跳过了这一步骤
因此该段代码会陷入死循环
而如果把这里的continue换成break
则不是一回事了
break是终止该循环
不是中止,而是终止
这就意味着该循环结束了
该循环不会进入下一个循环了
II.getchar与putchar
getchar的特点是它也具备输入的功能
它会像scanf一样需要我们输入
但它的特点是一次只读取一个字符
比方说我们输入12569
那它只会读取首位的1
不过需要额外注意的是
getchar还会读取\n
我们在理解这些之前
需要给大家讲一下缓冲区的概念
I.缓冲区
我们可以将我们的输入想象为三个领域
一个是读取区
一个是缓冲区
一个是我们的键盘
我们的代码区里的读取功能代码
比方说scanf和getchar
都会要求我们输入
这时候我们就会通过键盘打数据
这些数据就会堆在缓冲区
那这会有什么问题呢?
我们知道scanf要求我们输入后
我们是不用打换行的
因为它自动带有换行的属性
当我们输入1234567的时候
事实是输入了1234567\n
只不过\n被隐藏起来了
那假如我们先用scanf
再用printf
那么printf自然将1234567给拿走了
这时缓冲区就会留下来这个隐形的\n
而这个时候轮到getchar
我们假如输入abcde
由于它一次只读取一个字符
原本我们想它读取走a
结果因为残留的\n
它就会读取走\n
这明显就不是我们想要的了
读取区 | 缓冲区 | 键盘 |
scanf printf getchar |
1234567\n abcde | (输入数据) |
那缓冲区有没有什么办法来应付呢?
也是有办法的
int main()
{
char pasw[20] = {0};
printf("请输入密码:");
scanf("%s", pasw);
printf("请确认密码(Y/N):");
getchar();
int ensure = getchar();
if ('Y' == ensure)
{
printf("密码正确");
}
if ('N' == ensure)
{
printf("密码错误");
}
return 0;
}
这段代码我们看到getchar();就可以了
我们这里使用的就是加一行getchar来将那残留的\n吃掉
但这其实是一种比较差劲的代码
因为假如我们的scanf输入的不是123456
而是123 456呢?
由于scanf我们是说要的%d类型
当scanf看到空格后
它就会不读取了
那结果就是会剩下456\n
那有没有更好的办法?
有的
int main()
{
char pasw[20] = {0};
printf("请输入密码:");
scanf("%s", pasw);
printf("请确认密码(Y/N):");
while ('\n' != getchar() && c != EOF)
{
;
}
int ensure = getchar();
if ('Y' == ensure)
{
printf("密码正确");
}
if ('N' == ensure)
{
printf("密码错误");
}
return 0;
}
当我们利用这个while循环的时候
我们就可以一直循环用getchar读取
直到把\n吃掉
这样就不会影响到后续的getchar读取了
这种方式就是为了清空缓冲区
II.putchar
相信经过之前的解释
你已经知道了缓冲区的概念的getchar的功能
那我们来看看putchar的功能是什么
int main()
{
int ch = getchar();
putchar(ch)
return 0;
}
这段代码很简短
就是将getchar读取到的字符存到ch里面
然后putchar的作用就是把存在ch里面的数据输出出来
起到一个类似printf的作用
但我们一定不要误以为getchar和putchar是要捆绑起来用的
其实putchar是可以独立于getchar的
假如我们不写getchar
而直接给ch赋予一个值
那么putchar(ch)也是能够输出这个值的