Nhảy chuyển đến

Đọc nhập, phát ra ưu hoá

Ở cam chịu dưới tình huống,std::cin/std::coutLà cực kỳ chậm chạp đọc nhập / phát ra phương thức, màscanf/printfSostd::cin/std::coutMau đến nhiều.

Chú ý

cin/coutCùngscanf/printfThực tế tốc độ kém sẽ tùy biên dịch khí cùng thao tác hệ thống bất đồng phát sinh nhất định thay đổi. Nếu muốn tiến hành kỹ càng tỉ mỉ đối lập, thỉnh lấy thực tế thí nghiệm kết quả vì chuẩn.

Bên dưới đem kỹ càng tỉ mỉ giới thiệu đọc nhập phát ra ưu hoá phương pháp.

Đóng cửa đồng bộ / giải trừ trói định

std::ios::sync_with_stdio(false)

Cái này hàm số là một cái “Hay không kiêm dung stdio” chốt mở, C++ vì kiêm dung C, bảo đảm trình tự ở sử dụngprintfCùngstd::coutThời điểm không phát sinh hỗn loạn, đem phát ra lưu trói tới rồi cùng nhau. Đồng bộ phát ra lưu là tuyến trình an toàn.

Này kỳ thật là C++ vì kiêm dung mà áp dụng bảo thủ thi thố, cũng là sửcin/coutTốc độ so chậm nguyên nhân chủ yếu. Chúng ta có thể tại tiến hành IO thao tác phía trước đem stdio giải trừ trói định, nhưng là ở như vậy làm lúc sau phải chú ý không thể đồng thời sử dụngstd::cinCùngscanf,Cũng không thể đồng thời sử dụngstd::coutCùngprintf,Nhưng là có thể đồng thời sử dụngstd::cinCùngprintf,Cũng có thể đồng thời sử dụngscanfCùngstd::cout.

tie

tie là đem hai cái stream trói định hàm số, không tham số nói phản hồi trước mặt phát ra lưu kim đồng hồ.

Ở cam chịu dưới tình huốngstd::cin.tie()Trói định chính là&std::cout,Mỗi lần tiến hành cách thức hóa đưa vào thời điểm đều phải thuyên chuyểnstd::cout.flush()Quét sạch phát ra giảm xóc khu, như vậy sẽ gia tăng IO gánh nặng. Có thể thông quastd::cin.tie(nullptr)Tới giải trừ trói định, tiến thêm một bước nhanh hơn chấp hành hiệu suất.

Nhưng yêu cầu chú ý chính là, ở giải trừstd::cinCùngstd::coutTrói định sau, trình tự trung cần thiết tay độngflushMới có thể bảo đảm mỗi lầnstd::coutBày ra nội dung có thể ởstd::cinTrước xuất hiện. Đây là bởi vìstd::coutBị buffer vì cam chịu thiết trí. Tỷ như:

1
2
3
4
5
6
std::cout"Please input your name:"
std::flush;// hoặc là: std::endl;
// bởi vì mỗi lần thuyên chuyển std::endl đều sẽ flush phát ra giảm xóc khu, mà \n
// tắc sẽ không.
// nhưng thỉnh cẩn thận sử dụng, quá nhiều flush sẽ ảnh hưởng trình tự hiệu suất
std::cin>>name;

Số hiệu thực hiện

1
2
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);

Đọc nhập ưu hoá

scanfCùngprintfVẫn như cũ có ưu hoá không gian, đây là tấu chương sở giới thiệu nội dung —— đọc nhập cùng phát ra ưu hoá.

  • Chú ý, bổn giao diện trung giới thiệu đọc nhập cùng phát ra ưu hoá đều nhằm vào chỉnh hình số liệu, nếu muốn duy trì mặt khác loại hình số liệu ( như phù điểm số ), nhưng tự hành dựa theo bổn giao diện giới thiệu ưu hoá nguyên lý tới biên soạn số hiệu.

Nguyên lý

Mọi người đều biết,getcharLà dùng để đọc nhập 1 byte số liệu cũng đem này thay đổi vìcharLoại hình hàm số, thả tốc độ thực mau, cố có thể dùng “Đọc nhập tự phù —— thay đổi vì chỉnh hình” tới thay thế thong thả đọc nhập.

Mỗi cái số nguyên từ hai bộ phận tạo thành —— ký hiệu cùng con số.

Số nguyên '+' thông thường là tỉnh lược, thả sẽ không đối mặt sau con số sở đại biểu giá trị sinh ra ảnh hưởng, mà '-' không thể tỉnh lược, bởi vậy phải tiến hành phán định.

