FHVirus' 隨筆

FHVirus IO

FHVirus 2020-10-18

因為是 FHVirus,所以第一篇就來寫輸入輸出吧。

正常的輸入輸出

大家都應該要會的東西。

IOStream

輸出入串流,最適合初學者使用的東西。 不用自己判斷型別,但是大部分時候偏慢。

1
2
3
4
#include<iostream>
int a;
std::cin >> a;
std::cout << a << endl;

本人覺得沒有到很好用(尤其是輸出的時候,一堆數字加空格很麻煩),但是可以應付大部分工作(例如 CodeForces 的比賽)。

Faster IOStream

輸入輸出量很大 ( $10^6$ ) 的時候,直接用 IOStream 極有可能會 TLE。這個時候⋯⋯

1
2
3
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

main() 一開頭加上這三行,並用 '\n'(換行字元) 取代 endl(換行 + flush,因為有 flush 所以會很慢),通常就可以過了,而且時間會少很多。 至於為什麼,網路上都有,我懶得寫 OW<)b 也有很多人會在程式開頭加上這兩行:

1
2
#define OW0 ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'

其中 OW0 可以是任何自己喜歡而且不會與變數函數撞名的東東(例如「艾蜜莉亞我婆」、「8e7好強」之類的)。

cstdIO

通常比 IOStream 快(有點多)。指定輸出格式時超好用。

1
2
3
4
#include<cstdio>
int a;
scanf("%d", &a);
printf("%d", a);

剛開始可能會覺得很麻煩,一旦會了就超方便(指定小數位數、寬度、輸入字串直到指定字元等等)。 懶的寫教學,自己查 reference。

GetLine

顧名思義,輸入一整行的時候可以用的東西。 輸入都要一行一行讀而且輸入量大的時候, GetLine 會比其他方法都快(例題待補)。

1
2
3
4
#include<iostream>
#include<string>
string s;
std::getline(cin, s);

Others

1
2
3
4
5
#include<cstdio>
char c;
c = getchar();
putchar(c);
puts("Jizz");

有時候只有要輸出 "Yes""No" 的時候就可以用 puts()puts() 會自己多一個換行(像 Python 一樣)。

另外, putchargetchar 可以換成 putchar_unlockedgetchar_unlocked,似乎會比較快。


毒瘤壓常輸入輸出

壓 TopCoder / 怪題要會的。 用來造福(X)毒害(O)大眾的東東。

readchar

蛋餅那裡出來的。

1
2
3
4
5
6
#include<cstdio>
inline char readchar(){
	const int S = 1<<16;
	static char buf[S], *p = buf, *q = buf;
	return p == q and (q = (p = buf) + fread(buf, 1, S, stdin)) == buf ? EOF : *p++;
}

其中, S 的大小可以自己調整。 fread 會回傳實際輸入的大小(大概是位元數吧)。

the R function

這裡提供兩種版本,方便使用但特殊情況會錯的和正確的。

1
2
3
4
5
6
7
inline int R(){
	int ans = 0; char c = readchar(); bool minus = false;
	while((c < '0' or c > '9') and c != '-' and c != EOF) c = readchar();
	if(c == '-') minus = true, c = readchar();
	while(c >= '0' and c <= '9') ans = ans * 10 + (c ^ '0'), c = readchar();
	return minus ? -ans : ans;
}

可以根據題目輸入形式化簡。 不要問我為何用 xor ,在下也不知道。 這個版本在輸入 -2147483648 的時候會爆炸。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
inline int R(int &a){
	static char c;
	while(((c = readchar()) < '0' or c > '9') and c != '-' and c != EOF);
	if(c == '-'){
		a = 0;
		while((c = readchar()) >= '0' and c <= '9') a *= 10, a -= c ^ '0';
	} else {
		a = c ^ '0';
		while((c = readchar()) >= '0' and c <= '9') a *= 10, a += c ^ '0';
	}
}

用了參照及 static ,似乎空間比較小吧。

the W funciton

筆者自行研發的。使用上有點麻煩,不推薦日常使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
char outbuf[S]; int outp;
inline void W(int n){
	static char buf[12], p;
	if(n == 0) outbuf[outp++] = '0';
	p = 0;
	if(n < 0){
		outbuf[outp++] = '-';
		while(n) buf[p++] = '0' - (n % 10), n /= 10;
	} else {
		while(n) buf[p++] = '0' + (n % 10), n /= 10;
	}
	for(--p; p >= 0; --p) outbuf[outp++] = buf[p];
	outbuf[outp++] = '\n';
	if(outp > S-12) fwrite(outbuf, 1, outp, stdout), outp = 0;
}

int main(){
	// ...do something
	fwrite(outbuf, 1, outp, stdout);
}

大概就是把所有輸出寫到一個 buffer 。程式結束前記得把剩下的東西 fwrite 出來喔。

the RD function

很少很少會用到,但是寫了就丟上來吧。基本上只是為了某題寫了之後就丟在模板裡了。 這個只能讀 0 ~ 1 之間的小數喔。

1
2
3
4
5
6
7
inline double RB(){
	double ans = 0, mult = .1; char c = readchar();
	while(c != '.') c = readchar();
	c = readchar();
	while(c >= '0' and c <= '9') ans += mult * (c - '0'), mult *= .1, c = readchar();
	return ans;
}

the RD, RS… functions

待補。 反正每次寫都是再刻一次,也不算模板。


毒中之毒

一些怪東東:

如果有人知道其他神奇毒瘤麻煩告訴我 ><

最後,附上極簡版


10/27 更新,感謝油油的 cwcodinglife 提醒我修正 readchar()