diff --git a/.gitignore b/.gitignore index 4df5985..298a66d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ !**/*.md !**/makefile !**/Makefile +!**/*.csv diff --git a/C13-Linux系统编程/C13-Linux系统编程学习笔记.md b/C13-Linux系统编程/C13-Linux系统编程学习笔记.md index 1f6176b..d2a10e9 100644 --- a/C13-Linux系统编程/C13-Linux系统编程学习笔记.md +++ b/C13-Linux系统编程/C13-Linux系统编程学习笔记.md @@ -33,8 +33,8 @@ FILE *fopen(const char *path, const char *mode); */ int fclose(FILE *fp); -int fputc(FILE *stream); -int fgetc(int c, FILE *stream); +int fputc(int c, FILE *stream); +int fgetc(FILE *stream); char *fgets(char *s, int size, FILE *stream); /** @@ -64,8 +64,6 @@ int printf(const char *restrict format, ...); * 常用于 fprintf(stderr,...) */ int fprintf(FILE *restrict stream, const char *restrict format, ...); - -// TODO: int dprintf(int fd, const char *restrict format, ...); /** @@ -146,9 +144,10 @@ fflush(); /** * @prarm: mode - * _IONBF - * _IOLBF - * _IOFBF + * 三种缓冲模式: + * _IONBF + * _IOLBF + * _IOFBF */ int setvbuf(FILE *stream, char *buf, int mode, size_t size); @@ -200,13 +199,40 @@ FILE *tmpfile(void); - write - lsee +可以使用`./open file &`来后台运行一个程序。 +然后通过`ps`查看进程号 +然后进入`/proc/进程号/fd`查看文件描述符 +前三个是标准输入输出错误,后面的是打开的文件描述符 + ```c /** + * flag: + * * r -> O_RDONLY * r+ -> O_RDWR * w -> O_WRONLY | O_CREAT | O_TRUNC * w+ -> O_RDWR | O_TRUNC | O_CREAT + * + * O_RDONLY 只读 + * O_WRONLY 只写 + * O_RDWR 读写 + * O_CREAT 创建 + * O_TRUNC 截断 + * O_APPEND 追加 + * O_EXCL 排他(若要创建的文件已存在则报错) + * O_NONBLOCK 非阻塞 + * O_SYNC 同步 + * O_DSYNC 数据同步 + * O_RSYNC 读同步 + * O_DIRECT 直接IO + * O_LARGEFILE 大文件 + * O_DIRECTORY 目录 + * O_NOFOLLOW 不跟踪符号链接 + * O_CLOEXEC close-on-exec + * O_PATH 仅打开目录 + * O_TMPFILE 临时文件 + * O_NOCTTY 不分配控制终端 * * 如果有creat就必须用三参数的形式 * C语言没有重载,这是变参函数 @@ -214,6 +240,7 @@ FILE *tmpfile(void); * @prarm: pathname 文件路径 * @prarm: flags 文件打开方式 * @prarm: mode 文件权限 + * 假如0666,就是rw-rw-rw-,110110110 * */ int open(const char *pathname, int flags); @@ -222,14 +249,12 @@ int open(const char *pathname, int flags, mode_t mode); int close(int fd); /** - * read from a file descriptor - * * @return 读取的字节数,失败返回-1 */ ssize_t read(int fd, void *buf, size_t count); /** - * write to a file descriptor + * 想要控制写入的位置,需要使用lseek * * @return 写入的字节数,失败返回-1 */ @@ -248,6 +273,16 @@ off_t lseek(int fd, offt offset, int whence); ``` +### 例题:通过文件IO处理csv表格 +```csv +,语文,数学,英语,总分,评价 +张三,90,91,92,, +李四,80,81,82,, +王五,70,71,72,, +``` +思路:逐行处理 +可以使用16进制查看工具 + ### 文件IO与标准IO的区别 区别:响应速度&吞吐量 diff --git a/C13-Linux系统编程/fs/W_process_excel.c b/C13-Linux系统编程/fs/W_process_excel.c new file mode 100644 index 0000000..7b8fc5c --- /dev/null +++ b/C13-Linux系统编程/fs/W_process_excel.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include + +#if 1 +# define debug(fmt, args...) printf(fmt, ##args) +#else +# define debug(fmt, args...) +#endif + +/** + * @brief 读取一行 + * @details + * 循环读入一个字符 + * 如何判断读完一行? 读到0x0d, 0x0a + * + * @param fd + * @param buf + * + * @return int 读到的一行数据的数据个数( n>=0 ) + * -1: 读到文件尾部或者出错 + */ +static int read_line(int fd, unsigned char *buf) +{ + unsigned char c; + int len; + int i = 0; + int err = 0; + + while (1) + { + len = read(fd, &c, 1); + if (len <= 0) + { + err = -1; + break; + } + else + { + if (c != '\n' && c != '\r') + { + buf[i] = c; + i++; + } + else /* 碰到回车换行 */ + { + err = 0; + break; + } + } + } + + buf[i] = '\0'; + + if (err && (0 == i)) + /* 读到文件尾部且无有效数据 */ + return -1; + else + return i; +} + +/** + * @brief 处理一行的数据, 计算出总分和评价 + * @details + * + * @param data_buf + * @param result_buf + * + * @return int + */ +static void process_data(unsigned char *data_buf, unsigned char *result_buf) +{ + /** + * eg1: data_buf=",语文,数学,英语,总分,评价" + * result_buf=",语文,数学,英语,总分,评价" + * + * eg2: data_buf="张三,90,91,92,," + * result_buf="张三,90,91,92,273,A+" + * + */ + + char name[100]; + int scores[3]; + int sum; + char *levels[] = {"A+", "A", "B"}; + int level; + + // debug("data_buf[0]: %x\n", data_buf[0]); + if (0xef == data_buf[0]) /* 对于UTF-8, 前三个字符是0xef 0xbb 0xbf */ + { + strcpy(result_buf, data_buf); + } + else + { + // debug("data_buf: %s\n", data_buf); + // debug("进入了\n"); + /** + * @brief 从字符串得到数据 + * @details + * 拆分信息: scanf分隔符 + * %[^,]: 读数据直到碰到逗号 + * + */ + sscanf(data_buf, + "%[^,],%d,%d,%d,,", + name, + &scores[0], + &scores[1], + &scores[2]); + + debug("name: %s, scores: %d, %d, %d\n", + name, + scores[0], + scores[1], + scores[2]); + + sum = scores[0] + scores[1] + scores[2]; + if (sum >= 270) + level = 0; + else if (sum >= 240) + level = 1; + else + level = 2; + + sprintf(result_buf, + "%s,%d,%d,%d,%d,%s", + name, + scores[0], + scores[1], + scores[2], + sum, + levels[level]); + } +} + + +/** + * @brief 处理csv表格 + * @details + * Usage: ./W_process_excel data.csv result.csv + * + * @param argc + * @param argv + * + * @return int + */ +int main(int argc, char **argv) +{ + int fd_data, fd_result; + int len; + unsigned char data_buf[1000]; + unsigned char result_buf[1000]; + + if (argc != 3) + { + printf("Usage: %s data.csv result.csv\n", argv[0]); + exit(1); + } + + fd_data = open(argv[1], O_RDONLY); + if (fd_data < 0) + { + perror("open data.csv"); + exit(1); + } + else + printf("data file fd: %d\n", fd_data); + + fd_result = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd_result < 0) + { + perror("open result.csv"); + exit(1); + } + else + printf("result file fd: %d\n", fd_result); + + while (1) + { + /* 读取1行 */ + len = read_line(fd_data, data_buf); + if (-1 == len) + break; + + // if (len != 0) + // debug("%s\n\r", data_buf); + + if (len != 0) + { + /* 处理1行 */ + process_data(data_buf, result_buf); + + /* 写入结果文件 */ + write(fd_result, result_buf, strlen(result_buf)); + write(fd_result, "\r\n", 2); + } + } + + close(fd_data); + close(fd_result); + + exit(0); +} \ No newline at end of file diff --git a/C13-Linux系统编程/fs/data.csv b/C13-Linux系统编程/fs/data.csv new file mode 100644 index 0000000..a94a31c --- /dev/null +++ b/C13-Linux系统编程/fs/data.csv @@ -0,0 +1,4 @@ +,语文,数学,英语,总分,评价 +张三,90,91,92,, +李四,80,81,82,, +王五,70,71,72,, diff --git a/C13-Linux系统编程/fs/result.csv b/C13-Linux系统编程/fs/result.csv new file mode 100644 index 0000000..51a17f8 --- /dev/null +++ b/C13-Linux系统编程/fs/result.csv @@ -0,0 +1,4 @@ +,语文,数学,英语,总分,评价 +张三,90,91,92,273,A+ +李四,80,81,82,243,A +王五,70,71,72,213,B diff --git a/README.md b/README.md index f286570..e1676da 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,15 @@ # Linux-C-Notes Linux环境C语言开发学习笔记 ## 课程地址 + +主要是李慧芹老师的课程,讲的比较清晰。同时韦东山老师的课,讲的比较杂和跳跃,正好把知识点作为补充。 +韦东山课程的代码以"W"开头来命名。 + [史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV18p4y167Md/?spm_id_from=333.999.0.0&vd_source=4e03f52e94cfa281cde032856b1f93a7) +[【第4篇】嵌入式Linux应用开发基础知识_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1kk4y117Tu/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=4e03f52e94cfa281cde032856b1f93a7) + + ## 本仓库内容 教学过程中所有的课程笔记和代码示例。