C++ / Java在算法竞赛中的IO处理
C++
输入常用到的方法
std::cin
在标头 <iostream>
定义。
全局对象 std::cin
与标准 C 输入流 stdin 关联。
示例
// 读入整数(跳过中间的所有连续空白符)
int a, b;
cin >> a >> b;
// 读入字符串到c++风格字符串(读到空白符停止)
string s;
cin >> s;
// 读入整数(跳过中间的所有连续空白符)
int a, b;
cin >> a >> b;
// 读入字符串到c++风格字符串(读到空白符停止)
string s;
cin >> s;
scanf
在标头 <stdio.h>
定义。
从 stdin 读取数据,按照 format
转译,并将结果存储到指定位置。
用法
int scanf(format, ...);
参数:
format
:指向指定读取输入方式的空终止字符串的指针。 格式字符串由下列内容组成:非空白多字节字符,除了
%
:每个格式字符串中的这种字符处理来自输入流的准确同一字符,或若它与流的下个字符比较不相等则导致函数失败。空白符:任何格式字符串中的单个空白符处理所有来自输入的可用连续空白符(如同通过于循环中调用
isspace
确定)。注意格式字符串中"\n"
、" "
、"\t\t"
或其他空白无区别。转换指示:每个转换指示拥有下列格式:
- 引入用
%
字符 - (可选) 赋值抑制字符
*****
。若存在此选项,则此函数不将结果赋值给任何接收用参数。 - (可选) 指定最大域宽的整数数字(大于零),即函数进行在当前转换指示所指定的转换时,允许处理的最大字符数。注意若不提供宽度,则
%s
和%[
可能导致缓冲区溢出。 - (可选) 指定接收参数大小的长度修饰符,即实际目标类型。这影响转换准确性和溢出规则。默认目标类型对每个转换类型不同(见下表)。
- 转换格式指示符
下列格式指示符可用:
- 引入用
...
:接收用参数
返回值:
- 成功赋值的接收参数的数量(可以为零,在首个接收用参数赋值前匹配失败的情况下),或者若输入在首个接收用参数赋值前发生失败,则为EOF。
示例
// 读入整数(跳过中间的所有连续空白符)
int a, b;
scanf("%d%d", &a, &b);
// 读入字符串到c风格字符串(读到空白符停止)
char s[10];
scanf("%s", s);
// 读入整数(跳过中间的所有连续空白符)
int a, b;
scanf("%d%d", &a, &b);
// 读入字符串到c风格字符串(读到空白符停止)
char s[10];
scanf("%s", s);
std::getline
在标头 <string>
定义。
getline
从输入流读取字符并将它们放进字符串。
用法
getline(input, str, delim='\n');
参数:
input
:获取数据来源的流str
:放置数据的目标字符串delim
:分隔字符
返回值:input
示例
// 读取一整行到c++风格字符串
string s;
getline(cin, s);
// 读取一整行到c++风格字符串
string s;
getline(cin, s);
cin.getline
std::basic_istream<CharT,Traits>::getline
从流释出字符,直至行尾或指定的分隔符 delim
。
用法
getline(s, count, delim='\n');
参数:
s
:指向要存储字符到的字符串的指针count
:s
所指向的字符串的大小delim
:释出所终止于的分隔字符,释出但不存储它
返回值:*this
示例
// 读取一整行到c风格字符串
char s[10];
cin.getline(s, 10);
// 读取一整行到c风格字符串
char s[10];
cin.getline(s, 10);
cin.get
std::basic_istream<CharT,Traits>::get
从流释出字符或多个字符。
用法
int get();
读取一个字符,若可用则返回它。否则,返回 Traits::eof()
并设置 failbit 和 eofbit 。
返回值:
- 释出的字符或
Traits::eof()
get(ch);
读取一个字符,而若可用则存储于 ch
。
参数:
ch
:到要写入结果到的字符的引用
返回值:
*this
get(s, count, delim='\n');
从流中提取字符并将它们作为字符串存储在 s
中,直到提取 '\n'
或 delim
(如果指定了此参数),如果找到分隔符,则不会从输入序列中提取,而是保留在那里作为要从流中提取的下一个字符。
参数:
s
:指向要存储结果到的字符串的指针count
:s
所指向的字符串的大小delim
:用以停止释出的分隔字符,不释出且不存储它
返回值:
*this
get(strbuf, delim='\n');
从流中提取字符并将它们插入到由流缓冲区对象 strbuf
控制的输出序列中,一旦这样的插入失败或在输入序列中遇到分隔符就停止,分隔符是 '\n'
或 delim
(如果指定了此参数)。
参数:
strbuf
:要读取内容到的流缓冲delim
:用以停止释出的分隔字符,不释出且不存储它
返回值:
*this
示例
// 读取单字符
char c;
c = cin.get();
cin.get(c);
// 读取c风格字符串
char s[20];
cin.get(s, 10, '.'); // 读取前 9 个字符或直到分隔符 '.'
// 读取单字符
char c;
c = cin.get();
cin.get(c);
// 读取c风格字符串
char s[20];
cin.get(s, 10, '.'); // 读取前 9 个字符或直到分隔符 '.'
fgets
在标头 <stdio.h>
定义。
从给定文件流读取最多 count - 1
个字符并将它们存储于 str
所指向的字符数组。若文件尾出现或发现换行符则终止分析,后一情况下 str
将包含一个换行符。若读入字节且无错误发生,则紧随写入到 str
的最后一个字符后写入空字符。
用法
fgets(str, count, stream);
参数:
str
:指向 char 数组元素的指针count
:写入的最大字符数(典型的为str
的长度)stream
:读取数据来源的文件流
返回值:
成功时为 str
,失败时为空指针。 若遇到文件尾条件导致了失败,则设置 stream
上的文件尾指示器(见 feof() )。这仅若它导致未读取字符才是失败,该情况下返回空指针且不改变 str
所指向数组的内容(即不以空字符覆写首字节)。 若某些其他错误导致了失败,则设置 stream
上的错误指示器(见 ferror() )。 str
所指向的数组内容是不确定的(甚至可以不是空终止)。
示例
// 从c标准输入中读入
char s[1010];
fgets(s, 1000, stdin);
// 从c标准输入中读入
char s[1010];
fgets(s, 1000, stdin);
fread
在标头 <stdio.h>
定义。
从给定输入流 stream
读取至多 count
个对象到数组 buffer
中。
用法
fread(buffer, size, count, stream);
参数:
buffer
:指向要读取的数组中首个对象的指针size
:每个对象的字节大小count
:要读取的对象数stream
:读取来源的输入文件流
返回值:
成功读取的对象数,若出现错误或读到文件尾,则可能小于 count
。 若 size
或 count
为 fread
返回 fread
不区别文件尾和错误,而调用者必须用 feof 和 ferror 鉴别出现者为何。
示例
// 从c标准输入中读入
char s[1000];
fread(s, 1, 1000, stdin);
// 从c标准输入中读入
char s[1000];
fread(s, 1, 1000, stdin);
常见输入样例
单组输入
输入整数、字符、...
int a, b;
scanf("%d%d", &a, &b);
int a, b;
scanf("%d%d", &a, &b);
int a, b;
cin >> a >> b;
int a, b;
cin >> a >> b;
输入字符串(空白符分隔)
char s[100];
scanf("%s", s);
char s[100];
scanf("%s", s);
string s;
cin >> s;
string s;
cin >> s;
多组输入
给定数量
int n;
scanf("%d", &n);
while (n--) {
int a, b;
scanf("%d%d", &a, &b);
}
int n;
scanf("%d", &n);
while (n--) {
int a, b;
scanf("%d%d", &a, &b);
}
int n;
cin >> n;
while (n--) {
int a, b;
cin >> a >> b;
}
int n;
cin >> n;
while (n--) {
int a, b;
cin >> a >> b;
}
读到文件尾结束
int a, b;
while (~scanf("%d%d", &a, &b)) {
// ...
}
int a, b;
while (~scanf("%d%d", &a, &b)) {
// ...
}
int a, b;
while (cin >> a >> b) {
// ...
}
int a, b;
while (cin >> a >> b) {
// ...
}
读到特殊输入结束
输入多组数,两个一组,读入单个 -1
结束:
int a, b;
while (~scanf("%d%d", &a, &b) && a != -1) {
// ...
}
int a, b;
while (~scanf("%d%d", &a, &b) && a != -1) {
// ...
}
int a, b;
while (cin >> a >> b && a != -1) {
// ...
}
int a, b;
while (cin >> a >> b && a != -1) {
// ...
}
整行输入
输入单行到字符串
char s[100];
cin.getline(s, 100);
char s[100];
cin.getline(s, 100);
string s;
getline(cin, s);
string s;
getline(cin, s);
char s[100];
fgets(s, 100, stdin);
char s[100];
fgets(s, 100, stdin);
输入多行直到文件尾结束
vector<string> ss;
string s;
while (getline(cin, s)) {
ss.push_back(s);
}
vector<string> ss;
string s;
while (getline(cin, s)) {
ss.push_back(s);
}
char ss[N][N];
int idx = 0;
while (cin.getline(ss[cnt], N)) ++idx;
char ss[N][N];
int idx = 0;
while (cin.getline(ss[cnt], N)) ++idx;
vector<char*> ss;
char s[N];
while (cin.getline(s, N)) {
char* tmp = new char[N];
strcpy(tmp, s);
ss.push_back(tmp);
}
vector<char*> ss;
char s[N];
while (cin.getline(s, N)) {
char* tmp = new char[N];
strcpy(tmp, s);
ss.push_back(tmp);
}
C++ 标准输入输出提速
太长不看版
int _ = []() {
ios::sync_with_stdio(false);
cin.tie(NULL), cout.tie(NULL);
return 0;
}();
int _ = []() {
ios::sync_with_stdio(false);
cin.tie(NULL), cout.tie(NULL);
return 0;
}();
取消 iostream 与 stdio 的同步
C++ 中 的 iostream 为了确保能和 C 中的 stdio 在同一文件操作时按顺序进行,而进行了一些额外的同步操作,这些操作会对性能造成一些影响。 取消同步后,性能可能会得到提升,但之后不应再与 stdio 混用,否则读写顺序上不能保证。
取消同步:
std::ios::sync_with_stdio(false);
std::ios::sync_with_stdio(false);
解除输入输出流的关联
C++ 中的 输入流 std::cin
默认是关联到 输出流 std::cout
的,任何试图从输入流 读取数据的操作都会先刷新关联的 输出流,这样输出流的缓冲区就会在输入前得到刷新。 关联输入输出流意味着所有输出(包括用户提示等)都会在输入前被打印出来,而不会有在进行输入时之前调用的输出没有得到显示的情况发生。
解除输入输出流的关联来提升性能:
std::cin.tie(NULL);
std::cin.tie(NULL);
重新关联:
std::cin.tie(&std::cout);
std::cin.tie(&std::cout);
跳过末尾空白符
#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');
#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');
重定向输入输出
// 将标准输入流重定向到 in.txt 文件
freopen("in.txt", "r", stdin);
// 将标准输出流重定向到 out.txt 文件
freopen("out.txt", "w", stdout);
// 将标准输入流重定向到 in.txt 文件
freopen("in.txt", "r", stdin);
// 将标准输出流重定向到 out.txt 文件
freopen("out.txt", "w", stdout);
__int128
及其输入输出
简介
_int128
即占用 128 字节的整数存储类型。范围为:unsigned __int128
,则范围变成
注意:__int128
仅 64 位 gcc/g++ 支持,并不在 C++ 标准中!
由于其不在 C++ 标准内,没有配套的 printf
,scanf
,cin
,cout
输入输出,只能手写。
输入
快读:
__int128 read() {
__int128 x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
__int128 read() {
__int128 x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
输出
快写:
void print(__int128 x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
void print(__int128 x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
Java
输入常用到的方法
Scanner
在 Java.util
包中定义。
一个简单的文本扫描程序,可以使用正则表达式解析基本类型和字符串。
使用
import Java.util.Scanner;
Scanner in = new Scanner(System.in);
import Java.util.Scanner;
Scanner in = new Scanner(System.in);
常用方法
方法 | 说明 |
---|---|
boolean hasNext() | 判断输入是否还有下一个输入项,若有,则返回 true ,反之 false |
String next() | 读取下一个输入项(读到分隔符停止),并返回为字符串 |
double nextDouble() | 读取下一个输入项(读到分隔符停止),并返回为双精度浮点数 |
double nextInt() | 读取下一个输入项(读到分隔符停止),并返回为整数 |
double nextLong() | 读取下一个输入项(读到分隔符停止),并返回为长整型数 |
String nextLine() | 读取下一行输入,并返回为字符串 |
BufferedReader
+ StreamTokenizer
在 Java.io
包中定义。
使用注意
StreamTokenizer
源码存在Type
,该Type
根据你输入内容来决定类型,倘若你输入类似于123oi
以数字开头的字符串,它会强制认为你的类型是double
类型,因此在读入中以double
类型去读String
类型便会抛出异常。StreamTokenizer
在读入以上大小的数字会丢失精度。
使用
import Java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
import Java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
常用方法
判断是否读到文件尾:
Javaif (in.nextToken() == in.TT_EOF) // ...
if (in.nextToken() == in.TT_EOF) // ...
读入一个字符串(读到空白符停止):
Javain.nextToken(); String s = in.sval;
in.nextToken(); String s = in.sval;
读入一个整数(读到空白符停止):
Javain.nextToken(); int n = (int) in.nval;
in.nextToken(); int n = (int) in.nval;
读入一个长整型(读到空白符停止)(读入
1e14
以上大小的数字会丢失精度。):Javain.nextToken(); int n = (long) in.nval;
in.nextToken(); int n = (long) in.nval;
读入一个双精度浮点型(读到空白符停止)(读入
1e14
以上大小的数字会丢失精度。):Javain.nextToken(); double n = in.nval;
in.nextToken(); double n = in.nval;
读入一行字符串(读到换行符停止):
JavaString line = br.readLine();
String line = br.readLine();
模板
import Java.util.*;
public static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in), 32768));
public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static double nextDouble() throws IOException { in.nextToken(); return in.nval; }
public static float nextFloat() throws IOException { in.nextToken(); return (float) in.nval; }
public static int nextInt() throws IOException { in.nextToken(); return (int) in.nval; }
public static String next() throws IOException { return in.sval; }
public static long nextLong() throws Exception { in.nextToken(); return (long) in.nval;}
import Java.util.*;
public static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in), 32768));
public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static double nextDouble() throws IOException { in.nextToken(); return in.nval; }
public static float nextFloat() throws IOException { in.nextToken(); return (float) in.nval; }
public static int nextInt() throws IOException { in.nextToken(); return (int) in.nval; }
public static String next() throws IOException { return in.sval; }
public static long nextLong() throws Exception { in.nextToken(); return (long) in.nval;}
Kattio
+ StringTokenizer
最常用的方法之一是使用来自 Kattis 的 Kattio.Java 来提高 IO 效率。这个方法会将 StringTokenizer
与 PrintWriter
包装在一个类中方便使用。而在具体进行解题的时候(假如赛会/组织方允许)可以直接使用这个模板。
下方即为应包含在代码中的 IO 模板,由于 Kattis 的原 Kattio 包含一些并不常用的功能,下方的模板经过了一些调整(原 Kattio 使用 MIT 作为协议)。
模板
class Kattio extends PrintWriter {
private BufferedReader r;
private StringTokenizer st;
// 标准 IO
public Kattio() { this(System.in, System.out); }
public Kattio(InputStream i, OutputStream o) {
super(o);
r = new BufferedReader(new InputStreamReader(i));
}
// 文件 IO
public Kattio(String intput, String output) throws IOException {
super(output);
r = new BufferedReader(new FileReader(intput));
}
// 在没有其他输入时返回 null
public String next() {
try {
while (st == null || !st.hasMoreTokens())
st = new StringTokenizer(r.readLine());
return st.nextToken();
} catch (Exception e) {}
return null;
}
public int nextInt() { return Integer.parseInt(next()); }
public double nextDouble() { return Double.parseDouble(next()); }
public long nextLong() { return Long.parseLong(next()); }
}
class Kattio extends PrintWriter {
private BufferedReader r;
private StringTokenizer st;
// 标准 IO
public Kattio() { this(System.in, System.out); }
public Kattio(InputStream i, OutputStream o) {
super(o);
r = new BufferedReader(new InputStreamReader(i));
}
// 文件 IO
public Kattio(String intput, String output) throws IOException {
super(output);
r = new BufferedReader(new FileReader(intput));
}
// 在没有其他输入时返回 null
public String next() {
try {
while (st == null || !st.hasMoreTokens())
st = new StringTokenizer(r.readLine());
return st.nextToken();
} catch (Exception e) {}
return null;
}
public int nextInt() { return Integer.parseInt(next()); }
public double nextDouble() { return Double.parseDouble(next()); }
public long nextLong() { return Long.parseLong(next()); }
}
使用
class Test {
public static void main(String[] args) {
Kattio io = new Kattio();
// 字符串输入
String str = io.next();
// int 输入
int num = io.nextInt();
// 输出
io.println("Result");
// 请确保关闭 IO 流以确保输出被正确写入
io.close();
}
}
class Test {
public static void main(String[] args) {
Kattio io = new Kattio();
// 字符串输入
String str = io.next();
// int 输入
int num = io.nextInt();
// 输出
io.println("Result");
// 请确保关闭 IO 流以确保输出被正确写入
io.close();
}
}
常见输入样例
单组输入
输入整数、小数、...
Scanner in = new Scanner(System.in);
int a = in.nextInt();
double b = in.nextDouble();
String s = in.next();
Scanner in = new Scanner(System.in);
int a = in.nextInt();
double b = in.nextDouble();
String s = in.next();
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int a = (int) in.nval;
in.nextToken();
double n = in.nval;
in.nextToken();
int s = in.sval;
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int a = (int) in.nval;
in.nextToken();
double n = in.nval;
in.nextToken();
int s = in.sval;
Kattio io = new Kattio();
int a = io.nextInt();
double b = io.nextDouble();
String s = io.next();
Kattio io = new Kattio();
int a = io.nextInt();
double b = io.nextDouble();
String s = io.next();
输入字符串(空白符分隔)
Scanner in = new Scanner(System.in);
String s = in.next();
Scanner in = new Scanner(System.in);
String s = in.next();
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int s = in.sval;
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int s = in.sval;
Kattio io = new Kattio();
String s = io.next();
Kattio io = new Kattio();
String s = io.next();
多组输入
给定数量
Scanner in = new Scanner(System.in);
int n = in.nextInt();
while (n-- > 0) {
int a = in.nextInt();
int b = in.nextInt();
}
Scanner in = new Scanner(System.in);
int n = in.nextInt();
while (n-- > 0) {
int a = in.nextInt();
int b = in.nextInt();
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int n = (int) in.nval;
while (n-- > 0) {
in.nextToken();
int a = (int) in.nval;
in.nextToken();
int b = (int) in.nval;
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int n = (int) in.nval;
while (n-- > 0) {
in.nextToken();
int a = (int) in.nval;
in.nextToken();
int b = (int) in.nval;
}
Kattio io = new Kattio();
int n = io.nextInt();
while (n-- > 0) {
int a = io.nextInt();
int b = io.nextInt();
}
Kattio io = new Kattio();
int n = io.nextInt();
while (n-- > 0) {
int a = io.nextInt();
int b = io.nextInt();
}
读到文件尾结束
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int a = in.nextInt();
int b = in.nextInt();
}
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int a = in.nextInt();
int b = in.nextInt();
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int a, b;
while (in.nextToken() != in.TT_EOF) {
a = (int) in.nval;
b = (int) in.nval;
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int a, b;
while (in.nextToken() != in.TT_EOF) {
a = (int) in.nval;
b = (int) in.nval;
}
Kattio io = new Kattio();
String tmp;
while ((tmp = io.next()) != null) {
int a = Integer.parseInt(tmp);
int b = io.nextInt();
}
Kattio io = new Kattio();
String tmp;
while ((tmp = io.next()) != null) {
int a = Integer.parseInt(tmp);
int b = io.nextInt();
}
读到特殊输入结束
输入多组数,两个一组,读入单个 -1
结束:
Scanner in = new Scanner(System.in);
int a, b;
while (in.hasNext() && (a = in.nextInt()) != -1) {
b = in.nextInt();
}
Scanner in = new Scanner(System.in);
int a, b;
while (in.hasNext() && (a = in.nextInt()) != -1) {
b = in.nextInt();
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int a, b;
while (in.nextToken() != in.TT_EOF && (a = (int) in.nval) != 0) {
in.nextToken();
b = (int) in.nval;
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int a, b;
while (in.nextToken() != in.TT_EOF && (a = (int) in.nval) != 0) {
in.nextToken();
b = (int) in.nval;
}
Kattio io = new Kattio();
String tmp;
int a, b;
while ((tmp = io.next()) != null && (a = Integer.parseInt(tmp)) != -1) {
b = io.nextInt();
}
Kattio io = new Kattio();
String tmp;
int a, b;
while ((tmp = io.next()) != null && (a = Integer.parseInt(tmp)) != -1) {
b = io.nextInt();
}
整行输入
输入单行到字符串
Scanner in = new Scanner(System.in);
String s = in.nextLine();
Scanner in = new Scanner(System.in);
String s = in.nextLine();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String s = in.readLine();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String s = in.readLine();
输入多行直到文件尾结束
Scanner in = new Scanner(System.in);
String[] s = new String[N];
int idx = 0;
while (in.hasNextLine()) s[++idx] = in.nextLine();
Scanner in = new Scanner(System.in);
String[] s = new String[N];
int idx = 0;
while (in.hasNextLine()) s[++idx] = in.nextLine();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] s = new String[N];
int idx = 0;
while (in.ready()) s[++idx] = in.readLine();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] s = new String[N];
int idx = 0;
while (in.ready()) s[++idx] = in.readLine();