10 tiến chế số nguyên trung là không chứa không cách hoặc trừ 0~9 cùng chính dấu trừ ngoại mặt khác tự phù, bởi vậy ở đọc nhập không ứng tồn tại với số nguyên trung tự phù ( thông thường vì không cách ) khi, liền có thể phán định đã đọc nhập kết thúc.

C cùng C++ ngôn ngữ phân biệt ở ctype.h cùng cctype đầu văn kiện trung, cung cấp hàm sốisdigit,Cái này hàm số sẽ kiểm tra truyền vào tham số hay không vì số thập phân con số tự phù, là tắc phản hồitrue,Nếu không phản hồifalse.Đối ứng, ở dưới số hiệu trung, có thể sử dụngisdigit(ch)Thay thếch >= '0' && ch, cũng có thể sử dụng!isdigit(ch)Thay thếch '9'.

Số hiệu thực hiện

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
intread(){
intx=0,w=1;
charch=0;
while(ch'0'||ch>'9'){// ch không phải con số khi
if(ch=='-')w=-1;// phán đoán hay không vì phụ
ch=getchar();// tiếp tục đọc nhập
}
while(ch>='0'&&ch'9'){// ch là con số khi
x=x*10+(ch-'0');// đem tân đọc nhập con số “Thêm” ở x mặt sau
// x là int loại hình, char loại hình ch cùng '0' sẽ bị tự động chuyển vì này đối ứng
// ASCII mã, tương đương với đem ch chuyển hóa vì đối ứng con số
// nơi này cũng có thể sử dụng (x
ch=getchar();// tiếp tục đọc nhập
}
returnx*w;// con số * chính dấu trừ = thực tế trị số
}
  • Nêu ví dụ

Đọc nhập num nhưng viết vìnum=read();.

Phát ra ưu hoá

Nguyên lý

Đồng dạng là mọi người đều biết,putcharLà dùng để phát ra đơn cái tự phù hàm số.

Bởi vậy đem con số mỗi một vị chuyển hóa vì tự phù phát ra lấy gia tốc.

Phải chú ý chính là, dấu trừ muốn đơn độc phán đoán phát ra, hơn nữa mỗi lần % ( mod ) lấy ra chính là con số mạt vị, bởi vậy muốn đảo ngược phát ra.

Số hiệu thực hiện

1
2
3
4
5
6
7
8
voidwrite(intx){
if(x0){// phán phụ + phát ra dấu trừ + biến nguyên số vì số dương
x=-x;
putchar('-');
}
if(x>9)write(x/10);// đệ quy, đem trừ cuối cùng một vị ngoại mặt khác bộ phận phóng tới đệ quy trung phát ra
putchar(x%10+'0');// đã phát ra ( đệ quy ) xong x mạt vị trước sở hữu con số, phát ra mạt vị
}

Nhưng là đệ quy thực hiện hằng số là trọng đại, chúng ta có thể viết một cái sạn tới thực hiện cái này quá trình.

1
2
3
4
5
6
7
8
voidwrite(intx){
staticintsta[35];
inttop=0;
do{
sta[top++]=x%10,x/=10;
}while(x);
while(top)putchar(sta[--top]+48);// 48 là '0'
}
  • Nêu ví dụ

Phát ra num nhưng viết vìwrite(num);.

Càng mau đọc nhập / phát ra ưu hoá

Thông quafreadHoặc làmmapCó thể thực hiện càng mau đọc nhập.

freadCó thể đem yêu cầu văn kiện bộ phận đọc đi vào tồn giảm xóc khu.mmapTắc sẽ điều hành nội hạch cấp hàm số, đem văn kiện dùng một lần mà chiếu rọi đến nội tồn trung, cùng loại với có thể kim đồng hồ trích dẫn nội tồn khu vực. Cho nên ở hằng ngày trình tự đọc viết khi, chỉ cần lặp lại đọc lấy bộ phận văn kiện có thể sử dụngfread,Bởi vì nếu dùngmmapLặp lại đọc lấy một tiểu khối văn kiện, làm dùng một lần nội tồn chiếu rọi hơn nữa nội hạch xử lý page fault tiêu phí sẽ xa so sử dụngfreadNội hạch cấp hàm số điều hành đại.

Đồng thờifreadCùngmmapBởi vì là chỉnh đoạn chỉnh đoạn đọc lấy, viết nhập, cho nên sogetchar()/putchar()Muốn mau nhiều. Hơn nữammapBảo đảm tiến trình gian tự động cùng chung, tồn trữ khu nếu có thể cũng sẽ cùng nội hạch hoãn tồn chia sẻ tin tức, bảo đảm càng thiếu copy thao tác.

