第四次上机题目及参考代码.docx
#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include<stdlib.h> #include <sys/ioctl.h> #include <sys/soundcard.h> #include <termios.h> #include <unistd.h> int kbhit(void) { struct termios oldt, newt; int ch; int oldf; tcgetattr(STDIN_FILENO, &oldt;); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW,&newt;); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf |O_NONBLOCK); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW,&oldt;); fcntl(STDIN_FILENO, F_SETFL, oldf); if(ch != EOF) { ungetc(ch, stdin); return 1; } return 0; } int main(int argc,char **argv) { char *buf=malloc(1024); int fd=open(argv[1],O_RDONLY|O_CREAT|O_APPEND,0666); int fd1=open(argv[2],O_WRONLY|O_CREAT|O_APPEND,0666); printf("%d,%d\n",fd,fd1); int du=1; while(du>0) { while(kbhit()) { switch(getchar()) { case '1':lseek(fd,1000000,SEEK_CUR);break; case '2':lseek(fd,-1000000,SEEK_CUR);break; default:break; } break; } du=read(fd,buf,50); int fmt=AFMT_S16_LE,channels=2,speed=44100; ioctl(fd1,SNDCTL_DSP_SETFMT,&fmt;); ioctl(fd1,SNDCTL_DSP_CHANNELS,&channels;); ioctl(fd1,SNDCTL_DSP_SPEED,&speed;); int xie=write(fd1,buf,du); printf("%d %d ",du,xie); } close(fd); close(fd1); return 0; 【知识点详解】 此段代码是C++编程语言的实现,主要涉及了标准输入输出、文件操作、非阻塞I/O以及音频设备控制等概念。以下是这些知识点的详细说明: 1. **非阻塞I/O(Non-blocking I/O)**: - `kbhit()` 函数检查是否有键盘输入,如果存在则不等待直接返回,否则立即返回0。在C++中,这个功能通常是通过修改终端属性来实现的。 - `fcntl()` 函数用于设置文件描述符的标志,`F_GETFL` 获取当前标志,`F_SETFL` 设置新的标志。`O_NONBLOCK` 标志将文件描述符设置为非阻塞模式,使得`getchar()`在没有输入时不会阻塞等待。 2. **文件操作**: - `open()` 函数打开文件,参数包括文件路径、打开模式和权限。在这个例子中,`O_RDONLY`表示只读,`O_CREAT`表示如果文件不存在则创建,`O_APPEND`表示追加写入。 - `lseek()` 函数改变文件指针的位置,`SEEK_CUR`表示相对当前位置移动。 3. **音频设备控制**: - `ioctl()` 函数用于控制设备,这里主要用于设置音频设备的格式和参数。`SNDCTL_DSP_SETFMT`设置音频格式,`AFMT_S16_LE`表示16位小端格式;`SNDCTL_DSP_CHANNELS`设置通道数,`SNDCTL_DSP_SPEED`设置采样率。 4. **I/O流**: - `read()` 从文件描述符中读取数据到缓冲区,返回实际读取的字节数。 - `write()` 将缓冲区的数据写入文件描述符,返回实际写入的字节数。 5. **内存管理**: - `malloc()` 动态分配内存,用于创建缓冲区`buf`来存储读取的数据。 6. **错误处理与资源释放**: - 代码中没有显示的错误处理,例如检查`open()`、`read()`、`write()`等函数的返回值,这在实际编程中是必要的。 - 使用`close()`函数关闭文件描述符,释放资源。 7. **结构化程序设计**: - `switch`语句用于根据用户输入执行不同的操作,如在文件指针处移动。 - 循环结构 (`while`) 用于持续读取和处理文件,直到没有更多数据可读。 8. **函数使用**: - `tcgetattr()` 和 `tcsetattr()` 用于获取和设置终端属性,这里用于实现非阻塞键盘输入。 9. **友元函数与类设计**: - 虽然这个代码中没有体现,但题目中提到了友元函数 `Total`,它能访问不同银行类的私有数据成员 `balance` 来计算总存款,这是面向对象编程中的一个重要特性。 10. **静态成员**: - 题目中提到的`Score`类的静态成员 `sum` 和 `getSum()`,`sum` 存储所有对象的总分,`getSum()` 返回这个总分,这体现了静态成员在类级别的共享状态和功能。 这段代码展示了C++中非阻塞I/O、文件操作、音频设备控制以及基本的结构化编程技巧,同时也引出了面向对象编程中的类设计和静态成员的概念。