{ }codelper
표준 라이브러리 컨테이너참조P0085

참조로 받는 재고 장부

창고 재고를 물건 이름 → 개수로 std::map에 담고, 명령 n개를 차례로 처리하라.
명령마다 함수를 하나씩 만들고, 재고를 바꾸는 함수는 map을 참조(&)로, 읽기만 하는 함수는 const 참조로 받는다. - add 이름 k: 그 물건을 k개 더하고, 더한 뒤 개수를 출력한다. - get 이름: 그 물건의 개수를 출력한다.
없는 물건이면 0을 출력하고, 장부에 새로 적지 않는다. - use 이름 k: 그 물건이 k개 이상 있으면 k개를 빼고 남은 개수를 출력한다.
남은 개수가 0이 되면 그 물건을 장부에서 지운다.
k개보다 적거나 없는 물건이면 아무것도 바꾸지 않고 -1을 출력한다. 모든 명령이 끝나면 장부에 남은 물건의 수 m을 출력하고, 이어서 m줄에 "이름 개수"를 이름의 사전 순(영어 소문자 문자열 비교)으로 출력한다.

입력
첫 줄에 n(1 ≤ n ≤ 1000), 다음 n줄에 명령 하나씩.
이름은 영어 소문자 1~10글자, 1 ≤ k ≤ 1000
출력
명령마다 한 줄, 그다음 m, 그다음 m줄의 "이름 개수"
예시 1 · stdin
7
add apple 5
add kiwi 2
get pear
use apple 3
use kiwi 5
use kiwi 2
get apple
stdout
5
2
0
2
-1
0
2
1
apple 2
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 1개 언어 풀이

이 문제는 C++만 받아요.
참조(&)와 표준 라이브러리 컨테이너 std::map을 쓰는 방식이 C++만의 것이기 때문이에요(Java·C#·Python·JS는 객체를 늘 참조로 넘겨서 고르는 일이 없고, C에는 사전이 없어요).
함정 셋: ① 함수가 Stock stock처럼 & 없이 받으면 map 전체가 복사되고, 함수 안에서 뺀 개수는 복사본과 함께 사라져요.
② stock[name]은 읽기처럼 보이지만 없는 이름을 0으로 새로 넣어요.
get에서 쓰면 조회만 한 물건이 마지막 목록에 pear 0처럼 남아요.
find로 묻고, 읽기 전용 함수를 const Stock&로 받으면 []가 아예 컴파일되지 않아서 실수를 막아 줘요(add에서는 0부터 더하는 +=가 오히려 편해요).
③ std::unordered_map은 해시 순서라 이름 순으로 나오지 않아요.
std::map은 열쇠 순서대로 돌아요.
erase(it) 뒤에는 그 반복자를 쓰면 안 돼서, 남은 개수를 먼저 꺼내 둬요.
크레이콘이라면 사전()과 있나로 같은 일을 하지만, 참조와 복사를 고를 일은 없어요.

C++main.cpp · 45 줄
#include <iostream>#include <map>#include <string> using Stock = std::map<std::string, int>; // 바꾸는 함수는 참조(&)로 받는다: 복사본이 아니라 main의 stock 그 자체int add(Stock& stock, const std::string& name, int k) {    stock[name] += k;  // 없으면 0으로 만들고 더한다 — 여기서는 그게 맞다    return stock[name];} // 읽기만 하는 함수는 const 참조: 복사도 없고, stock[name]처럼 넣어 버리는 코드는 컴파일되지 않는다int get(const Stock& stock, const std::string& name) {    auto it = stock.find(name);    return it == stock.end() ? 0 : it->second;} int use(Stock& stock, const std::string& name, int k) {    auto it = stock.find(name);    if (it == stock.end() || it->second < k) return -1;    it->second -= k;    int left = it->second;    if (left == 0) stock.erase(it);  // erase 뒤에는 it를 쓰지 않는다    return left;} int main() {    int n;    std::cin >> n;    Stock stock;    for (int i = 0; i < n; i++) {        std::string cmd, name;        std::cin >> cmd >> name;        if (cmd == "get") {            std::cout << get(stock, name) << '\n';        } else {            int k;            std::cin >> k;            std::cout << (cmd == "add" ? add(stock, name, k) : use(stock, name, k)) << '\n';        }    }    std::cout << stock.size() << '\n';    for (const auto& [name, qty] : stock) std::cout << name << ' ' << qty << '\n';}