算法日志1:编程第一步,搞清读参数
前言
笔者上了几个月的班,昨天参加了一场笔试,感觉算法甚至编程语言的语法都忘光了(定义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 == '': # 判断是否 EOF print("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 sys
sys.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 sys
if __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:
break
print(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
输出示例
6
30
题解
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
输出示例
10
15
6
提示信息
注意以上样例为一组测试数据,后端判题会有很多组测试数据,也就是会有多个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
输出则是
10
15
6
10
15
6
只保证每组数据间是有空行的。但两组数据并没有空行
题解
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";
}
}
}
}

浙公网安备 33010602011771号