网站要求,济南手机端建站模板,聊城手机网站服务,电影网站开发背景文章目录 一.C语言的输入输出1.printfi. 输出整数ii. 浮点数iii.字符 字符串 2.scanfi.整数ii.浮点数iii. 字符 字符串 3.特殊用法i. * 的应用ii. %n 的应用iii. %[] 的应用 二.C中的输入输出1.couti. 缓冲区#xff08;buffer#xff09;ii. cout之格式化输出 2… 文章目录 一.C语言的输入输出1.printfi. 输出整数ii. 浮点数iii.字符 字符串 2.scanfi.整数ii.浮点数iii. 字符 字符串 3.特殊用法i. * 的应用ii. %n 的应用iii. %[] 的应用 二.C中的输入输出1.couti. 缓冲区bufferii. cout之格式化输出 2.cini. cin.get()ii. cin.getline()iii. 流状态 三.取消同步流 一.C语言的输入输出
在讲 c 的输入输出之前有必要先回顾一下最经典的 c 语言的输入输出 —— s c a n f ——scanf ——scanf 和 p r i n t f printf printf他们被声明在头文件 #include stdio.h 中
scanf printf 的优势
格式化输入输出效率高 1.printf p r i n t f printf printf 函数为格式输出函数其功能是按照用户指定的格式将指定的数据输出到屏幕上
printf(格式控制字符串, 输出表项);格式控制字符串有两种格式字符串、非格式字符串非格式字符串在输出的时候原样打印格式字符串是以 % \% % 开头的字符串后面跟不同格式字符用来说明输出数据的类型、形式、长度、小数位数等就像一个模具用来控制希望得到的物体的形态
类型格式字符串int%dfloat%fdouble%lfchar%cchar[]%slong long%lld
格式字符串的形式为% [对齐方式][输出最小宽度] [.精度] 类型
对齐方式- 表示左对齐不填表示右对齐没有% 的写法默认为右对齐如 % -d表示左对齐最小宽度 N N N当实际宽度小于 N N N时用指定的字符填充剩余部分默认以空格填充使其长度为 N N N并输出当实际宽度大于 N N N时按实际位数输出如 % 010d表示最小宽度为 10不足部分用 0 填充精度控制这里精度表示保留小数点后几位如 %.2f表示保留小数点后两位 i. 输出整数
代码实现
#includestdio.h
int main()
{int a100;printf(%d\n, a); //100printf(%5d\n, a); // 100printf(%05d\n, a); //00100printf(%.2d\n, a); //100.00return 0;
}ii. 浮点数
浮点数有两种类型 f l o a t 、 d o u b l e float、double float、double f l o a t float float是单精度浮点数类型通常在内存中占据 4 4 4个字节它可以表示大约6到7位的有效数字 d o u b l e double double是双精度浮点数类型通常在内存中占据 8 8 8个字节它可以表示大约15到16位的有效数字
当使用 p r i n t f printf printf输出时若不控制精度均默认保留至小数点后 6 6 6 位
代码实现
#includestdio.h
int main()
{float a2.01;printf(%f\n, a); //2.010000printf(%.3f\n, a); //2.010printf(%10f\n, a); // 2.010000printf(%10.3f\n, a); // 2.010double b5.01;printf(%lf\n, b); //5.010000printf(%.3lf\n, b); //5.010return 0;
}iii.字符 字符串
const char* 和 char[] 都可以用来表示字符串
const char* 是一个指向常量字符的指针即指针指向的字符内容是不可更改的char[] 是一个字符数组可以通过索引修改字符串
均可以通过 % s \%s %s 得到整个字符串
代码实现
#includestdio.h
int main()
{char a A;printf(%c\n, a); //Aconst char* strHello World!;char buf[]Hello World!;printf(%s\n, str); //Hello World!printf(%s\n, buf); //Hello World!return 0;
}2.scanf s c a n f scanf scanf 函数称为格式输入函数即按照格式字符串的格式从键盘上把数据输入到指定的变量之中其调用的基本格式为
scanf(格式控制字符串,输入项地址列表);其中格式控制字符串的作用与 p r i n t f printf printf函数相同地址表项中的地址给出各变量的地址地址是由地址运算符 后跟变量名组成的 为什么需要加上取址符 ? 因为 s c a n f scanf scanf函数需要知道变量的内存地址才能将输入的值存储到正确的位置上当我们使用 s c a n f scanf scanf函数时我们需要将输入的值存储到一个变量中而不是直接给出变量的名称通过使用 操作符我们可以获取该变量的内存地址从而告诉 s c a n f scanf scanf函数将输入的值存储到这个地址所对应的内存位置上 特别地对于数组而言可以不用加 因为数组名本身就是指向数组首地址的指针 s c a n f scanf scanf 的返回值 s c a n f ( ) scanf() scanf() 函数返回成功读入的项目的个数如果它没有读取任何项目比如它期望接收一个数字而实际却输入的一个非数字字符时就会发生这种情况scanf() 则会返回 0 0 0
当它检测到 文件末尾 (end of file) 时它返回 E O F EOF EOF E O F EOF EOF 在是文件 stdio.h 中的定义好的一个特殊值通常 #define 指令会将 E O F EOF EOF 的值定义为 − 1 -1 −1则可以结合 w h i l e while while 循环实现多行输入通常有两种 c 的写法
while(scanf(%d,a) ! EOF)while(~scanf(%d,a)) 代码实现
#include stdio.h
int main() {int a,b;while(scanf(%d %d, a, b) ! EOF)printf(%d\n, ab);return 0;
}也就是说若不按下 CtrlZ循环就不会结束 W i n d o w s Windows Windows允许通过键盘模拟文件尾 C t r l Z CtrlZ CtrlZ i.整数
代码实现
#include stdio.h
int main(){int a, b;scanf(%d %d,a, b); //1 2printf(%d,%d\n, a, b); //1,2return 0;
}ii.浮点数
代码实现
#include stdio.h
int main(){double c, d;scanf(%lf %lf, c, d); //1 2printf(%.2lf,%.3lf\n, c, d); //1.00,2.000return 0;
}iii. 字符 字符串
输入单个字符
代码实现
#includestdio.h
int main(){char e, f;scanf(%c %c, e, f); //a bprintf(%c,%c\n, e, f); //a,breturn 0;
}利用 %s 输入字符串
注意%s 输入遇到空格或者回车就会停下截断
#includestdio.h
int main(){char s[10];scanf(%s, s);printf(%s, s);return 0;
}输出结果 利用正则表达式输入字符串
[] 是正则表达式表示只要不是回车就读入字符串空格不会截断
#includestdio.h
int main(){char s0[15];scanf(%[^\n], s0);printf(%s, s0);return 0;
}输出结果 3.特殊用法
i. * 的应用
① ′ ∗ ′ * ′∗′ 在 p r i n t f printf printf 中的应用
控制宽度和精度假如在输出时不想事先指定字段宽度 / / /精度而是希望由程序来制定该值则可以在字段宽度 / / /精度部分使用 * 代替数字来达到目的同时需要在后面多增加一个参数来告诉函数宽度 / / /精度的值是多少具体的说如果转换说明符为%*d那么参数列表中应该包括一个*的值和一个d的值来控制宽度 / / /精度和变量的值
代码示例
#includestdio.h
int main(void)
{printf(%0*d\n, 5, 10); //00010printf(%.*f\n, 2, 10.12345); //10.12printf(%*.*f\n, 5, 1, 10.0); // 10.0return 0;
}② ′ ∗ ′ * ′∗′ 在 s c a n f scanf scanf 中的应用
忽略赋值* 在 s c a n f scanf scanf 函数中通常用来指定忽略某个输入值的赋值这在处理输入时非常有用因为有时候我们可能只想跳过一些输入而不需要将其赋值给特定的变量
例如有以下的输入数据 “10 20”但是我们只想读取第二个整数而不关心第一个整数则可以使用 *
#include stdio.h
int main(){int num;scanf(%*d %d, num); //10 20printf(%d, num); //20return 0;
}ii. %n 的应用
① % n \%n %n 在 p r i n t f printf printf 中的应用
统计字符数 p r i n t f ( ) printf() printf() 中%n 是一个特殊的格式说明符它不打印某些内容而是会将目前为止打印输出字符的数量存储到参数列表中指向的变量中
代码示例
#includestdio.h
int main()
{int k0;printf(hello %nworld, k); //输出 hello worldprintf(%d,k); //6return 0;
}② % n \%n %n 在 s c a n f scanf scanf 中的应用
统计字符数 s c a n f ( ) scanf() scanf() 中%n 会将目前为止读入字符的数量存储到参数列表中指向的变量中
代码示例
#include stdio.h
int main() {char str[100];int count;scanf(%s%n, str, count); //abcdprintf(%d\n, count); //4return 0;
}iii. %[] 的应用
常见用法
%[0-9] 表示只读入’0’到’9’之间的字符%[a-zA-Z] 表示只读入字母%[^\n] 就表示读入除换行符之外的字符^ 表示除…之外%k[^] 读入号前的至多 k k k个字符
当读取到范围之外的字符时就会做截取也就是之后的数据将不会放入字符串中 代码示例
//1
#include stdio.h
int main() {char number[10];scanf(%[0-9], number); //123abcprintf(%s\n, number); //123return 0;
}//2
#include stdio.h
int main() {char letters[20];scanf(%[a-zA-Z], letters); //abc121efgprintf(%s\n, letters); //abcreturn 0;
}//3
#includestdio.h
int main(){char s0[15];scanf(%[^\n], s0); //123abc abcprintf(%s, s0); //123abc abcreturn 0;
}//4
#include stdio.hint main() {char str[20];scanf(%10[^], str); //123abcprintf(%s\n, str); //123return 0;
}二.C中的输入输出
现在来到 C 中其输入输出通过头文件 #include iostream 来完成其命名空间为 s t d std std
流 S t r e a m Stream Stream是一个抽象概念用于表示数据的序列它可以是从一个地方到另一个地方的数据传输通道流可以用于从文件、内存、网络或其他设备中读取数据也可以用于向这些地方写入数据而 C 的 I / O I/O I/O 就是发生在流
输入流 i s t r e a m istream istream用于从数据源中读取数据比如从键盘读取用户输入、从文件中读取数据、从网络连接中读取数据等输出流 o s t r e a m ostream ostream用于向目标位置写入数据比如将数据输出到屏幕、写入到文件、发送到网络等 1.cout
cout 是 C 标准库中的标准输出流对象
cout hello world endl;是输出运算符左侧必须是 o s t r e a m ostream ostream 对象右侧是要打印的值此运算符将给定的值写到给定的 o s t r e a m ostream ostream 对象中计算结果就是我们写入给定值的那个 o s t r e a m ostream ostream 对象
cout 是一个输出对象输出语句本质上就是不断创造 o s t r e a m ostream ostream 对象的过程第一个计算的结果是第二个的输入从而形成链条最终将所有信息输出到屏幕上例如
cout hello endl;
等价于
1.cout hello;
2.cout endl;第一个 给用户打印一条消息这个消息是一个字符串字面值常量在双引号之间的文本会被打印到标准输出第二个 打印 endl这是一个被称为操作符的特殊值写入 endl 的效果是结束当前行并将与设备关联的缓冲区中的内容刷到设备中 i. 缓冲区buffer
当程序向输出设备比如屏幕、打印机输出数据时数据通常不是立即传递到设备上而是先存储到缓冲区中这样做的好处是可以减少向设备频繁传输数据的开销而是利用缓冲区将数据一次性传输从而提高效率类似地当数据从输入设备比如键盘、网络输入进来时也会先存储到输入缓冲区中程序可以逐步读取这些数据。
在 C 中对于标准输出流 c o u t cout cout也存在一个输出缓冲区当程序使用 c o u t cout cout 进行输出时数据首先被存储在输出缓冲区中直到缓冲区满了或者遇到显式的刷新操作时数据才会被真正输出到屏幕上
使用 std::flush 操纵符手动刷新输出缓冲区输出末尾添加 std::endl 自动刷新缓冲区并插入换行符 ii. cout之格式化输出
通过 #include iomanip 头文件来实现格式化的输出
std::setw(int n) 设置域宽为 n n n默认为右对齐std::setprecision(int n) 设置浮点数的精度为 n n n 位小数std::setfill(char c) 设置填充字符为 c c cstd::left 设置输出在设定的宽度内左对齐std::right 设置输出在设定的宽度内右对齐std::boolalpha 将布尔类型的输出从 0 / 1 0/1 0/1 改为 t r u e / f a l s e true/false true/falsestd::hex 以十六进制形式输出值std::oct 以八进制形式输出值std::dec 以十进制形式输出值 代码示例
#include iostream
#include iomanipint main() {int n 255;double pi 3.1415926;std::cout Default: n pi std::endl;std::cout setw: std::setw(10) n std::setw(10) pi std::endl;std::cout setprecision: std::setprecision(4) n std::setprecision(3) pi std::endl;std::cout setfill: std::setfill(*) std::setw(10) n std::setfill(#) std::setw(10) pi std::endl;std::cout left/right: std::left std::setw(10) n std::right std::setw(10) pi std::endl;std::cout boolalpha: std::boolalpha true false std::endl;std::cout Hex/Oct/Dec: std::hex n std::oct n std::dec n std::endl;return 0;
}输出结果 2.cin
cin 是 C 标准库中的标准输入流对象在查看输入流的时候 c i n cin cin 会自动跳过空白空格换行符制表符直到遇到非空白字符
int a, b;
cin a b;是输入运算符其左侧为一个 i s t r e a m istream istream 运算对象再接受一个变量作为右侧运算对象可以连续读取多个数据并将它们存储到不同的变量中
一些简单代码示例
整数
#include iostream
using namespace std;
int main(){int a, b;cin a b;cout a b endl;return 0;
}浮点数
#include iostream
using namespace std;
int main(){double c, d;cin c d;cout fixed setprecision(3) c d endl; //保留三位有效数字return 0;
}单个字符
#include iostream
using namespace std;
int main(){char ch;cin ch;cout ch endl;return 0;
}字符串
#include iostream
using namespace std;
int main(){char str[10];cin str; //cin输入字符串也是遇到空格或回车就会结束cout str endl;return 0;
}注意 c i n cin cin 接受一个字符串时遇到 ‘空格’、‘ t a b tab tab’、回车’就会结束当需要输入包含空格的整行文本时可以使用 std::getline 函数来读取输入流而不是直接使用 运算符这样可以确保整行文本被完整地存储到字符串中
getline(cin, string)
头文件#include string第一个参数是输入流比如 s t d : : c i n std::cin std::cin 或文件流第二个参数是用来存储读取的文本的字符串
代码示例
#include iostream
#include string
using namespace std;
int main(){string s;getline(cin, s); //可以实现整行输入cout s endl;return 0;
}i. cin.get()
① cin.get(字符变量名)
每次接受单个字符逐个字符读取当读取的输入流有空格或回车时会读取空格或回车并将其视为普通字符而不会将其作为流结束的标志来处理 A S C I I ASCII ASCII 中空格 − 32 -32 −32回车 − 10 -10 −10 代码示例
#include iostream
using namespace std;
int main (){char a, b;cin.get(a);cin.get(b);couta bendl;cout(int)a (int)bendl;return 0;
}输出
示例1输入 a[回车]
a
a97 10
结果得到的是字母 a 和 换行符(\n)示例2输入 a[空格]b[回车]
a b
a
97 32
结果得到的是字母 a 和 空格符② cin.get(字符数组名,接收字符数目,结束符)
接收一定长度的字符串接受字符数目如 cin.get(s, 5) 会读取最多 5 5 5 个字符到数组 s s s 中并且在必要时加上空字符\0 以表示字符串的结束也就是说实际读取的长度会减 1 1 1因为结尾的 \0 占了一位结束符默认为回车 \n也就是说可以接受空格不接受回车但不读取不代表丢弃回车仍然在输入缓冲区内 代码示例
#include iostream
using namespace std;
int main (){char ch1,ch2[10];cin.get(ch2,5); //在不遇到结束符的情况下最多可接收5-14个字符到ch2中注意结束符为默认Entercin.get(ch1); //读取单个字符coutch2ch2endl;coutch1(int)ch1endl;return 0;
}输出
示例1输入 a[回车]
a
ch2a10
由于第二个就读取到了换行符因此直接结束之后换行符被第二个 cin.get() 读取示例2输入长度为 7 的字符串 abcdefg
abcdefg
ch2abcd
e101③ cin.get()
无参数可用于舍弃输入流中的不需要的字符或者舍弃回车 \n弥补 cin.get(字符数组名,字符数目,结束符) 的不足
代码示例
#include iostream
using namespace std;
int main()
{char ch1,ch2[10];cin.get(ch2,5);cin.get(); //舍弃一个缓冲区中的字符cin.get(ch1);coutch2endl;coutch1\n(int)ch1endl;return 0;
}输出
示例1输入长度为 7 的字符串
abcdefg
ch2abcd
f102
结果表明第二个 cin.get() 跳过了字符 e使得第三个 cin.get() 读取到了 f示例2输入 1a[回车]bcdef
1a
bcdef
ch21a
b98
同理第二个 cin.get() 跳过了换行符ii. cin.getline()
cin.getline(字符数组名接收长度结束符) 与 cin.get(...)的用法极为类似但存在几个注意点 c i n . g e t ( ) cin.get() cin.get() 当输入的字符串超长时不会引起 c i n cin cin 函数的错误后面若有 c i n cin cin 操作会继续执行只是直接从缓冲区中取数据但是 c i n . g e t l i n e ( ) cin.getline() cin.getline() 当输入超长时会引起 c i n cin cin 函数的错误后面的 c i n cin cin 操作将不再执行
代码示例
#include iostream
using namespace std;
int main()
{char ch1, ch2[10];cin.getline(ch2, 5);cinch1;coutch2endl;coutch1\n(int)ch1endl;return 0;
}输出结果 可以看到此时出现输入超长 c h 2 1234 ch21234 ch21234此时缓冲区剩余5[回车]但是结果得到了 0 0 0(g环境下)说明 c i n cin cin 已失效 c i n . g e t ( ) cin.get() cin.get() 每次读取一整行并把由 Enter键 生成的换行符 \n 留在输入队列中然而 c i n . g e t l i n e ( ) cin.getline() cin.getline() 每次读取一整行后会将换行符\n丢弃 !
代码示例
#include iostream
using namespace std;int main() {cout Enter your name:;char name[15];cin.getline(name, 15); //输入xjc(enter)cout name: name endl;char ch;cin.get(ch); // 输入123(enter) 注因为cin.getline把最后一个换行符丢弃了所以此处ch读取字符1cout ch (int)ch endl; //输出49 1的ASCII码值return 0;
}输出结果 iii. 流状态
流状态是顾名思义就是输入或输出流的状态 c i n cin cin 和 c o u t cout cout 对象都包含了一个描述流状态的变量 i o s t a t e iostate iostate 类型它由三个元素组成 e o f b i t f a i l b i t b a d b i t eofbitfailbitbadbit eofbitfailbitbadbit其中每一个元素都由一位来表示 1 1 1代表是 0 0 0代表否
成员描述eofbit到达文件尾则此位设置为1badbit如果流被破坏则此位设置为1failbit如果输入未能读取预期的字符或输出操作没有写入预期字符则此位设置为1goodbit流状态正常也代表所有位为 0 即表示 0good()如果流正常则返回 trueeof()如果 eofbit 为 1 返回 truebad()如果 badbit 为 1 返回 truefail()如果 badbit 或 failbit 为 1 返回 truerdstate()返回流状态exceptions()返回一个位掩码指出哪些标记将导致异常发生exceptions(iostate ex)设置哪些状态将导致 clear() 引发异常clear(iostate s)将流状态设置为 ss 默认为 0 即goodbitsetstate(iostate s)设置与 s 中对应位的流状态其他位保持不变相当于用 s 与 当前流状态做 “或运算” 来看一个缓冲区未读取完导致 f a i l b i t 1 failbit1 failbit1 的例子
#include iostream
using namespace std;int main()
{
char ch, str[20];cin.getline(str, 5);coutflag:cin.good()endl; // 查看goodbit状态即是否有异常cin.clear(); // 清除错误标志coutflag:cin.good()endl; // 清除标志后再查看异常状态cinch;coutstr:strendl;coutch :chendl;system(pause);return 0;
}输出结果 可以看出因输入缓冲区未读取完造成输入异常 cin.good()false
通过cin.clear()可以清除输入流对象 c i n cin cin的异常状态不影响后面的 cinch 从输入缓冲区读取数据因为 cin.getline 读取之后输入缓冲区中残留的字符串是5[回车]所以 c i n c h cinch cinch 将 5 5 5 读取并存入 c h ch ch打印输入并输出 5 5 5
如果没有 cin.clear()cinch 将读取失败 c h ch ch 为空
输出结果 三.取消同步流
在算法题中涉及到大量数据读入的时候通常避免使用cin读入数据而改用scanf原因是scanf相对速度更快
解决方法: c i n cin cin 效率低的原因一是在于默认 C 中的 c i n cin cin (输入流对象) 与 C语言中的 s t d i n stdin stdin (输入流指针) 总是保持同步 c i n cin cin 会把要输出的东西先存入缓冲区进而消耗时间通过关闭同步可以有效提高 c i n cin cin 效率可以用 sync_with_stdio(0) 实现异步 默认情况下 c i n cin cin 绑定的是 c o u t cout cout每次执行 的时候都要调用 f l u s h flush flush当 cout 的缓冲区刷新的时候cin 的缓冲区由于绑定的存在也同时进行了刷新进而增加 I / O I/O I/O 负担因此可以通过 tie(0) 解绑
关闭同步后 c i n cin cin 的速度将与 s c a n f scanf scanf 相差无几
int main(){//取消同步流ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);//其余操作不变int x;cin x;cout x;system(pause);return 0;
}注意
关闭同步之后请不要同时使用C与C的读写方式避免不必要的麻烦如 printf()scanf()gets()pus()getchar() 不要与 cincout 共用 c o u t cout cout 中不要使用 e n d l endl endl每次使用 e n d l endl endl都要 f l u s h flush flush 缓冲区造成大量时间耗费 ch$ 为空