前日の記事:@niinaさんの「C++しか書かずにPythonライブラリを作る」
翌日の記事:@kizulさんです。
この記事の概要
この記事は"C言語とC++の書き方を両方書き表したもの"です。
つまり、
"C言語とC++版のロゼッタストーンです。"
C言語を学んだけど、C++の書き方がわからない…… (39歳 Aさん 主婦)
C++は書き方わかるけど、C言語がよくわからない……(195歳 Bさん 小学生)
他にどんな書き方があるのか知りたい!(17歳 Cさん 高校生)
のような口コミが聞こえてきたので、(幻聴)
今回はC言語とC++の書き方を同時にまとめました!
※この記事は入門書レベルの基本事項から書いていきます。
基本的に以下に記載するソースコードは
C89
とC++11
の環境で動作するように書いています。
C99
やC++14
等で動作するソースコードはその都度バージョンを明記します。
※本当はC99で動作するプログラムを載せたいところですが、あえてカンブリア紀レベルの化石であるC89でも動作するプログラムを載せていきます。(もしかしたら癖でC99を書いてしまっているかもしれません)
間違いや改善点、追加してほしいものなどありましたらコメントでお伝えください。
出力(引数なし)
C
#include <stdio.h>
int main(void) {
puts("Hello, World!");
return 0;
}
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
return 0;
}
C++
#include <cstdio>
int main() {
std::puts("Hello, World!");
return 0;
}
#include <cstdio>
int main() {
std::printf("Hello, World!\n");
return 0;
}
#include <iostream>
int main() {
std::cout << "Hello, World!\n";
return 0;
}
出力結果
Hello, World!
みんな大好きハローワーク、
いいえ、ハローワールドです。
巷では、10種類以上の言語でハローワールドをしただけで
"10種類以上の言語を使えます"と宣言している人もいるとか。
ハローワールドだけでもこのように様々な方法で書くことが出来ます。
出力(引数あり)
C
#include <stdio.h>
int main(void) {
int a = 10;
int b = 5;
printf("%d + %d = %d\n", a, b, a + b);
return 0;
}
C++
#include <cstdio>
int main() {
int a = 10;
int b = 5;
std::printf("%d + %d = %d\n", a, b, a + b);
return 0;
}
#include <iostream>
int main() {
int a = 10;
int b = 5;
std::cout << a << " + " << b << " = " << a + b << "\n";
return 0;
}
出力結果
10 + 5 = 15
足し算結果の出力です。
入門書では前半のページで学ぶと思います。
ここでついに可変長引数のありがたみを受けます。
数値の入力
C
#include <stdio.h>
int main(void) {
int a;
scanf("%d", &a);
printf("a==%d", a);
return 0;
}
@yumetodo さんからのコメントより
ですが、完全に脇道に逸れるとscanfで数値に変換するのは安全ではないのでだめですね。
ref: https://qiita.com/yumetodo/items/238751b879c09b56234b
C++
#include <cstdio>
int main() {
int a;
std::scanf("%d", &a);
std::printf("a==%d", a);
return 0;
}
#include <iostream>
int main() {
int a;
std::cin >> a;
std::cout << "a==" << a << "\n";
return 0;
}
出力結果
10
a==10
scanfはアレなので、C++を使用している方はstd::cinをお勧めします。
余談
Visual Studioでは、scanfがあまりにも危険すぎる(?)ため
_CRT_SECURE_NO_WARNINGS
マクロを書かないとコンパイルエラーが出ます。
#define _CRT_SECURE_NO_WARNINGS //ここを書かないとエラー!
#include <stdio.h>
int main(void) {
int a;
scanf("%d", &a);
printf("a==%d", a);
return 0;
}
Visual Studioでは、scanf
ではなくscanf_s
の使用を
推奨しています。
※scanf_sはstd名前空間に属していないので注意。
#include <stdio.h>
int main(void) {
int a;
scanf_s("%d", &a);
printf("a==%d", a);
return 0;
}
書き換えるの面倒ですね!(本音)
乱数(範囲指定なし)
C
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void) {
int i;
srand((unsigned int)time(NULL));
for (i = 0; i < 10; ++i) {
printf("%d ", rand());
}
printf("\n");
return 0;
}
C++
#include <iostream>
#include <random>
int main() {
std::mt19937 mt;
std::random_device rd;
mt.seed(rd());
for (int i = 0; i < 10; ++i) {
std::cout << mt() << " ";
}
std::cout << std::endl;
return 0;
}
@yumetodo さんからのコメントより
C++14
からstd::rand()
とstd::srand()
はdeprecated
になったようなのでBetter Cの部分は削除しました。
出力結果
2680 12099 12992 1755 4675 11920 23824 19081 19872 32396
1028496359 321947819 1840655768 2203056587 3403894914 1543972996 2921512719 528846214 2426473444 1679236695
※乱数なので出力される数値はほぼ毎回異なります。
(ただし、randの実装方法だと1秒おきに変わる)
コンパイル時定数とdefineマクロ
C
#include <stdio.h>
#define INT_TEN (10)
int main(void) {
printf("%d\n", INT_TEN);
return 0;
}
C++
#include <cstdio>
constexpr int INT_TEN = 10;
int main() {
std::printf("%d\n", INT_TEN);
return 0;
}
出力結果
10
配列
C
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[] = { 5,2,8,3,9,1 };
size_t a_size = sizeof(a) / sizeof(int);
for (size_t i = 0; i < a_size; ++i) {
printf("%d ", a[i]);
}
printf("\n");
}
C++
#include <iostream>
#include <algorithm>
#include <array>
int main() {
std::array<int, 6> a{ 5,2,8,3,9,1 };
for (size_t i{}; i < a.size(); ++i) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
出力結果
5 2 8 3 9 1
ソート(昇順)
C (C99)
#include <stdio.h>
#include <stdlib.h>
int qsort_(const void *a, const void *b) {
return *(int *)a - *(int *)b;
}
int main(void) {
int a[] = { 5,2,8,3,9,1 };
size_t a_size = sizeof(a) / sizeof(int);
qsort(a, a_size, sizeof(int), qsort_);
for (size_t i = 0; i < a_size; ++i) {
printf("%d ", a[i]);
}
printf("\n");
}
C++
#include <cstdio>
#include <cstdlib>
#include <array>
int main() {
std::array<int, 6> a{ 5,2,8,3,9,1 };
std::qsort(a.data(), a.size(), sizeof(int), [](const void *a, const void *b){
return *reinterpret_cast<const int*>(a) - *reinterpret_cast<const int*>(b);
});
for (size_t i{}; i < a.size(); ++i) {
std::printf("%d ", a[i]);
}
std::printf("\n");
}
コメントより @yumetodo さんからのコードを拝借致しました。
#include <iostream>
#include <algorithm>
#include <array>
int main() {
std::array<int, 6> a{ 5,2,8,3,9,1 };
std::sort(a.begin(), a.end());
for (size_t i{}; i < a.size(); ++i) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
出力結果
1 2 3 5 8 9
ソート(降順)
C (C99)
#include <stdio.h>
#include <stdlib.h>
int qsort_(const void *a, const void *b) {
return *(int *)b - *(int *)a;
}
int main(void) {
int a[] = { 5,2,8,3,9,1 };
size_t a_size = sizeof(a) / sizeof(int);
qsort(a, a_size, sizeof(int), qsort_);
for (size_t i = 0; i < a_size; ++i) {
printf("%d ", a[i]);
}
printf("\n");
}
C++
#include <cstdio>
#include <cstdlib>
#include <array>
int main() {
std::array<int, 6> a{ 5,2,8,3,9,1 };
std::qsort(a.data(), a.size(), sizeof(int), [](const void *a, const void *b){
return *reinterpret_cast<const int*>(b) - *reinterpret_cast<const int*>(a);
});
for (size_t i{}; i < a.size(); ++i) {
std::printf("%d ", a[i]);
}
std::printf("\n");
}
#include <iostream>
#include <algorithm>
#include <array>
int main() {
std::array<int, 6> a{ 5,2,8,3,9,1 };
std::sort(a.begin(), a.end(), std::greater<int>());
for (size_t i{}; i < a.size(); ++i) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
出力結果
9 8 5 3 2 1
整数型の最大値・最小値
C
#include <stdio.h>
#include <limits.h>
int main(void) {
int int_min = INT_MIN;
int int_max = INT_MAX;
printf("int: %d ~ %d \n", int_min, int_max);
return 0;
}
C++
#include <cstdio>
#include <climits>
int main(void) {
constexpr int int_min = INT_MIN;
constexpr int int_max = INT_MAX;
std::printf("int: %d ~ %d \n", int_min, int_max);
return 0;
}
#include <stdio.h>
#include <limits>
int main() {
constexpr int int_min = std::numeric_limits<int>::min();
constexpr int int_max = std::numeric_limits<int>::max();
printf("int: %d ~ %d \n", int_min, int_max);
return 0;
}
出力結果
int: -2147483648 ~ 2147483647
メモリ領域の動的確保
C
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *m = NULL;
int i, n = 10;
m = (int *)malloc(n * sizeof(int));
for (i = 0; i < n; i++) m[i] = i;
for (i = 0; i < n; i++) printf("%d ", m[i]);
printf("\n");
free(m);
return 0;
}
C++
#include <cstdio>
#include <cstdlib>
int main() {
int *m{ nullptr };
const size_t n{ 10 };
m = (int *)std::malloc(n * sizeof(int));
for (size_t i = 0; i < n; i++) m[i] = (int)i;
for (size_t i = 0; i < n; i++) std::printf("%d ", m[i]);
std::printf("\n");
std::free(m);
return 0;
}
#include <cstdio>
int main() {
int *m{ nullptr };
const size_t n{ 10 };
m = new int[n];
for (size_t i = 0; i < n; i++) m[i] = (int)i;
for (size_t i = 0; i < n; i++) std::printf("%d ", m[i]);
std::printf("\n");
delete[] m;
return 0;
}
new
は忘れてスマートポインタ
を使いましょう。
#include <cstdio>
#include <memory>
int main() {
const size_t n{ 10 };
std::unique_ptr<int[]> m(new int[n]);
for (size_t i = 0; i < n; i++) m[i] = (int)i;
for (size_t i = 0; i < n; i++) std::printf("%d ", m[i]);
std::printf("\n");
return 0;
}
スマートポインタについては
C++11スマートポインタ入門を読んでください。
出力結果
0 1 2 3 4 5 6 7 8 9
文字列代入
C(文字数がわかっている場合)
#include <stdio.h>
#include <string.h>
int main(void) {
char str[100];
strcpy(str, "abcdefghijk");
printf("%s\n", str);
return 0;
}
他のやり方は準備中……。
C++
#include <iostream>
#include <string>
int main() {
std::string str;
str = "abcdefghijk";
std::cout << str << std::endl;
return 0;
}
出力結果
abcdefghijk
文字列連結
C(文字数がわかっている場合)
#include <stdio.h>
#include <string.h>
int main(void) {
char str[100];
strcpy(str, "abcdefghijk");
strcat(str, "ABCDEFG");
printf("%s\n", str);
return 0;
}
他のやり方は準備中……。
C++
#include <iostream>
#include <string>
int main() {
std::string str;
str = "abcdefghijk";
str += "ABCDEFGHIJK";
std::cout << str << std::endl;
return 0;
}
出力結果
abcdefghijkABCDEFGHIJK
関数ポインタ
C
#include <stdio.h>
//加算
int add(int x_, int y_) {
return (x_ + y_);
}
//減算
int sub(int x_, int y_) {
return (x_ - y_);
}
//乗算
int mul(int x_, int y_) {
return (x_ * y_);
}
//除算
int div(int x_, int y_) {
return (x_ / y_);
}
int main(void) {
int a = 18;
int b = 3;
int ans;
int(*f)(int, int);
printf("a = %d, b = %d\n", a, b);
f = add;
ans = (*f)(a, b);
printf("a + b = %d\n", ans);
f = sub;
ans = (*f)(a, b);
printf("a - b = %d\n", ans);
f = mul;
ans = (*f)(a, b);
printf("a * b = %d\n", ans);
f = div;
ans = (*f)(a, b);
printf("a / b = %d\n", ans);
return 0;
}
C++
#include <cstdio>
//加算
int add(const int x_, const int y_) {
return (x_ + y_);
}
//減算
int sub(const int x_, const int y_) {
return (x_ - y_);
}
//乗算
int mul(const int x_, const int y_) {
return (x_ * y_);
}
//除算
int div(const int x_, const int y_) {
return (x_ / y_);
}
int main() {
const int a{ 18 };
const int b{ 3 };
int ans;
int(*f)(int, int);
std::printf("a = %d, b = %d\n", a, b);
f = add;
ans = (*f)(a, b);
std::printf("a + b = %d\n", ans);
f = sub;
ans = (*f)(a, b);
std::printf("a - b = %d\n", ans);
f = mul;
ans = (*f)(a, b);
std::printf("a * b = %d\n", ans);
f = div;
ans = (*f)(a, b);
std::printf("a / b = %d\n", ans);
return 0;
}
#include <cstdio>
#include <functional>
//加算
int add(const int x_, const int y_) {
return (x_ + y_);
}
//減算
int sub(const int x_, const int y_) {
return (x_ - y_);
}
//乗算
int mul(const int x_, const int y_) {
return (x_ * y_);
}
//除算
int div_(const int x_, const int y_) {
return (x_ / y_);
}
int main() {
const int a{ 18 };
const int b{ 3 };
int ans;
std::function<int(int, int)> f;
std::printf("a = %d, b = %d\n", a, b);
f = add;
ans = f(a, b);
std::printf("a + b = %d\n", ans);
f = sub;
ans = f(a, b);
std::printf("a - b = %d\n", ans);
f = mul;
ans = f(a, b);
std::printf("a * b = %d\n", ans);
f = div_;
ans = f(a, b);
std::printf("a / b = %d\n", ans);
return 0;
}
出力結果
a = 18, b = 3
a + b = 21
a - b = 15
a * b = 54
a / b = 6
私が記述したソースコードのライセンス
These codes are licensed under CC0.
ソースコードは自由に使用してください。