C++勉強日記(2022/02/23):基礎1
「1習慣でC++の基礎が学べる本」を元に、C++の勉強をしていく。
本ではVScodeを使用しているが、ブラウザで実行し学習する。
Hello worldを表示
Hello worldを表示する。
code:c++
//ヘッダファイルのインクルード(coutを使用するのに必要)
//名前空間の宣言(coutを使用するのに必要)
using namespace std;
int main(void){
//Hellow worldを表示
//endlは改行
//cout<<で表示
cout<<"Hello world"<<endl;
return 0;
}
'#include<iostream>
C言語でいうヘッダーファイル。 C++専用で、ヘッダと呼ぶ。
cout(表示用のオブジェクト)を使用するのに宣言が必要。
usin namespace std;
名前空間といい、今回はcoutを使用するのに、必要。
stdが標準名前空間として用意されている名前空間で、coutやcinなどを使用する場合に宣言する必要がある。
cout
C++で用意されている標準名前空間に含まれるストリームを扱うオブジェクト。
何かを表示したいときに使用する。
cout<<表示したいもの
で使用することができる。
endl
改行をするときに使用する。
\nも使用できるが、C++では一般的にendlを使う。
return
戻り値を返す。
return 0で0の値を返している。
ここでのreturnの意味は、0を返せば正常終了、0以外なら異常終了という意味で使用される。
数値の入力
コンソールから数値を入力して、計算結果を表示する。
code:c++
//ファイル名:main.cpp
//プログラム内容:数値をa,bを入力し、その足し算の結果を表示する。
//ーーーーーーーープログラム開始ーーーーーーーーーーー
//ヘッダの宣言
//名前空間の宣言
using namespace std;
//メイン関数処理
int main(void){
// Your code here!
//変数宣言
int a,b;
//初期化処理
a=0;
b=0;
//a=を表示
cout<<"a="<<endl;
//変数aにキーボードで入力
cin>>a;
//b=を表示
cout<<"b="<<endl;
//変数bにキーボードで入力
cin>>b;
//a+bの計算結果を表示する
cout<<"a+b="<<a+b;
//0の値を返す。
return 0;
}
//ーーーーーーーープログラム終了ーーーーーーーーーーー
(実行結果には、入力にa=5,b=9を入力)
cin
数値の入力に使用する。
coutと同様、標準名前空間に含まれるストリームを扱うオブジェクトの一つ。
キーボードから入力した値を変数に代入する。
ストリームの概念
coutやcinは、c言語のprintfとと同じに見えるが、違うもの。
ストリームと呼ばれるものに対し、データ(数値や文字列)をお送りだしたり、逆に受け取ったりしている。
つまり、coutやcinは、ストリームからデータを受け取ったり、送ったりしている。
不等号の向きは、その流れを表している。
出力先がコンソールだったり、ファイルシステムだったりするので、
ストリームによって、入出力対象を切り替えることにより、入出力の処理が殆ど同じような記述で、行うことができる。
文字列の扱い
C++で文字列を表す。
C++で文字列を扱う方法は、char型配列を利用する方法と、stringクラスを利用する方法がある。
cinからデータを受け取る場合、char型配列は利用できない。
stringクラスを使った文字列の入出力
code:c++
//ファイル名:main.cpp
//プログラム内容:文字列を入力し、「入力された文字は、入力した文字です。」を表示する。
//ーーーーーーーープログラム開始ーーーーーーーーーーー
using namespace std;
int main(void){
// Your code here!
string s,t;
t="入力されたもじは、";
cout << "文字列を入力:"<<endl;
cin >> s;
cout <<t+s<<"です。"<<endl;
return 0;
}
//ーーーーーーーープログラム終了ーーーーーーーーーーー
'#include <string>
stringクラスを使って文字列を扱うのに必要。
stringクラスが利用可能になるとstring型の変数が使用できるようになる。
string型の変数へ値(文字列)を代入する時には、=演算子を使用する。
また、+演算子で文字列同士を繋げる事が可能になる。
char型を使った文字列の入出力
code:c++
//ファイル名:main.cpp
//プログラム内容:
//別の宣言方法で、下記2点の表示を行う。
//abc の出力
//入力した文字列の表示をする。
//ーーーーーーーープログラム開始ーーーーーーーーーーー
//ヘッダのインクルード
//名前空間宣言
using namespace std;
//メイン処理
int main(void){
// Your code here!
//char型の変数宣言
char s1[]={'a','b','c','\0'}; //abcを入力
char s2[]="入力した文字";
char s3[]={}; //入力用変数
//文字列の出力
cout << "s1="<<s1<<endl;
cout << "s2="<<s2<<endl;
cin >> s3;
cout << s3 << endl;
//cout <<s2+s1<<endl; //これはできない。
}
//ーーーーーーーープログラム終了ーーーーーーーーーーー
char型の配列変数の要素には、それぞれ文字コードが入っている。
文字列の最後にあたる要素には必ず\0が入る。
これをNULL文字、ヌル終端文字という。
値としては、整数値の0に等しい。
NULL文字が入るため、配列変数に文字列を作る場合は、最低限「文字数+1」の大きさの要素が必要。
配列の途中に\0が配列があれば、そこで文字列は終了になる。
char型とstring型の使い分け、特徴
char型
長所:
必要とするメモリが少ない
処理スピードが早い
C言語の資産を受け継げる
短所:
処理が複雑
エラーが起こりやすい
string型
長所:
扱いが簡単で分かりやすい
エラーを起こしにくい
短所:
char型の配列に比べて余計なメモリが必要
char型の配列よりも処理スピードが遅い
名前空間について
名前空間により、名前の重複しても大丈夫なように出来る。
名前空間が無い場合、変数や関数の名前に同じ名前が使われると、バグの元になる。
名前空間を利用して、同名の変数を複数定義する。
code:c++
//ファイル名:main.cpp
//プログラム内容:
//名前空間A,B 2個用意し、同じ名前の変数を作成する。
//作成した変数に数値を入れ、出力することにより、それぞれの名前空間でのふるまいを確認する。
//ーーーーーーーープログラム開始ーーーーーーーーーーー
//ヘッダーの宣言
//名前空間の宣言
using namespace std;
//名前空間Aのpowerを作成
namespace A{
int power; //名前空間Aの変数powerを作成
}
//名前空間Bのpowerを作成
namespace B{
int power; //名前空間Bの変数powerを作成
}
//関数のプロトタイプ宣言
void funcA();
void funcB();
//メイン関数処理
int main(void){
//変数への代入
A::power = 20; //名前空間Aのpowerに20を代入
B::power = 30; //名前空間Bのpowerに30を代入
cout<<"main:A::power="<<A::power<<endl; //名前空間Aのpowerを表示
cout<<"main:B::power="<<B::power<<endl; //名前空間Bのpowerを表示
funcA(); //関数Aを使用
funcB(); //関数Bを使用
return 0;
}
//関数Aの作成
void funcA(){
//名前空間Aを使う。
using namespace A;
cout<<"funcA:A::power="<<power<<endl; //名前空間Aのpowerを表示
cout<<"funcA:B::power="<<B::power<<endl; //名前空間Bのpowerを表示
//power(名前空間A)の値を変更
power = 40;
}
//関数Bの作成
void funcB(){
//名前空間Bを使う。
using namespace B;
cout<<"funcB:A::power="<<A::power<<endl; //名前空間Aのpowerを表示
cout<<"funcB:B::power="<<power<<endl; //名前空間Bのpowerを表示
}
//ーーーーーーーープログラム終了ーーーーーーーーーーー
名前空間の使い方
名前空間の定義
namespace 名前空間の名称{
変数や関数の定義など
}
{}の中で定義した変数や関数等は、指定した名前空間の中でしか使えない。
名前空間の利用
名前空間を利用する方法は2種類ある。
1: using namespace 名前空間名;
で宣言する。
2: 名前空間名::変数名やクラス名など;
で使用する。
下記コードは同じ結果となる。
code:c++
//ヘッダファイルのインクルード
int main(void){
// Your code here!
//Hellow worldを表示
std::cout<<"Hello world"<<endl;
return 0;
}
code:c++
//ヘッダファイルのインクルード
using namespace std; //名前空間stdを使用
int main(void){
// Your code here!
//Hellow worldを表示
cout<<"Hello world"<<endl;
return 0;
}
メモリとポインタ
アドレスとサイズの取得
code:c++
using namespace std;
int main(void){
// Your code here!
int a = 100;
cout <<"aの値は"<<a<<endl;
cout <<"aのサイズは"<<sizeof(int)<<"byte"<<endl;
cout <<"アドレスは"<<std::hex<<&a<<endl;
return 0;
}
変数、データ型のサイズを取得するには、sizeof演算子を使用する。
使い方:
sizeof(int);
sizeof(変数);
変数型が使用するメモリのサイズは決まっているため、常に同じ値が得られる。
変数のアドレスを取得するには、先頭に&記号をつける。
使い方:
&a
変数のアドレスはプログラムを実行するたびに動的に割り振られるため、常に異なる値が割り振られる。
std::hex
整数を16進数に変換する。
結果が16進数で表示される。
通常、メモリのアドレスは16進数で表される。
アドレスを入れ替える。
アドレスを入れ替える変数をポインタ変数、又はポインタという。
ポインタの書き方(下記2種類どちらでも可):
int *p;
int* p;
table:ポインタと通常の変数の比較
形態 通常の変数 ポインタ変数 解説
宣言 int a; int* p; 、int *p; ポインタは、変数の先頭か型のあとに*をつける。
値 a *p ポインタ変数で値を示すには、先頭*をつける。
アドレス &a p ポインタはアドレスを入れる。
code:c++
//ファイル名:main.cpp
//プログラム内容:
//ポインタpと変数bのふるまいの違いを表示し、確認する。
//ーーーーーーーープログラム開始ーーーーーーーーーーー
using namespace std;
int main(void){
// Your code here!
//変数宣言及び初期化
int a = 100; //変数aに100を代入
//ポインタの宣言
int *p = NULL; //ポインタpの参照先無効
//代入
p = &a; //ポインタpの参照先をaにする。
//aと*pの値を表示
cout<<"*p="<<*p<<endl; //ポインタpに入っている値を表示
return 0;
}
//ーーーーーーーープログラム終了ーーーーーーーーーーー
code:c++
//ファイル名:main.cpp
//プログラム内容:
//ポインタpと変数bのふるまいの違いを表示し、確認する。
//ーーーーーーーープログラム開始ーーーーーーーーーーー
using namespace std;
int main(void){
// Your code here!
//変数宣言及び初期化
int a = 100; //変数aに100を代入
int b = 0;
//ポインタの宣言
int *p = NULL; //ポインタpの参照先を0番地に設定
//値の表示
cout<<"a="<<a<<endl; //変数aに入っている値を表示
cout<<"b="<<b<<endl; //変数bに入っている値を表示
cout<<"*p="<<*p<<endl; //ポインタpに入っている値を表示
//ポインタPにaのアドレスを入れる。
cout<<"*pにaのアドレスを、bにaの値を代入"<<endl;
//代入
p = &a; //ポインタpの参照先をaにする。
b = a; //bにaを代入する。
//aと*pの値を表示
cout<<"a="<<a<<endl; //変数aに入っている値を表示
cout<<"b="<<b<<endl; //変数bに入っている値を表示
cout<<"*p="<<*p<<endl; //ポインタpに入っている値を表示
//*p,bの変更
*p = 200; //ポインタbに200を入れる。
b = 300; //変数bに300を入れる。
cout<<"*pの値を200に、bの値を300に変更"<<endl;
//aと*pの値を表示
cout<<"a="<<a<<endl; //変数aに入っている値を表示
cout<<"b="<<b<<endl; //変数bに入っている値を表示
cout<<"*p="<<*p<<endl; //ポインタpに入っている値を表示
return 0;
}
//ーーーーーーーープログラム終了ーーーーーーーーーーー
ポインタ変数pの宣言
ポインタは、NULLを代入することにより、初期化する。
NULL:数値でいうところの0を意味する定数
ポインタ変数は、他の変数のアドレスを代入するとその変数としてふるまうことが出来る。
p =&a;
これにより、ポインタ変数pに変数aのアドレスが代入
*pの値を表示すると、変数aと同じ値が表示
ポインタ*pの値を変更すると、代入されている変数aの値も変更される。
ポインタ変数のアドレスを設定する場合、同じ型のポインタ変数に対して行う。
int a; であれば int *p;
double d; であれば、 double *pd;
値渡しとポインタ渡し
code:c++
using namespace std;
//変数の値を入れ替える関数
void swap(int*,int*);
int swap2(int,int);
int main(void){
// Your code here!
int a = 1;
int b = 2;
int c = 3;
int d = 4;
cout<<"a="<<a<<"b="<<b<<endl;
swap(&a,&b);
cout<<"a="<<a<<"b="<<b<<endl;
cout<<"c="<<c<<"d="<<d<<endl;
swap2(c,d);
cout<<"c="<<c<<"d="<<d<<endl;
return 0;
}
void swap(int* num1,int* num2){
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
int swap2(int num1,int num2){
int temp = num1; //temp = 3
num1 = num2; //num1 = 4
cout<<"num1="<<num1<<"num2="<<num2<<endl;
num2 = temp; //num2 = 3
cout<<"num1="<<num1<<"num2="<<num2<<endl;
return num1,num2;
}
ポインタ渡しを使うと、呼び出し元の変数の複数の値を変更することが出来る。
普通の変数だと、複数の値を返せないため、変更することが出来ない。