C++ Syntax
บทนี้สรุปภาษา C++ เท่าที่ต้องใช้ในการแข่งขัน ถ้าเคยเขียนภาษาอื่นมาก่อน ให้สังเกตจุดที่ C++ ต่างออกไป เช่น ต้องประกาศชนิดตัวแปรและระวังค่าล้น (overflow)
เครื่องมือที่ใช้เขียน
เริ่มด้วย VS Code 1 กับ extension Competitive Programming Helper (cph) 2 ซึ่งช่วยรันโค้ดกับตัวอย่าง input/output ได้ในคลิกเดียว
ต้องมี compiler เช่น
g++แล้ว compile ด้วยคำสั่งg++ -std=c++17 -O2 -Wall a.cpp -o a(-Wallช่วยเตือนข้อผิดพลาดที่พบบ่อย)
โค้ดเริ่มต้น
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// เขียนโปรแกรมที่นี่
return 0;
}
#include <bits/stdc++.h>include ทุก library มาตรฐานในบรรทัดเดียว (ใช้ได้กับg++ซึ่ง grader ส่วนใหญ่ใช้)using namespace std;ทำให้เขียนcoutแทนstd::coutได้สองบรรทัดแรกใน
mainทำให้cin/coutเร็วขึ้นมาก ควรใส่เสมอเมื่อ input ใหญ่ (แต่หลังจากนั้นห้ามใช้scanf/printfปนกับcin/cout)
Comments
Comment คือข้อความที่ compiler ไม่สนใจ ใช้อธิบายโค้ดให้คนอ่าน
// line comment: ตั้งแต่ // ถึงท้ายบรรทัด
/*
block comment
หลายบรรทัด
*/
ตัวแปรและชนิดข้อมูล
ใน C++ ต้องประกาศ ชนิด (type) ของตัวแปรเสมอ ซึ่งกำหนดว่าเก็บค่าอะไรได้และใช้หน่วยความจำเท่าไร
| ชนิด | ขนาด (byte) | เก็บอะไร |
|---|---|---|
bool |
1 | true หรือ false |
char |
1 | ตัวอักษรหนึ่งตัว เช่น 'a' (จริง ๆ คือเลข ASCII) |
int |
4 | จำนวนเต็ม ประมาณ \pm 2.1 \times 10^{9} |
long long |
8 | จำนวนเต็ม ประมาณ \pm 9.2 \times 10^{18} |
double |
8 | จำนวนจริง (ทศนิยม) ละเอียดประมาณ 15 หลัก |
string |
- | ข้อความ |
Overflow
ถ้าค่าเกินขอบเขตของชนิด ผลลัพธ์จะผิดโดย ไม่มี error เตือน นี่คือสาเหตุอันดับต้น ๆ ที่ทำให้เสียคะแนน
int a = 100000, b = 100000;
long long wrong = a * b; // ผิด! a * b คำนวณเป็น int แล้วล้นก่อน
long long right = (long long)a * b; // ถูก: 10000000000
กฎง่าย ๆ: ถ้าคำตอบหรือค่าระหว่างทางอาจเกิน 10^{9} ให้ใช้ long long
Input/Output
ใช้ cin >> รับค่าและ cout <<
แสดงผล cin จะข้ามช่องว่างและขึ้นบรรทัดใหม่ให้อัตโนมัติ
และแปลงข้อมูลตามชนิดของตัวแปร
int n;
string name;
cin >> n >> name; // input: 5 alice
cout << name << " has " << n << " apples\n"; // alice has 5 apples
'\n' คือขึ้นบรรทัดใหม่ ควรใช้แทน endl เพราะ
endl สั่งล้าง buffer ทุกครั้งจึงช้ากว่ามากเมื่อพิมพ์หลายบรรทัด
ชนิดของตัวแปรมีผลกับการรับค่า เช่น ถ้าพิมพ์ 5 ให้ตัวแปร
char จะได้ตัวอักษร '5' ซึ่งมีรหัส ASCII เท่ากับ 53
ไม่ใช่เลข 5
char c;
cin >> c; // input: 5
cout << (int)c << '\n'; // 53
cout << c - '0'; // 5 (แปลงตัวอักษรตัวเลขเป็นจำนวน)
การพิมพ์ทศนิยมให้กำหนดจำนวนตำแหน่งด้วย fixed และ
setprecision
double x = 2.0 / 3;
cout << fixed << setprecision(3) << x; // 0.667
Operators
| operator | ความหมาย | ตัวอย่าง |
|---|---|---|
+ - * |
บวก ลบ คูณ | 7 * 3 = 21 |
/ |
หาร (ถ้าเป็น int ทั้งคู่จะปัดเศษทิ้ง) |
7 / 2 = 3, 7.0 / 2 = 3.5 |
% |
เศษจากการหาร (ใช้กับจำนวนเต็ม) | 7 % 3 = 1 |
== != |
เท่ากัน ไม่เท่ากัน | a == b |
< <= > >= |
เปรียบเทียบ | a < b |
&& || ! |
และ หรือ ไม่ | a > 0 && b > 0 |
++ += -= |
เพิ่ม/ลดค่า | i++, s += x |
ระวัง: -7 % 3 ใน C++ ได้ -1 (ไม่ใช่ 2)
ถ้าต้องการเศษที่ไม่ติดลบให้เขียน ((a % m) + m) % m
Control structures
if / else
if (x > 0) {
cout << "positive";
} else if (x < 0) {
cout << "negative";
} else {
cout << "zero";
}
ระวังเขียน if (x = 0) (กำหนดค่า) แทน
if (x == 0) (เปรียบเทียบ) ซึ่ง compile ผ่านแต่ทำงานผิด
-Wall จะช่วยเตือน
for และ while
for (int i = 0; i < 10; i++) { // i = 0, 1, ..., 9
cout << i << ' ';
}
int n = 37;
while (n > 0) { // พิมพ์เลขฐานสองของ 37 จากหลักขวาไปซ้าย
cout << n % 2;
n /= 2;
}
ใช้ break เพื่อออกจาก loop ทันที และ continue
เพื่อข้ามไปรอบถัดไป
Arrays
Array เก็บข้อมูลชนิดเดียวกันหลายตัวต่อกัน เข้าถึงด้วย index ที่เริ่มจาก 0
int n;
int a[100005]; // ประกาศให้ใหญ่กว่า n สูงสุดเล็กน้อย
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i]; // a[0], a[1], ..., a[n-1]
long long sum = 0;
for (int i = 0; i < n; i++) sum += a[i];
cout << sum;
Array ขนาด n มี index 0 ถึง n - 1 การเข้าถึง
a[n]หรือ index ติดลบเป็นข้อผิดพลาดที่อาจไม่ crash แต่ให้คำตอบผิดArray ขนาดใหญ่ (เกินประมาณ 10^{5} ตัว) ควรประกาศเป็น global คือนอก
mainเพราะตัวแปรใน function ใช้พื้นที่ stack ซึ่งมีจำกัด และ global array จะมีค่าเริ่มต้นเป็น 0 ให้อัตโนมัติ
Array หลายมิติ
int grid[505][505];
int r, c;
cin >> r >> c;
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
cin >> grid[i][j];
Strings
string เก็บข้อความและใช้งานคล้าย array ของ
char
string s;
cin >> s; // อ่านหนึ่งคำ (หยุดที่ช่องว่าง)
cout << s.size(); // ความยาว
cout << s[0]; // ตัวอักษรแรก
s += "!"; // ต่อข้อความ
string line;
getline(cin, line); // อ่านทั้งบรรทัดรวมช่องว่าง
ถ้าใช้ getline หลัง cin >>
ต้องอ่านทิ้งบรรทัดที่ค้างอยู่ก่อนด้วย cin.ignore()
Functions
long long square(long long x) {
return x * x;
}
int main() {
cout << square(12); // 144
}
รายละเอียดเรื่อง function, parameter และ scope อยู่ในบท Function
ข้อผิดพลาดที่พบบ่อย
ใช้
intกับค่าที่เกิน 2.1 \times 10^{9} (overflow)ลืมว่า
7 / 2เป็น 3 เมื่อหารจำนวนเต็มเข้าถึง array นอกขอบเขต โดยเฉพาะ
a[n]ประกาศ array ใหญ่ไว้ใน
mainจน stack overflowใช้
endlพิมพ์หลายแสนบรรทัดจนเกินเวลา
โจทย์ฝึกฝน (Practice Problems)
ลองทำโจทย์เหล่านี้จาก CSES Problem Set เพื่อฝึกใช้ทักษะจากบทนี้ โดยเริ่มจากโจทย์ที่ง่ายที่สุดก่อน
Weird Algorithm (ระวัง overflow)
โจทย์เพิ่มเติม: CSES Problem Set และ programming.in.th