freadCùng loại với tham số vì"%s"scanf,Bất quá nó càng vì nhanh chóng, hơn nữa có thể dùng một lần đọc nhập bao nhiêu cái tự phù ( bao gồm không cách đổi hành chờ chế biểu phù ), nếu hoãn tồn khu cũng đủ đại, thậm chí có thể dùng một lần đọc nhập toàn bộ văn kiện.

Đối với phát ra, chúng ta còn có đối ứngfwriteHàm số.

1
2
3
4
std::size_tfread(void*buffer,std::size_tsize,std::size_tcount,
std::FILE*stream);
std::size_tfwrite(constvoid*buffer,std::size_tsize,std::size_tcount,
std::FILE*stream);

Sử dụng thí dụ mẫu:fread(Buf, 1, SIZE, stdin),Tỏ vẻ từ stdin văn kiện lưu trung đọc nhập SIZE cái lớn nhỏ vì 1 byte số liệu khối đến Buf trung.

Đọc nhập lúc sau sử dụng liền cùng bình thường đọc nhập ưu hoá tương tự, chỉ cần trọng định nghĩa một chút getchar. Nó nguyên lai là từ văn kiện trung đọc nhập một cái char, hiện tại biến thành từ Buf trung đọc nhập một cái char, cũng chính là đầu kim đồng hồ về phía sau di động một vị.

1
2
3
4
5
charbuf[120],*p1,*p2;
#define gc() \
(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1
?EOF \
:*p1++)

fwriteCũng là cùng loại, trước để vào một cáiOutBuf[MAXSIZE]Trung, cuối cùng thông quafwriteDùng một lần đemOutBufPhát ra.

Tham khảo số hiệu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
namespaceIO{
constexprintMAXSIZE=120;
charbuf[MAXSIZE],*p1,*p2;
#define gc() \
(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) \
?EOF \
:*p1++)

intrd(){
intx=0,f=1;
charc=gc();
while(!isdigit(c)){
if(c=='-')f=-1;
c=gc();
}
while(isdigit(c))x=x*10+(c^48),c=gc();
returnx*f;
}

charpbuf[120],*pp=pbuf;

voidpush(constchar&c){
if(pp-pbuf==120)fwrite(pbuf,1,120,stdout),pp=pbuf;
*pp++=c;
}

voidwrite(intx){
staticintsta[35];
inttop=0;
do{
sta[top++]=x%10,x/=10;
}while(x);
while(top)push(sta[--top]+'0');
}
}// namespace IO

mmapLà linux hệ thống thuyên chuyển, có thể đem văn kiện dùng một lần mà chiếu rọi đến nội tồn trung. Ở một ít cảnh tượng hạ có càng ưu tốc độ.

Chú ýmmapKhông thể ở Windows hoàn cảnh hạ sử dụng ( tỷ như CodeForces tester ), đồng thời cũng không kiến nghị ở chính thức trên sân thi đấu sử dụng, có thể ở tạp thường khi sử dụng. Ở sử dụng trước muốn dẫn vàofcntl.h,unistd.h,sys/stat.hCùngsys/mman.h.

Đọc nhập thí dụ mẫu: Đầu tiên muốn thu hoạch văn kiện miêu tả phùfd,Sau đó thông quafstatThu hoạch văn kiện tin tức lấy được đến văn kiện lớn nhỏ, từ nay về sau thông quachar *pc = (char *) mmap(NULL, state.st_size, PROT_READ, MAP_PRIVATE, fd, 0);Ngón tay giữa châm*pcChỉ hướng chúng ta văn kiện. Có thể trực tiếp dùng*pc ++Thay thếgetchar().

Khi chúng ta muốn đệ trình không sử dụng văn kiện thao tác đề mục khi, có thể đemfdThiết vì0,Tỏ vẻ từ stdin đọc nhập.Nhưng là, đối stdin sử dụng mmap là cực kỳ nguy hiểm hành vi, đồng thời không thể ở đầu cuối đưa vào, chúng ta không kiến nghị ngài làm như vậy.

Tham khảo số hiệu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include&LTbits/stdc++.h>
#include&LTfcntl.h>
#include&LTsys/mman.h>
#include&LTsys/stat.h>
#include&LTunistd.h>
char*pc;

intrd(){
intx=0,f=1;
charc=*pc++;
while(!isdigit(c)){
if(c=='-')f=-1;
c=*pc++;
}
while(isdigit(c))x=x*10+(c^48),c=*pc++;
returnx*f;
}

intmain(){
intfd=open("*.in",O_RDONLY);
structstatstate;
fstat(fd,&state);
pc=(char*)mmap(NULL,state.st_size,PROT_READ,MAP_PRIVATE,fd,0);
close(fd);
printf("%d",rd());
}

Đưa vào phát ra giảm xóc

