LotosLabo

プログラミング技術とか気になった情報を載せていきます

C++について5

文字列と配列

Char str[4];

str[0] = 'H';
str[1] = 'e';
str[2] = 'i';
str[3] = '\0'; // 最後に'\0'をつける


最後に入力した\0はNULL文字と呼ばれ、C++では文字列配列の最後を表すものです。
これは必ず付けます。

文字列の長さ+1個文として考える必要があります。


文字列配列の初期化

char str[4] = {'H','e','i','\0'};
char str = {'H','e','i','\0'};
char str[4] = "Hei";
char str
= "Hei";

このような4パターンの初期化方法があります。


文字列配列の出力

int  main()
{
 char str[] = "Hei";
 cout << str << '\n';
 return 0;
}


出力

Hei

文字列をポインタで扱う


char* str = "Hei";


例:

int main()
{
char* str = "Hei";
cout << str << '\n';
return 0;
}


出力

Hei


配列とポインタでは配列では文字列を指定したものを変更できませんが、ポインタでは後から文字列を変更できます。


文字列を操作する

int main()
{
  char str[] = "Hei";
  cout <<"Hei\n";
  
  for(int i=0; str[i]!='\0'; i++){
   cout << str[i] << '*';
  }
  cout << '\n';
  
  return 0;
  
 }




出力結果

Hei
H*e*i*

ここでは配列最後の\0が登場するまで文字位置文字の間に*を挿入しています。


文字列を扱うライブラリ

size_t strlen(const char* s);
sのNULL文字を除く長さを返す

char* strcpy(char* s1, const char* s2);
s2を配列s1にコピーしてs1を返す

char* strcat(char* s1, char* s2);
s2をs1の末尾に追加してs1を返す

int strcmp(const char* s1, const char* s2);
s1とs2を比較し、
s1がs2より小さい時→負
s1がs2より等しい時→0
s1がs2より大きい時→正を返す


文字列関数を利用するには


#include

と記述する。


例: strlen関数

int main()
{
 char str[100];
 cout << "文字列を入力してください\n";
 cin >> str;
 cout << "文字列の長さは" << strlen(str) << "です\n";
 return 0;
}


変数とスコープ

変数の種類


ローカル変数

int main()
{
int a;
}



グローバル変数

int a;

int main()
{
}


●スコープの仕組み

void func();

int a = 0;

int main()
{
 int b = 1;
 
 cout << "main関数では変数aとbが使えます\n";
 cout << "変数aの値は" << a << "です\n";
 cout << "変数bの値は" << b << "です\n";
 
 func();
 
 return 0;
 
 void func()
 {
 int c = 2;
 cout <<"func関数では変数aとcが使えます\n";
 cout << "変数aの値は" << a << "です\n";
 cout << "変数cの値は" << c << "です\n";
 }


変数a → 関数の外に宣言したグローバル変数
変数b → main()関数内に宣言したローカル変数
変数c → func()関数内に宣言したローカル変数

それぞれの変数が利用できる部分の範囲を示しています。このように変数の名前が適用できる範囲のことをスコープと呼んでいます。


また、ローカル変数の名前が重なっても定義するスコープが異なれば問題ありません。しかし、グローバル変数と名前が重なった時は

int a= 0; // グローバル

int main()
{
int a = 0; // ローカル変数
a++; // ローカル変数の処理
::a++; // グローバル変数の処理
}


グローバル変数を利用するには
グローバル解決演算子「::」を使います。


記憶寿命


変数を宣言すると、値を記憶するハコがメモリに準備されます(メモリの確保)。その後、変数に値を格納・出力し、メモリがまた別の用途に使われます(メモリの解放)。このように変数のハコが存在し、値を記憶していられる期間を記憶寿命といいます。


例:

void func();

int a = 0;

int main()
{
  for(int i=0; i<3; i++)
   func();
   return 0;
   }
   
void fun()
{
 int b = 0;
 static int c = 0;
 
 cout << "変数aは" << a << "変数bは" << b << "変数cは" << c << "です\n";
 
 a++;
 b++;
 c++;
 }




出力結果

変数aは0変数bは0変数cは0
変数aは1変数bは0変数cは1


ローカル変数cはインクリメントされない


staticとは

staticを使うとグローバル変数と同じ記憶寿命を持つことが出来ます。静的寿命を持つローカル変数と言います。


動的なメモリ確保

私たちプログラムを作成する人間が指定するタイミングで、メモリを確保する方法を動的なメモリの確保と言います。

ポインタ = new 型名;

 int* pA; // ポインタを用意
 pA = new int;
 *pA = 50;


メモリの解放


delete ポインタ名;

delete pA;

メモリを確保した場合にはメモリが必要でなくなった場合に、プログラマがメモリを開放する処理を書かなければならい。これを行わないとプログラムを実行するたびにメモリが確保され、利用できるメモリが少なくなっていってしまいます。


例:

int main()
{
 int* pA;
 pA = new int;
 cout << "動的にメモリを確保しました\n";
 
 *pA = 10;
 cout << "動的に確保したメモリを使って" << *pA << "を出力しています\n";
 
 delete pA;
 
 cout << "確保したメモリを開放しました\n";
 return 0;
 }




ローカル変数や関数の引数が確保されるメモリ領域はスタックと呼ばれ、グローバル変数などの静的変数が確保される領域は静的記憶領域と呼ばれ、動的に確保されるメモリ領域は動的記憶領域(ヒープ領域)と呼ばれている。


ファイルの分割


例:

test.h → ヘッダーファイル

int max(int x, int y);  // 関数プロトタイプ宣言


test.cpp

int max (int x, int y)
{
 if(x > y)
  return x;
 else
  retrun y;
 }





test1.cpp

#include "test.h" // ヘッダーファイルを読み込む

int main()
{
 int num1, num2, ans;
 
 cout << "1番目の整数を入力してください\n";
 cin >> num1;
 
 cout << "2番目の整数を入力してください\n";
 cin >> num2;
 
 ans = max(num1,num2);
 
 cout << "最大値は" << ans << "です\n";
 return 0;
}