C_输入与输出 缓冲区缓冲区cpu会一条条执行指令当执行到scanf和printf指令就需要往外部设备输出或倒输入数据而cpu速度非常快外部设备速度更不上就会导致拖累Cpu速度。为了解决这个问题设立了缓冲区。这个缓冲区位置在内存中。现在CPU往外部设备输出数据不用直接而是先往缓冲区内存里面输出等到合适时间在输出到外部设备缓冲区可分为三种满缓冲区当缓冲区满的时候数据才会刷新到目的地。行缓冲区printf就是行缓冲区。如果在不影响业务逻辑下建议printf加\n无缓冲区stderr就是无缓冲区面试题缓冲区的作用平衡速度的差异。一方速度快一方速度慢可以加缓冲区平衡两者的速度差异。扩展Cpu的内部组成里面有一个叫做Register内部寄存器cpu的内存速度差异Register内存外部设备计算机采取读数据的方式是想要读取磁盘的数据不会马上就去磁盘找而是先在最快的Register看看有没有没有就去内存里面看看有没有最后再到磁盘里面找这种方式也叫缓存命中标准输入和输出在c中scanf和printf输入和输出scanf从键盘做输入printf打印往屏幕做打印。在window环境下scanf会报错因为微软认为是不安全会喊你用scanf_f,但是这_s是微软特有的你去别的环境可能就会报错所以还是用scanf在微软可以使用#define _CRT_SECURE_NO_WARNINGS 取消因为scanf的错误提示标准输出printf()printf函数的返回值是一个int类型在输出成功时返回值表示函数实际输出的字符总数不包括末尾的空字符。即输出成功时返回值是一个非负数最小也是0。如果输出由于某些原因失败那么返回值将会是一个负数。printf函数将数据输出到stdout的行缓冲区但要将这些数据真正展示到外部设备如屏幕则需依靠stdout的自动刷新机制。为了增加输出的实时性和可预测性一个常见策略是在输出字符串的末尾添加换行符\n”这样可以立即触发缓冲区的刷新。这确保了待显示的信息能够迅速呈现不会因其他因素延迟。建议:在不影响程序的逻辑的前提下调用printf函数的格式字符串应当总是以换行符n结尾。#define _CRT_SECURE_NO_WARNINGS #include stdio.h int main(void) { int i, j; float x, y; i 10;j 20; x 43.2892f;y 5527.0f; printf(i%d,j%d,x%f,y%f\n, i, j, x, y); //输出百分号 printf(%%); fLoat a 3.1415926f; //printf转换说明中使用*字符代码2 printf(|%5.2f|a); /* 打印结果是 3.14 现在我改变需求希望能够用变量在程序运行时期确定打印小数点后的位数以及打印结果的总宽度 比如给定两个变量 printf转换说明中使用*字符 */ int width 5; int point 2; /* 那么该如何实现呢 此时就需要用到转换说明中的特殊字符””它的使用语法如下 printf转换说明中使用*字符 */ printf(|%*,*f|,width,point,a); printf(|%4f|\n, 3.14159f); printf(|%10f|\n, 3.14159f); printf(|%.4f|\n, 3.14159f); printf(|%4.1f|\n, 3.14159f); printf(|%04.1f|\n, 3.14159f); printf(|%4.1f|\n, 3.14159f); printf(|%-4.1f|n, 3.14159f); printf(|%4.1f|\n, 3.14159f); return 0; }标准输入scanF()scanf函数的核心作用是从stdin缓冲区中读取字符形式的数据并将其转换为特定类型的数据。从实际效果看scanf函数会根据格式字符串读取输入的内容并将这些内容赋值给指定的变量。调用scanf函数时首要参数也是格式字符串紧随其后的参数是变量的地址表示将读取到的值存放在哪个地址。scanf函数会从左到右依次匹配格式字符串中的每一项如果匹配数据项成功那么scanf函数会继续处理格式串的剩余部分如果匹配不成功那么scanf函数将不再处理格式串的剩余部分而会立刻返回。#define _CRT_SECURE_NO_WARNINGS #include stdio.h int main(void) { int i, j; float x, y; scanf(%d%d%f%f\n, i, j, x, y); /* 100 200 0.1 0.2 i100, j200, x0.1, y0.2 1-20.3-4.0e3 i1, j-20, x0.3, y-4.0e3 100a2000.10.2 i100j,x,y随机值因为a匹配不了 1002000.10.2 i1002000, j随机, x随机, y随机 j是int0.10搞不了 */ //如果在scanf中出现了普通字符。必须要原样写这个普通字符。 scanf(i%d, i); //在输入的时候必须写i 999这种。前面的i一定要写。 // %c的匹配比较特殊。可以匹配任意多个空格可以匹配换行符。 // 但是一般我们对%c的输入肯定是某个非空白的字符 //建议前面加一个空格 char ch; scanf( %c, ch); scanf(%d, i); scanf(%c, ch); //10a,这样子i和ch的值都是对的 /* 10换行符 a 这时候i是对的ch就直接匹配换行符而没有匹配那个a 这句话很多同学是知道的但没有完全理解。 我们来看一段普通的scanf代码 */ }缓冲区对scanf函数的影响-示例代码int num;char ch;scanf(%dnum);scanf( %c,ch);该行代码执行如果正常进行键盘录入100A最终num和ch的结果分别是100和A但如果键盘录入100A最终结果是什么呢实际上结果仍然是100和A那么为什么呢这是因为当键盘录入100A时这一段数据会被放入stdin缓冲区缓冲区中已有数据100A然后scanf开始从缓冲区中读数据。第一个scanf以转换说明%d读取整数所以num变量的最终取值是100而缓冲区中的A字符第一个scanf是不会管它的。因为当scanf函数遇到一个不属于当前项的字符时就返回了。第二个scanf以转换说明%c读取字符也是从缓冲区中读缓冲区不为空且恰好存在一个字符A于是ch的最终取值就是A。所以在需要连续录入的场景中我们要特别注意缓冲区中数据的变化避免因此引发的一些问题。其它输入输出printf/scanf 屏幕 - 键盘sprintf/sscanf 字符串 - 变量fprintf/fscanf 文件 / 流 - 变量#define _CRT_SECURE_NO_WARNINGS #include stdio.h void test_1() { //sprintf → 往字符串里打印作用把数字、变量 变成 字符串存到字符数组里 char str[20] { 0 }; sprintf(str, %d %d\n, 10, 20); //sscanf是输入从字符串输入。可以将字符串转换位某种类型 //全称string scan → 从字符串里读取数据 //作用把字符串解析成数字、变量 int num 100; sscanf(str, %d, num); printf(num%d, num); } void test_2() { int num 100; //fprintf:输出往文件流里面输出 //全称file print → 往文件 / 流里打印 //作用往文件、屏幕、网络等 “流” 里输出内容 fprintf(stdout, %d %d, 30, 60); //往屏幕输出3060 //fscanf也是输入只是是从文件里面输入 //全称file scan → 从文件 / 流里读取 //作用从文件、键盘等 “流” 里读数据 fscanf(stdin, %d, num); printf(num%d, num); } int main(void) { test_1(); return 0; }案例分数相加#define _CRT_SECURE_NO_WARNINGS #include stdio.h int main(void) { /* 分子分母的输入两个分数相加 1/2 3/4 1*4/2*4 3*2/4*2 这两个分数相加。 */ int numerator1,denominator1;//第一个分数的分子和分母 int numerator2,denominator2;//第二个分数的分子和分母 //输入第一个分数 printf(请输入第一个分数格式a/b)); scanf(%d/%d,numerator1,denominator1); //输入第二个分数 printf(请输入第二个分数格式a/b)); scanf(%d/%d,numerator2,denominator2); //分数加法计算 int result_num numerator1 * denominator2 numerator2 * denominator2; int result_denom denominator1 * denominator2; printf(两个分数之和为%d/%d\n, result_num, result_denom); return 0; /* 假设大家就是不知道。 怎么搞 有一些东西不会但是得让自己会起来。 第一种方式google/bing搜索 按照词语的分隔搜索是最好的分子 分母 化简 */ }