printfCùngscanfLà có giảm xóc khu. Này cũng chính là vì cái gì, nếu đưa vào hàm số theo sát ở phát ra hàm số lúc sau / phát ra hàm số theo sát ở đưa vào hàm số lúc sau khả năng dẫn tới sai lầm.

Đổi mới phát ra giảm xóc khu điều kiện

  1. Trình tự kết thúc;
  2. Đóng cửa văn kiện;
  3. printfPhát ra\rHoặc là\nĐến đầu cuối thời điểm ( chú: Nếu là phát ra đến văn kiện, tắc sẽ không đổi mới giảm xóc khu );
  4. Tay độngfflush();
  5. Giảm xóc khu mãn tự động đổi mới;
  6. coutPhát raendl;
  7. Tay độngcout.flush().

Sử đưa vào phát ra ưu hoá càng vì thông dụng

Nếu ngươi trình tự sử dụng nhiều loại hình lượng biến đổi, như vậy khả năng yêu cầu viết nhiều đưa vào phát ra ưu hoá hàm số. Phía dưới cấp ra số hiệu sử dụngC++ trungtemplateThực hiện đối với sở hữu số nguyên loại hình đưa vào phát ra ưu hoá.

1
2
3
4
5
6
7
8
9
10
// thanh minh template loại, yêu cầu cung cấp đưa vào loại hình T, cũng lấy này loại hình định nghĩa nội liên hàm số read()
templatetypenameT>
Tread(){
Tsum=0,fl=1;// đem sum,fl cùng ch lấy đưa vào loại hình định nghĩa
intch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
returnsum*fl;
}

Nếu muốn phân biệt đưa vàointLoại hình lượng biến đổi a,long longLoại hình lượng biến đổi b cùng__int128Loại hình lượng biến đổi c, như vậy có thể viết thành:

1
2
3
a=readint>();
b=readlonglong>();
c=read__int128>();

Hoàn chỉnh mang điều chỉnh thử bản

Đóng cửa điều chỉnh thử chốt mở khi sử dụngfread(),fwrite(),Rời khỏi khi tự động tích cấu chấp hànhfwrite().

Mở ra điều chỉnh thử chốt mở khi sử dụnggetchar(),putchar(),Dễ bề điều chỉnh thử.

Nếu muốn mở ra văn kiện đọc viết khi, thỉnh ở sở hữu đọc viết phía trước gia nhậpfreopen().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// #define DEBUG 1 // điều chỉnh thử chốt mở
structIO{
#define MAXSIZE (1
#define isdigit(x) (x >= '0' && x
charbuf[MAXSIZE],*p1,*p2;
charpbuf[MAXSIZE],*pp;
#if DEBUG
#else
IO():p1(buf),p2(buf),pp(pbuf){}

~IO(){fwrite(pbuf,1,pp-pbuf,stdout);}
#endif
chargc(){
#if DEBUG// điều chỉnh thử, nhưng biểu hiện tự phù
returngetchar();
#endif
if(p1==p2)p2=(p1=buf)+fread(buf,1,MAXSIZE,stdin);
returnp1==p2?' ':*p1++;
}

boolblank(charch){
returnch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}

templateclassT>
voidread(T&x){
doubletmp=1;
boolsign=false;
x=0;
charch=gc();
for(;!isdigit(ch);ch=gc())
if(ch=='-')sign=1;
for(;isdigit(ch);ch=gc())x=x*10+(ch-'0');
if(ch=='.')
for(ch=gc();isdigit(ch);ch=gc())
tmp/=10.0,x+=tmp*(ch-'0');
if(sign)x=-x;
}

voidread(char*s){
charch=gc();
for(;blank(ch);ch=gc());
for(;!blank(ch);ch=gc())*s++=ch;
*s=0;
}

voidread(char&c){for(c=gc();blank(c);c=gc());}

voidpush(constchar&c){
#if DEBUG// điều chỉnh thử, nhưng biểu hiện tự phù
putchar(c);
#else
if(pp-pbuf==MAXSIZE)fwrite(pbuf,1,MAXSIZE,stdout),pp=pbuf;
*pp++=c;
#endif
}

templateclassT>
voidwrite(Tx){
if(x0)x=-x,push('-');// số âm phát ra
staticTsta[35];
Ttop=0;
do{
sta[top++]=x%10,x/=10;
}while(x);
while(top)push(sta[--top]+'0');
}

templateclassT>
voidwrite(Tx,charlastChar){
write(x),push(lastChar);
}
}io;

Tham khảo

cin.tie cùng sync_with_stdio gia tốc đưa vào phát ra - nông dân code tràng

C++ cao tốc hóa - Heavy Watal

'Re: mmap/mlock performance versus read' - MARC