前言
笔者上了几个月的班,昨天参加了一场笔试,感觉算法甚至编程语言的语法都忘光了(定义c语言数组想了十几分钟),于是痛定思痛,决心要把代码随想录的题刷一遍,系统的学一下算法。
笔者已经坚定决心,从本篇开始,不断记录自己的学习和思考过程(其实是大模型的思考过程!😃)
ACM 模式和 核心代码模式
ACM模式要自己处理系统输入输出, 核心代码模式是写一个核心函数
编程第一步,搞清读参数
C++ 的 cin/cout
、C 的 scanf/printf
、Python 的 sys.stdin/stdout
和 Shell 的标准输入输出(如管道和重定向)都是处理标准输入/输出(stdin/stdout)的工具,但它们在使用方式、性能、抽象层次和设计哲学上有显著区别和联系。以下是详细对比:
核心联系
-
统一的抽象概念
所有工具都基于操作系统的标准输入/输出(stdin/stdout)概念,对应文件描述符0
(输入)和1
(输出)。 -
数据流方向一致
均遵循“数据从 stdin 读取,处理后再写入 stdout”的流程。 -
可互相组合
不同工具可通过管道(|
)或重定向(<
,>
)协同工作。例如:# C++ 程序输出到 Python 脚本 ./cpp_program | python3 script.py
主要区别
特性 | C++ cin/cout |
C scanf/printf |
Python sys.stdin/stdout |
Shell 标准输入输出 |
---|---|---|---|---|
语法风格 | 面向对象(运算符 >> /<< ) |
函数式(格式字符串) | 面向对象(文件对象方法) | 命令式(管道 ` |
类型安全 | 是(自动类型推导) | 否(需显式指定格式符,易出错) | 是(动态类型) | 无类型(纯文本流) |
性能 | 较高(但默认同步 C 库,可能略慢) | 最高(直接系统调用,无额外抽象) | 较低(解释型语言,动态类型开销) | 中等(依赖工具实现,如 grep /awk ) |
缓冲机制 | 行缓冲(默认,可调整) | 全缓冲(默认,可通过 fflush 控制) |
全缓冲(可设置 flush=True ) |
行缓冲(通常由工具自行管理) |
错误处理 | 通过流状态(如 failbit )检查 |
通过返回值检查(如 scanf 返回成功数) |
通过异常或返回值(如 read() ) |
通过退出状态码($? ) |
典型用途 | 类型安全的高性能 I/O | 底层高效控制 | 快速开发和文本处理 | 文本流处理和工具组合 |
示例代码 | cin >> x; cout << x; |
scanf("%d", &x); printf("%d", x); |
line = sys.stdin.readline() |
`cat file.txt |
关键细节对比
1. 类型处理
- C++:
cin >> x
根据x
的类型自动解析输入(如int
、string
),类型安全。 - C:需显式指定格式符(如
%d
、%s
),易因类型不匹配导致未定义行为。 - Python:输入始终为字符串,需手动转换类型(如
int(input())
)。 - Shell:数据为纯文本流,需用工具(如
awk
)解析类型。
2. 缓冲机制
- C++:
cout
默认行缓冲(输出到终端时),但写入文件时为全缓冲;可通过endl
或flush
强制刷新。 - C:
printf
全缓冲,除非输出到终端(行缓冲);需手动调用fflush(stdout)
。 - Python:
print
函数默认全缓冲,但可设置flush=True
;sys.stdout.write
需手动刷新。 - Shell:管道中的工具通常行缓冲(如
grep
),但某些工具(如sed
)可能全缓冲。
3. 性能考量
- C/C++:适合处理大规模数据(如每秒百万级输入),但需避免频繁同步(如
sync_with_stdio(false)
)。 - Python:处理大数据时性能较差,但可通过批量读取(如
sys.stdin.read()
)优化。 - Shell:组合工具时性能取决于具体命令(如
awk
比纯 Shell 循环快)。
4. 错误处理
- C++:通过
cin.fail()
检查输入错误,需手动清除状态(cin.clear()
)。 - C:
scanf
返回成功匹配的参数数量,需逐项检查。 - Python:
sys.stdin.read()
可能抛出异常(如键盘中断),需try/except
捕获。 - Shell:通过
$?
获取上一个命令的退出状态(0 表示成功,非 0 表示失败)。
使用场景建议
- 需要高性能和类型安全:优先选择 C++
cin/cout
(关闭同步)或 Cscanf/printf
。 - 快速开发和文本处理:使用 Python
sys.stdin
和字符串方法。 - 组合现有工具处理文本流:Shell 管道和重定向(如
awk
/sed
)。 - 混合语言协作:通过 stdin/stdout 跨语言传递数据(如 C++ 程序输出到 Python 脚本)。
示例:跨语言协作
# C 程序生成数据 → Python 处理 → Shell 过滤
./c_program | python3 script.py | grep "result"
c,c++, python输入输出函数的返回值详解:
C++ cin
和 cout
-
cin >> var
的返回值-
类型:
istream&
(输入流对象的引用)。 -
行为:返回流对象本身,允许链式调用(如
cin >> a >> b;
)。 -
错误处理:可通过检查流状态判断是否成功:
if (cin >> x) { /* 读取成功 */ } else { /* 失败(如类型不匹配或 EOF)*/ }
-
-
cout << value
的返回值- 类型:
ostream&
(输出流对象的引用)。 - 行为:返回流对象本身,支持链式输出(如
cout << a << b;
)。 - 错误处理:通常不检查返回值,但可通过
cout.good()
检测流状态。
- 类型:
C 的 scanf
和 printf
-
scanf
的返回值-
类型:
int
。 -
行为:返回成功匹配并赋值的输入项数量。若遇到输入错误或 EOF,返回
EOF
(通常是-1
)。 -
示例:
int a, b; int result = scanf("%d %d", &a, &b); if (result == 2) { /* 成功读取两个整数 */ } else if (result == EOF) { /* 输入结束或错误 */ }
-
-
printf
的返回值-
类型:
int
。 -
行为:返回实际输出的字符数(不包括终止符
\0
)。若出错(如格式化字符串无效),返回负数。 -
示例:
int len = printf("Value: %d", 42); // len = 8("Value: 42" 共 8 字符)
-
Python 的 sys.stdin
和 print
-
sys.stdin
的方法返回值-
sys.stdin.read()
:返回整个输入内容(字符串),直到 EOF。 -
sys.stdin.readline()
:返回一行输入(包括换行符\n
),EOF 时返回空字符串''
。 -
示例:
line = sys.stdin.readline() if line == '': # 判断是否 EOFprint("Input ended.")
-
-
print
的返回值-
类型:
None
。 -
行为:
print
是 Python 的函数,仅执行输出操作,没有返回值。 -
示例:
result = print("Hello") # result = None
-
关键对比表
函数/方法 | 返回值类型 | 返回值含义 | 错误处理 |
---|---|---|---|
cin >> var |
istream& |
返回流对象本身,用于链式操作 | 检查流状态(如 cin.fail() ) |
cout << value |
ostream& |
返回流对象本身,用于链式操作 | 通常忽略,可检查 cout.good() |
scanf |
int |
成功匹配的输入项数量 | 检查返回值是否等于预期参数数量 |
printf |
int |
成功输出的字符数 | 检查是否为负数 |
sys.stdin.read() |
str |
输入的全部内容(字符串) | 空字符串表示 EOF |
sys.stdin.readline() |
str |
单行输入内容(含换行符) | 空字符串表示 EOF |
print() |
None |
无返回值 | 异常可能由输出流引发(如 IOError) |
常见场景示例
-
C++ 读取直到 EOF
int x; while (cin >> x) { // 当读取失败(如 EOF)时退出循环// 处理 x }
-
C 安全读取输入
int a; if (scanf("%d", &a) != 1) {fprintf(stderr, "Invalid input!");exit(1); }
-
Python 逐行读取输入
import sys for line in sys.stdin:line = line.strip()if not line:break# 处理 line
总结
- C/C++:通过返回值或流状态显式处理错误。
- Python:输入方法返回字符串,需手动处理类型和 EOF;
print
无返回值。 - Shell:输入输出为纯文本流,依赖外部工具解析(如
awk
处理数值)。
不同语言stdin, stdout,stderr详解
在C++和Python中,标准输入(stdin)、标准输出(stdout)和标准错误(stderr)是三个独立的流。cin
和 cout
是C++中的标准输入输出流,而 scanf
和 printf
是C语言的标准输入输出函数。sys.stdin
、sys.stdout
和 sys.stderr
则是Python中的对应概念。
C++中的处理
标准输出 (cout
) 和标准错误 (cerr
)
std::cout
:用于标准输出(通常是终端屏幕)。std::cerr
:用于标准错误输出(也是通常显示在终端屏幕上,但与标准输出分开)。
示例:
#include <iostream>int main() {std::cout << "This is standard output." << std::endl;std::cerr << "This is standard error output." << std::endl;return 0;
}
使用 fprintf
处理 stderr
如果你使用的是C风格的I/O函数,可以使用 fprintf
来向 stderr
输出信息。
示例:
#include <cstdio>int main() {printf("This is standard output.\n");fprintf(stderr, "This is standard error output.\n");return 0;
}
Python中的处理
标准输入 (sys.stdin
)、标准输出 (sys.stdout
) 和标准错误 (sys.stderr
)
sys.stdin
:用于标准输入。sys.stdout
:用于标准输出。sys.stderr
:用于标准错误输出。
示例:
import syssys.stdout.write("This is standard output.\n")
sys.stderr.write("This is standard error output.\n")# 或者使用 print 函数指定文件参数
print("This is standard output.", file=sys.stdout)
print("This is standard error output.", file=sys.stderr)
总结
- C++: 使用
std::cout
和std::cerr
分别处理标准输出和标准错误输出。也可以使用printf
和fprintf(stderr, ...)
来分别处理标准输出和标准错误输出。 - Python: 使用
sys.stdout
和sys.stderr
分别处理标准输出和标准错误输出。可以通过print
函数的file
参数来指定输出流。
这些方法允许你将正常的程序输出和错误信息分离,这对于调试和日志记录非常有用。例如,你可以将正常的信息打印到控制台或日志文件,而将错误信息重定向到一个单独的日志文件中以便于分析。
代码实战
下面的所有代码均为自己手写,非官方参考答案,官方答案在这
第一题
1. A+B问题I
题目描述
你的任务是计算a+b。输入描述
输入包含一系列的a和b对,通过空格隔开。一对a和b占一行。输出描述
对于输入的每对a和b,你需要依次输出a、b的和。如对于输入中的第二对a和b,在输出中它们的和应该也在第二行。输入示例
3 4
11 40
输出示例
7
51
题解
C++:
#include<iostream>
using namespace std;
int main(){int a,b;while(cin>>a>>b){cout<<a+b<<'\n';}
}
C风格:
//代码1:#include<cstdio>
using namespace std;
int main(){int a,b;while(scanf("%d%d",&a,&b) == 2){printf("%d\n",a+b);}}//代码2:
#include<cstdio>
using namespace std;
int main(){int a,b;while(scanf("%d%d",&a,&b) != EOF){printf("%d\n",a+b);}}
python:
import sysif __name__ =="__main__": for line in sys.stdin:x,y = line.split(" ")#print(type(line))#print(line)print(int(x)+int(y))
第二题
2. A+B问题II
题目描述
计算a+b,但输入方式有所改变。输入描述
第一行是一个整数N,表示后面会有N行a和b,通过空格隔开。输出描述
对于输入的每对a和b,你需要在相应的行输出a、b的和。
如第二对a和b,对应的和也输出在第二行。
输入示例
2
2 4
9 21
输出示例
6
30
提示信息
注意,测试数据不仅仅一组。也就是说,会持续输入N以及后面的a和b
题解:
c&c++
#include<iostream>
#include<cstdio>
using namespace std;
/*int main(){int n,a,b;while(true){if(scanf("%d",&n) == 1){while(n--){scanf("%d%d",&a,&b);printf("%d\n",a+b);} }else{break;}}}*/int main(){int n,a,b;while(cin>>n){while(n--){cin>>a>>b;cout<<a+b<<"\n";}}
}
python:
while 1:try:N = int(input())for i in range(N):l = list(map(int,input().split()))print(sum(l))except:break
第三题
3. A+B问题III
题目描述
你的任务依然是计算a+b。输入描述
输入中每行是一对a和b。其中会有一对是0和0标志着输入结束,且这一对不要计算。输出描述
对于输入的每对a和b,你需要在相应的行输出a、b的和。
如第二对a和b,他们的和也输出在第二行。
输入示例
2 4
11 19
0 0
输出示例
6
30
题解:
python
while(1):mylist = list(map(int, input().split()))if mylist[0] == mylist[1] == 0:break;else:print(sum(mylist))
c++&c
#include<iostream>
using namespace std;
int main(){int a,b;while(true){cin>>a>>b;if(a==0&&b==0){break;}else{cout<<a+b<<endl;}}
}
第四题
4. A+B问题IV
题目描述
你的任务是计算若干整数的和。输入描述
每行的第一个数N,表示本行后面有N个数。如果N=0时,表示输入结束,且这一行不要计算。输出描述
对于每一行数据需要在相应的行输出和。输入示例
4 1 2 3 4
5 1 2 3 4 5
0
输出示例
10
15
python
import sys
while(1):mylist = list(map(int, input().split()))if mylist[0] == 0:breakprint(sum(mylist[1:]))
c++
#include<iostream>
using namespace std;
int main(){int n;while(cin>>n && n!=0){int tmp;int sum = 0;while(n--){cin>>tmp;sum+=tmp;}cout<<sum<<endl;}
}
第五题
5. A+B问题VII
题目描述
你的任务是计算两个整数的和。
输入描述
输入包含若干行,每行输入两个整数a和b,由空格分隔。
输出描述
对于每组输入,输出a和b的和,每行输出后接一个空行。
输入示例
2 4
11 19
输出示例
630
题解
python
while 1:try:mylist = list(map(int, input().split()))print(sum(mylist),'\n')except:break
c++
#include<iostream>
using namespace std;
int main(){int a,b;while(cin>>a>>b){cout<<a+b<<"\n\n";}}
第六题
6. A+B问题VIII
题目描述
你的任务是计算若干整数的和。
输入描述
输入的第一行为一个整数N,接下来N行每行先输入一个整数M,然后在同一行内输入M个整数。输出描述
对于每组输入,输出M个数的和,每组输出之间输出一个空行。
输入示例
3
4 1 2 3 4
5 1 2 3 4 5
3 1 2 3
输出示例
10156
提示信息
注意以上样例为一组测试数据,后端判题会有很多组测试数据,也就是会有多个N的输入
例如输入可以是:
3
4 1 2 3 4
5 1 2 3 4 5
3 1 2 3
3
4 1 2 3 4
5 1 2 3 4 5
3 1 2 3
输出则是
10156
10156
只保证每组数据间是有空行的。但两组数据并没有空行
题解
python
while 1:try:N = int(input())for i in range(N):fin = list(map(int,input().split()))print(sum(fin[1:]))if i != N-1:print()except:break
c++
#include<iostream>
using namespace std;
int main(){int n;while(cin>>n){int n_loop;int cnt_loop;int tmp_loop;while(n--){cin>>n_loop;cnt_loop = 0;while(n_loop--){cin>>tmp_loop;cnt_loop+=tmp_loop;}cout<<cnt_loop<<endl;if(n!=0){cout<<"\n";}}}
}