2020.01.12-2020.01.18

2020.1.12-2020.1.18


1.scanf、getchar、getch、getche和缓冲区

https://cloud.tencent.com/developer/article/1354983
https://www.cnblogs.com/lanhaicode/p/10575049.html

读取字符时:
(1)scanf()以 Enter 结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
(2)getchar()以 Enter 结束输入,不会舍弃最后的回车符。
读取字符串时:
(1) scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符;
(2) gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
所以读取一个字符串中的每一个字符的时候,往往使用getchar()而不使用scanf(),因为一个字符串中是会出现空格的。如果使用scanf()会造成将一个字符串首先读入第一个空格前的部分,其余部分会残留在输入缓冲区的情况,在下次读取时可能会出现错误。
其次为了避免出现上述问题,必须要在读取输入前,清空缓冲区的残留数据

缓冲区是一块内存空间,用来缓存数据,目的是让快速的cpu不必等待慢速的输入输出设备,同时减少操作硬件的次数

根据数据刷新的时机可将缓冲区类型分为
1.全缓冲:当缓冲区被填满以后才进行真正的输入输出操作
2.行缓冲:当输入或输出时遇到换行符时才进行真正的输入输出操作
3.无缓冲:没有缓冲区,立即进行输入输出

Windows下c语言的printf是无缓冲的

2.洛谷

1.P1597-语句解析

在这里插入图片描述
没有啥思路就看题解了
因为scanf成功读入一个返回值为1,读入两个返回值为2,可以此作为循环条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
int main() {
int a[3];
char c1,c2;
while(scanf("%c:=%c;",&c1,&c2)==2) {
if(c2>'0'&&c2<'a'){
a[c1-'a']=c2-'0';
}
else{
a[c1-'a']=a[c2-'a'];
}
}
printf("%d %d %d",a[0],a[1],a[2]);
// char a=14;
// int b;
// b=a;
// printf("%d",b);
return 0;
}
2.P1739-表达式括号匹配

在这里插入图片描述
第一次提交了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
int main(){
char b;
int i=0,j=0;
while(1){
scanf("%c",&b);
if(b=='@')
break;
if(b=='(')
i++;
if(b==')')
j++;
}
if(j==i)
printf("YES");
else
printf("NO");
return 0;
}

没考虑到右括号在左括号旁边的情况 如:)(a+1)*(a+2)(@
看了一下题解:
每出现一个左括号+1,每出现一个右括号且该变量大于0时-1.最后整个字符串判断完之后如果这个变量值为0则原表达式是匹配的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
while(1){
scanf("%c",&b);
if(b=='@')
break;
if(b=='('){
i++;
c++;
}

if(b==')'){
j++;
if(c>0)
c--;
}
}
if(j==i&&c==0)
printf("YES");
else
printf("NO");
return 0;

通过了

3.汇编语言学习

栈段

栈顶的变化范围是0~ffff,栈空时sp=0,栈满时sp也=0,一个栈容量最大为64kb
执行修改栈段寄存器ss的指令时,下一条指令也紧接着被执行
如 用t命令执行 mov ss,ax时,下一条mov sp,10也紧接着执行了

一个源程序从写出到执行的过程
  1. 编写汇编源程序,产生了一个存储源程序的文本文件
  2. 用汇编语言编译程序编译源程序,产生目标文件,再用连接程序对目标文件进行连接,生成可执行文件
    可执行文件包1.含程序(机器码)和数据,2.相关描述信息,如程序有多大,要占用多少内存空间等
  3. 执行可执行文件中的程序
源程序

例:

1
2
3
4
5
6
7
8
9
10
11
12
assume cs:codesg
codesg segment
mov ax,0123
mov bx,0456
add ax,bx
add ax,ax

mov ax,4c00
int 21

codesg ends
end
  1. 伪指令
    1。xxx segment\n····\nxxx ends
    是必须使用到的一对伪指令,功能是定义一个段,xxx是段名
    一个汇编程序是由多个段组成的,这些段被用来存放代码/数据/当作栈空间用
    一个汇编程序中至少要有一个段用来存放代码
    段名(xxx)最终将被处理为一个段的段地址
    2。end
    是一个汇编程序的结束标记
    3。assume
    假设某一段寄存器和程序中的某一个用 segment…ends定义的段相关联,如例中段codesg和cpu中的段寄存器cs联系起来
[bx]和loop指令
  1. [bx]
    要完整地描述一个内存单元,需要两种信息:1。内存单元的地址;2.内存单元的长度(类型)(有多大)
    mov al(ax),[bx] :
    将一个内存单元的内容送入al(ax),这个内存单元的长度为1(2)字节,存放一个字节(一个字),偏移地址在bx中,段地址在ds中。
  2. loop
    用loop指令实现循环功能,cx中存放循环次数
    执行loop指令的时候,1.(cx)=(cx)-1 ; 2.判断(cx),不为零则转至标号处执行程序,如果为零则向下执行
    `` 例:计算2^12
1
2
3
4
5
6
7
8
9
10
11
12
assume cs:code
code segment
mov ax,2

mov cx,11
s: add ax,ax
loop s

mov ax,4c00h
int 21h
code ends
end