티스토리 뷰
아마 이 글은 백준 코딩용이 될 것이다. 풀면서 시간이나 메모리를 절약할 수 있는 방법이 있는 글이다.
주로 FastIO를 다룰 것 같다. 우선 readInt, readChar, writeInt에 대해 다뤄보자.
우선 read부분을 다뤄보자.
#define MAX 1<<20
char rbuf[MAX];
char wbuf[MAX];
int idx, nidx, widx;
inline char read(){
if(idx == nidx){
nidx = fread(rbuf, 1, MAX, stdin);
if(!nidx) return 0;
idx = 0;
}
return rbuf[idx++];
}
inline int readInt(){
int sum = 0;
char now = read();
bool flg = false;
while(now <= 32) now = read();
if(now == 45) flg = true, now = read();
while(now >= 48) sum = sum * 10 + now - '0', now = read();
return flg ? -sum : sum;
}
inline void readString(std::string& s){
char tmp[101];
char now = read();
int index = 0;
while(now <= 32) now = read();
while(now >= 50) tmp[index++] = now, now = read();
tmp[index] = '\0';
s = std::string(tmp);
}
readInt를 먼저 보자. sum이 리턴할 값이고, flg는 음수, 양수를 결정해주는 변수이다. now를 통해 sum의 값이 변경된다.
while문을 보면 now <= 32일 때 now =read()로 read함수를 불러온다. 이 문장에서 알아야 할 점이 2가지가 있다.
1. now <= 32
2. read()
2번부터 해보자. read()함수를 살펴보자. idx 와 nidx가 같으면 fread로 buf에 stdin에 있는 입력값을 저장해준다. 그리고 idx를 0으로 초기화 해주고 buf[idx++]를 반환해준다. 그러니까 idx와 nidx가 같아지면 새롭게 buf에 입력할 값을 저장해주고, 같지 않다면 buf에 있는 값을 idx에 맞게 순서대로 반환해주는 것이다.
이제 read()함수가 이해됐을 것이다.
1번을 이해해보자. 그러면 now변수에 read()로 불러온 char형이 저장될 것이다. 우리는 숫자를 제외한 값들은 필요가 없다. 예를 들면 ' '과 '\n'의 입력값은 필요가 없다. 이것에 해당하는 아스키 코드는 각각 32번, 10번이다. 32번 이하의 값이 now에 저장이 된다면 다시 read()함수로 새로운 값을 입력받게 하는 것이다.
이제 첫번째 while문이 이해가 됐을 것이다.
다음으로 if문이다. 이것은 반환할 sum의 부호를 결정해준다.
'-'기호는 아스키코드로 45번이다. 그렇기 때문에 now의 값이 32이하가 아니고, 음수라면 해당 if문이 실행될 것이다. 실행이 된다면 flg의 값을 true로 변경, now의 값을 다음 값으로 바꿔준다.
다음 while문이다.
sum에 값을 저장해야 한다. 만약 15346의 값이 buf에 순서대로 있다면 우리는 이렇게 할 수 있다.
sum = 1;
sum = 1 * 10 + 5; -> 15
sum = 15 * 10 + 3 -> 153
sum = 153 * 10 + 4 -> 1534
sum = 1534 * 10 + 6 -> 15346
-> now <= 32로 while문 종료
이런식의 느낌으로 sum에 값이 저장되는 것이다.
마지막으로 return할 때 flg ? -sum : sum을 해주어 flg가 true라면 음수의 값을, flg가 false라면 양수의 값을 마지막으로 반환해준다.
이것을 응용하면 실수값도 할 수 있다.
다음으로 write 부분이다.
#define MAX 1<<20
char rbuf[MAX];
char wbuf[MAX];
int idx, nidx, widx;
inline int unitSize(int n){
if(n < 0) n = -n;
int isz = 1;
while(n >= 10){
isz++;
n /= 10;
}
return isz;
}
inline void bflush(){
fwrite(wbuf, 1, widx, stdout);
widx = 0;
}
inline void write(char c){
if(widx == MAX) bflush();
wbuf[widx++] = c;
}
inline void writeInt(int n){
int isz = unitSize(n);
if(widx + isz >= MAX) bflush();
if(n < 0) {
n = -n;
wbuf[widx++] = '-';
}
int next = widx + isz;
while(isz--){
wbuf[widx + isz] = n % 10 + '0';
n /= 10;
}
widx = next;
write(' ');
}
inline void writeString(std::string s){
int isz = 1;
while(s[isz] != '\0') isz++;
if(isz + widx >= (1<<20)) bflush();
for(int i = 0; i<isz; i++) wbuf[widx++] = s[i];
write('\n');
}
write가 살짝 더 어렵다.
writeInt를 먼저 살펴보자.
isz를 unitSize(n)으로 시작하기 때문에 isz의 의미를 먼저 설명하고 unitSize로 가보자. 입력된 n의 자릿수를 알아야 한다. 그 이유는 나중에 설명하고 unitSize로 바로 가보자.
unitSize를 보면 while(n >= 10) {... n /= 10; ...} 으로 되어있다. 그러니까 n의 자릿수를 반환해주는 것이다. 여기에서 음수 처리도 해야 한다는 것을 조심!
다음으로 if문을 봐보자. if문의 조건은 나중에 생각하고 bflush()함수를 먼저 보자.
bflush()함수는 wbuf에 저장되어 있는 값들을 char형의 크기가 1 이므로, 사이즈 1의 widx까지의 값을 stdout을 통해 출력하겠다는 의미이다. 그리고 widx를 0으로 바꿔준다. 그러니까 우리는 widx가 MAX를 넘어가면 안되기 때문에 MAX를 넘어가기 전에 출력을 해줘야 한다. 그렇기 때문에 우리가 입력할 값의 isz에 이미 입력되어 있는 widx의 합이 MAX를 넘어가기 전에 bflush()로 출력을 해주는 것이다.
다음 if문은 입력된 값이 음수라면 '-'기호를 wbuf에 저장해줘야 한다. 그리고 widx의 값을 1 증가시킨다.
여기에서 next변수가 필요하다.
왜냐하면 만약 15346의 값을 wbuf에 입력하고 싶다고 하자. 이것을 15346순서대로 저장해야 한다. 가장 편한 방법은 15346 % 10으로 6먼저 저장하는 것이다. 그렇기 때문에 다음 값을 저장할 위치를 먼저 저장하는 것이다.
다음 while문을 살펴보면 isz를 하나씩 줄이면서 6, 4, 3, 5, 1을 순서대로 저장하는 것을 확인할 수 있다.
그리고 widx를 next의 값으로 바꿔준다. 즉, 다음 숫자가 저장될 위치가 된다.
다음으로 공백을 write함수를 통해 넣어준다.
write는 혼자 해석해보자~
'코딩 씹어먹기 > C++' 카테고리의 다른 글
[C++] deque 라이브러리 (0) | 2022.07.14 |
---|---|
[C++] unordered_map 라이브러리 (0) | 2022.07.02 |
[C++] map 라이브러리 (0) | 2022.06.27 |
[C++] queue 라이브러리 (0) | 2022.06.27 |
[C++] numeric 라이브러리 (0) | 2022.06.23 |
- Total
- Today
- Yesterday
- Set
- bits/stdc++.h
- deque와 vector의 차이
- cin.tie(nullptr);
- readString
- Witcher3
- 큰 수 계산
- 에라토스테네스의 체
- fastIo
- 행렬 멱법
- readInt
- 좌표 압축 알고리즘
- unistd.h
- manber myers
- scanf
- ios::sync_with_stdio(false)
- list
- portal1
- 해시맵
- 분할정복
- fread
- 트리보나치
- writeInt
- 확장 유클리드
- SCC 알고리즘
- 피보나치
- 플로이드-워셜
- tsp알고리즘
- writeString
- 비트마스킹
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |