情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |
y = sqrt(x);
#include <math.h> double sqrt(double x) x : 倍精度浮動小数点数
double x = 3.14; double y = sqrt(x); // double y = sqrt(3.14) としても良い
double d_data; int i_data; char c_data[10]; scanf("%lf %d %s", &d_data, &i_data, c_data);
3.141592654 123 abc
3.141592654 123 abc
double d_data; int i_data; char c_data[10]; ・・・・・ printf("結果は %f %10.3f %d %5d %s %c\n", d_data, d_data, i_data, i_data, c_data, c_data[1]);
結果は 3.141593 3.142 123 123 abc b
#include <stdio.h> int main() { double x[2]; int y; char str[10]; scanf("%lf %lf %d %s", &x[0], &x[1], &y, str); printf("result %s %.4f %c %f%6d\n", str, x[0], str[2], x[1], y); return 0; }
result printf 3.1416 i 2.500000 123
/****************************/ /* 文字列操作の例 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> #include <string.h> int main() { // 現在の文字列の内容を出力 char abc[] = "abc"; printf("-abc- %s\n", abc); // 文字列として出力 printf("-abc- "); // 1文字ずつ出力 int i1; for (i1 = 0; i1 < 3; i1++) printf("%c", abc[i1]); printf("\n"); // 文字列の長さ int len1, len2, len3; char *defgh = "defgh"; // 警告メッセージ(この表現は,避けた方が良い) char emp[20] = ""; len1 = strlen(abc); len2 = strlen(defgh); len3 = strlen(emp); printf("各文字列の長さ %d %d %d\n", len1, len2, len3); // 文字列のコピー char *str = strcpy(emp, abc); len1 = strlen(emp); printf("-str- %s -emp- %s 長さ %d\n", str, emp, len1); // 文字列の比較 int c1 = strcmp(emp, abc); int c2 = strcmp(emp, defgh); printf("-empとabc- %d -empとdefgh- %d\n", c1, c2); // 文字列の結合 str = strcat(emp, " "); str = strcat(emp, defgh); len1 = strlen(emp); printf("-str- %s -emp- %s 長さ %d\n", str, emp, len1); // 文字列の検索 str = strstr(emp, "ef"); len1 = strlen(str); printf("-str- %s 長さ %d -emp- %s\n", str, len1, emp); return 0; }
-abc- abc -abc- abc 各文字列の長さ 3 5 0 -str- abc -emp- abc 長さ 3 -empとabc- 0 -empとdefgh- -1 -str- abc defgh -emp- abc defgh 長さ 9 -str- efgh 長さ 4 -emp- abc defgh
---------------------(C++)string クラス-------------------------
/****************************/ /* 文字列操作の例(C++) */ /* coded by Y.Suganuma */ /****************************/ #include <iostream> #include <string> using namespace std; int main() { // 現在の文字列の内容を出力 string abc = "abc"; cout << "-abc- " << abc << endl; // 文字列として出力 cout << "-abc- "; // 1文字ずつ出力 for (int i1 = 0; i1 < 3; i1++) cout << abc[i1]; cout << endl; // 文字列の長さ string defgh = "defgh"; string emp = ""; int len1 = abc.size(); int len2 = defgh.size(); int len3 = emp.size(); cout << "各文字列の長さ " << len1 << " " << len2 << " " << len3 << endl; // 文字列のコピー emp = abc.assign(abc); len1 = emp.size(); cout << "-emp- " << emp << " 長さ " << len1 << endl; // 文字列の比較 cout << boolalpha << "emp == abc ? " << (emp == abc) << endl; cout << "emp >= defgh ? " << (emp >= defgh) << endl; // 文字列の結合 string str = emp + " " + defgh; len1 = str.size(); cout << "-str- " << str << " 長さ " << len1 << endl; // 文字列の検索 int n = str.find("ef"); cout << (n+1) << " 番目以降の文字列 " << str.substr(5) << endl; return 0; }
-abc- abc -abc- abc 各文字列の長さ 3 5 0 -emp- abc 長さ 3 emp == abc ? true emp >= defgh ? false -str- abc defgh 長さ 9 6 番目以降の文字列 efgh
----------------------(C++)string クラス終わり--------------------
関数の型 関数名 ( 引数リスト )
例 : constexpr int func(・・・・・)
/****************************/ /* nの階乗の計算 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> int main() { /* データの入力 */ int n; printf("nの値を入力して下さい "); scanf("%d", &n); /* 階乗の計算 */ double kai = 1.0; /* 初期設定 */ int i1; for (i1 = 1; i1 <= n; i1++) kai *= (double)i1; /* 結果の出力 */ printf(" %dの階乗は=%f\n", n, kai); return 0; }
/****************************/ /* nの階乗の計算 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> double kaijo(int); int main() { /* データの入力 */ int n; printf("nの値を入力して下さい "); scanf("%d", &n); /* 階乗の計算 */ double kai = kaijo(n); /* 結果の出力 */ printf(" %dの階乗は=%f\n",n,kai); return 0; } /**************************/ /* mの階乗 */ /* m : データ */ /* return : mの階乗 */ /**************************/ double kaijo(int m) { double s = 1.0; int i1; for (i1 = 1; i1 <= m; i1++) s *= (double)i1; return s; }
printf(" %dの階乗は=%f\n", n, kaijo(n));
/****************************/ /* nの階乗の計算 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> int kaijo(int); int main() { /* データの入力 */ int n; printf("nの値を入力して下さい "); scanf("%d", &n); /* 階乗の計算 */ int kai = kaijo(n); /* 結果の出力 */ printf(" %dの階乗は=%d\n", n, kai); return 0; } /**************************/ /* mの階乗 */ /* m : データ */ /* return : nの階乗 */ /**************************/ int kaijo(int m) { int s; if (m > 1) s = m * kaijo(m-1); /* 自分自身を呼んでいる */ else s = 1; return s; }
/****************************/ /* nCrの計算 */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> double kaijo(int); int main() { /* データの入力 */ int n, r; printf("nとrの値を入力して下さい "); scanf("%d %d", &n, &r); /* nCrの計算と出力 */ double sn = kaijo(n); double sr = kaijo(r); double snr = kaijo(n-r); printf(" %dC%dは=%f\n", n, r, sn/(sr*snr)); return 0; } /**************************/ /* mの階乗 */ /* m : データ */ /* return : nの階乗 */ /**************************/ double kaijo(int m) { double s = 1.0; int i1; for (i1 = 1; i1 <= m; i1++) s *= (double)i1; return s; }
[記憶クラス] [型修飾]データ型 変数名, 配列名, 関数名, ・・・
const int n = 10; double x[n];
y = ::x;
01 /**********************************/ 02 /* 変数の有効範囲(同じファイル) */ 03 /* coded by Y.Suganuma */ 04 /**********************************/ 05 #include <stdio.h> 06 07 void sub3(void); 08 09 extern int j; // 26 行目で宣言された j 10 11 void sub1(void) 12 { 13 extern int i; // 25 行目で宣言された i 14 int k = 3; 15 printf("%d %d %d\n", i, j, k); 16 } 17 18 void sub2(void) 19 { 20 int i = 5; 21 int k = 6; 22 printf("%d %d %d\n", i, j, k); 23 } 24 25 int i = 1; 26 int j = 2; 27 28 int main() 29 { 30 sub2(); 31 sub1(); 32 sub3(); 33 34 return 0; 35 } 36 37 void sub3(void) 38 { 39 int k = 7; 40 printf("%d %d %d\n", i, j, k); 41 }
5 2 6 1 2 3 1 2 7
------------------------file 1---------------------------- /************************************/ /* 変数の有効範囲(別々のファイル) */ /* coded by Y.Suganuma */ /************************************/ void sub1(void); void sub2(void); void sub3(void); int i = 1; int j = 2; int main() { sub2(); sub1(); sub3(); return 0; } ------------------------file 2---------------------------- #include <stdio.h> void sub1(void) { extern int i; // file 1 で宣言された i extern int j; // file 1 で宣言された j int k = 3; printf("%d %d %d\n", i, j, k); } ------------------------file 3---------------------------- #include <stdio.h> void sub2(void) { extern int j; // file 1 で宣言された j int i = 5; int k = 6; printf("%d %d %d\n", i, j, k); } ------------------------file 4---------------------------- #include <stdio.h> void sub3(void) { extern int i; // file 1 で宣言された i extern int j; // file 1 で宣言された j int k = 7; printf("%d %d %d\n", i, j, k); }
01 /*******************************/ 02 /* C/C++における変数の有効範囲 */ 03 /* coded by Y.Suganuma */ 04 /*******************************/ 05 #include <stdio.h> 06 07 int x = 10; // 以下に記述されたすべての関数で有効 08 09 int main() 10 { 11 int x = 20; // main 関数内で有効 12 int y; // main 関数内で有効 13 14 y = ::x; // 7 行目の x を参照( C では許されない) 15 printf("x %d y %d\n", x, y); 16 17 if (x > 5) { 18 int y = 30; // 18,19 行目だけで有効 19 printf("x %d y %d\n", x, y); 20 } 21 22 printf("x %d y %d\n", x, y); 23 24 for (int x = 1; x <= 3; x++) { // x は 24 ~ 27 行目で有効 // この表現は,C では許されない 25 int y = x + 1; // 25,26 行目だけで有効 26 printf("x %d y %d\n", x, y); 27 } 28 29 printf("x %d y %d\n", x, y); 30 31 return 0; 32 }
x 20 y 10 x 20 y 30 x 20 y 10 x 1 y 2 x 2 y 3 x 3 y 4 x 20 y 10
namespace 名前空間名 { リスト };
namespace name1 { int func1( ・・・ ) { ・・・ } ・・・・・ };
x = name1::func1( ・・・ );
#include <stdio.h> namespace Test1 { void print(int k1, int k2) { printf("%d %d\n", k1, k2); } } namespace Test2 { void print(int k1, int k2) { printf("%d / %d", k1, k2); } } /****************/ /* main program */ /****************/ int main() { Test1::print(10, 20); Test2::print(10, 20); return 0; }
10 20 10 / 20
/****************/ /* main program */ /****************/ using namespace Test1; int main() { print(10, 20); Test2::print(10, 20); return 0; }
01 { 02 ・・・ 03 int a = 1; 04 int b = 5; 05 int n = sub(a, &b); 06 ・・・ 07 } 08 int sub(int a, int *c) // int* c でも可,c には b のアドレスのコピー 09 { 10 ・・・ 11 *c = 10; // 4 行目の b の値を変更 12 ・・・ 13 a = 100; // 3 行目の a の値は変化しない 14 ・・・ 15 }
/****************************/ /* 複数結果の受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> int sub(int, int, int *); // int* でも可 int n; /* 以下の関数にすべて有効 */ int main() { /* データの入力 */ int a, b; printf("a,b,及び,nの値を入力して下さい "); scanf("%d %d %d", &a, &b, &n); /* 関数の呼び出し */ int res; int ind = sub(a, b, &res); /* 変数resはアドレス渡し */ /* 結果の出力 */ if (ind == 0) printf("n %d result %d\n", n, res); else printf("n = 0 (n %d)\n", n); return 0; } /*****************************/ /* (a+b)/nの計算 */ /* a,b : データ */ /* res : 計算結果 */ /* return : =0 : normal */ /* =1 : n = 0 */ /*****************************/ int sub(int a, int b, int *res) // int* res でも可 { extern int n; int ind; if (n == 0) { ind = 1; n = 100; } else { ind = 0; *res = (a + b) / n; } return ind; }
n 3 result 2 n = 0 (n 100)
/****************************/ /* 複数結果の受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> void sub(int, int, int *, int *); int n; /* 以下の関数にすべて有効 */ int main() { /* データの入力 */ int a, b; printf("a,b,及び,nの値を入力して下さい "); scanf("%d %d %d", &a, &b, &n); /* 関数の呼び出し */ int res, ind; sub(a, b, &res, &ind); /* 結果の出力 */ if (ind == 0) printf("n %d result %d", n, res); else printf("n = 0 (n %d)\n", n); return 0; } /**************************/ /* (a+b)/nの計算 */ /* a,b : データ */ /* res : 計算結果 */ /* ind : =0 : normal */ /* =1 : n = 0 */ /**************************/ void sub(int a, int b, int *res, int *ind) { extern int n; if (n == 0) { *ind = 1; n = 100; } else { *ind = 0; *res = (a + b) / n; } }
/****************************/ /* 複数結果の受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> int *sub(int, int); int n; /* 以下の関数にすべて有効 */ int main() { /* データの入力 */ int a, b; printf("a,b,及び,nの値を入力して下さい "); scanf("%d %d %d", &a, &b, &n); /* 関数の呼び出し */ int *res = sub(a, b); /* resに結果が入る */ /* 結果の出力 */ if (res[0] == 0) printf("n %d result %d", n, res[1]); else printf("n = 0 (n %d)\n", n); delete [] res; return 0; } /**************************************/ /* (a+b)/nの計算 */ /* a,b : データ */ /* return : res[0] : =0 : normal */ /* =1 : n = 0 */ /* res[1] : 計算結果 */ /**************************************/ int *sub(int a, int b) { extern int n; int *res = new int [2]; if (n == 0) { res[0] = 1; n = 100; } else { res[0] = 0; res[1] = (a + b) / n; } return res; }
/****************************/ /* 複数結果の受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> void sub(int, int, int *); int n; /* 以下の関数にすべて有効 */ int main() { /* データの入力 */ int a, b; printf("a,b,及び,nの値を入力して下さい "); scanf("%d %d %d", &a, &b, &n); /* 関数の呼び出し */ int res[2]; sub(a, b, res); /* 結果の出力 */ if (res[0] == 0) printf("n %d result %d", n, res[1]); else printf("n = 0 (n %d)\n", n); return 0; } /***********************************/ /* (a+b)/nの計算 */ /* a,b : データ */ /* res : res[0] : =0 : normal */ /* =1 : n = 0 */ /* res[1] : 計算結果 */ /***********************************/ void sub(int a, int b, int *res) // void sub(int a, int b, int res[]) でも可 { extern int n; if (n == 0) { res[0] = 1; n = 100; } else { res[0] = 0; res[1] = (a + b) / n; } }
int func(int, int = 5, char * = "test");
func(x) func(x, 10);
func(x, 5, "test") func(x, 10, "test");
01 /****************************/ 02 /* デフォルト引数 */ 03 /* coded by Y.Suganuma */ 04 /****************************/ 05 #include <stdio.h> 06 07 void sub(int, int = 5, FILE * = stdout); 08 09 int main() 10 { 11 sub(10); // sub(10, 5, stdout)と解釈,標準出力 12 sub(10, 10); // sub(10, 10, stdout)と解釈,標準出力 13 sub(10, 20, stdout); // 標準出力 14 FILE *out = fopen("test.txt", "w"); 15 sub(10, 30, out); // ファイル test.txt へ出力 16 fclose(out); 17 return 0; 18 } 19 20 /*********************************/ 21 /* 整数の足し算 */ 22 /* x,y : データ */ 23 /* fp : 出力先 */ 24 /*********************************/ 25 void sub(int x, int y, FILE *fp) 26 //void sub(int x, int y = 5, FILE *fp = stdout) 27 { 28 fprintf(fp, "結果は=%d\n", x+y); 29 }
int sub(・・・, int c[], ・・・) // int sub(・・・, int *c, ・・・) でも可 { ・・・ } int main { int b[5]; ・・・ n = sub(・・・, b, ・・・); ・・・ }
/****************************/ /* 1次元配列の受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> void wa(int, int*, int*, int*); int main() { int a[2][3] = {{1, 2, 3}, {4, 5, 6}}, b[3]; /* 関数の呼び出し */ wa(3, &(a[0][0]), &(a[1][0]), b); /* 1行目と2行目のベクトル和の計算 */ /* 結果の出力 */ int i1; for (i1 = 0; i1 < 3; i1++) printf("%d ", b[i1]); printf("\n"); return 0; } /***********************************/ /* n次元ベクトルの和 */ /* n : 次元数 */ /* a,b : 和を計算するベクトル */ /* c : 計算結果が入るベクトル */ /***********************************/ void wa(int n, int* a, int* b, int* c) { int i1; for (i1 = 0; i1 < n; i1++) c[i1] = a[i1] + b[i1]; }
5 7 9
---------------------(C++11)初期化子リストの受け渡し-------------------------
/****************************/ /* 初期化子リストの受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <iostream> #include <vector> using namespace std; void wa(vector<pair<int, int>>, int *); int main() { int res[2] = {0}; vector<pair<int, int>> v {{1, 2}, {3, 4}, {5, 6}}; cout << "v"; for (auto x : v) cout << " (" << x.first << ", " << x.second << ")"; cout << endl; wa(v, res); // wa({{1, 2}, {3, 4}, {5, 6}}, res); // 初期化子リスト cout << " result " << res[0] << " " << res[1] << endl; return 0; } /*********************************************/ /* ペアの和 */ /* r[0] : vector の各要素の first の和 */ /* r[1] : vector の各要素の second の和 */ /*********************************************/ void wa(vector<pair<int, int>> v, int *r) { for (auto x : v) { r[0] += x.first; r[1] += x.second; } }
v (1, 2) (3, 4) (5, 6) result 9 12
----------------------(C++11)初期化子リストの受け渡し--------------------
int b[4][10];
int sub(・・・, int c[][10], ・・・)
int sub(・・・, int (*c)[10], ・・・)
C = AB, cij = Σkaikbkj k = 1, ・・・, m
/**********************************/ /* 2次元配列の受け渡し(方法1) */ /* coded by Y.Suganuma */ /**********************************/ #include <stdio.h> void seki(int, int, int, double [][3], double [][2], double [][2]); int main() { /* 関数の呼び出し */ double a[2][3] = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}}; double b[3][2] = {{1.0, 0.0}, {0.0, 1.0}, {0.0, 0.0}}; double c[2][2]; seki(2, 3, 2, a, b, c); /* 結果の出力 */ int i1; for (i1 = 0; i1 < 2; i1++) { int i2; for (i2 = 0; i2 < 2; i2++) printf("%f ", c[i1][i2]); printf("\n"); } return 0; } /**************************************/ /* 行列の積 */ /* n,m,l : 次元数 */ /* a : n x m */ /* b : m x l */ /* c : 計算結果が入る行列,n x l */ /**************************************/ void seki(int n, int m, int l, double a[][3], double b[][2], double c[][2]) { int i1, i2, i3; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < l; i2++) { c[i1][i2] = 0; for (i3 = 0; i3 < m; i3++) c[i1][i2] += a[i1][i3] * b[i3][i2]; } } }
1 2 4 5
/**********************************/ /* 2次元配列の受け渡し(方法2) */ /* coded by Y.Suganuma */ /**********************************/ #include <stdio.h> void seki(int, int, int, double**, double**, double**); int main() { /* 領域の確保と値の設定 */ double **a = new double* [2]; double **b = new double* [3]; double **c = new double* [2]; for (int i1 = 0; i1 < 2; i1++) { c[i1] = new double [2]; if (i1 == 0) a[i1] = new double [3] {1, 2, 3}; else a[i1] = new double [3] {4, 5, 6}; } for (int i1 = 0; i1 < 3; i1++) { if (i1 == 0) b[i1] = new double [2] {1, 0}; else if (i1 == 1) b[i1] = new double [2] {0, 1}; else b[i1] = new double [2] {0, 0}; } /* 関数の呼び出し */ seki(2, 3, 2, a, b, c); /* 結果の出力 */ for (int i1 = 0; i1 < 2; i1++) { for (int i2 = 0; i2 < 2; i2++) printf("%f ", c[i1][i2]); printf("\n"); } return 0; } /**************************************/ /* 行列の積 */ /* n,m,l : 次元数 */ /* a : n x m */ /* b : m x l */ /* c : 計算結果が入る行列,n x l */ /**************************************/ void seki(int n, int m, int l, double **a, double **b, double **c) { for (int i1 = 0; i1 < n; i1++) { for (int i2 = 0; i2 < l; i2++) { c[i1][i2] = 0; for (int i3 = 0; i3 < m; i3++) c[i1][i2] += a[i1][i3] * b[i3][i2]; } } }
/**********************************/ /* 2次元配列の受け渡し(方法3) */ /* coded by Y.Suganuma */ /**********************************/ #include <stdio.h> void seki(int, int, int, double *, double *, double *); int main() { /* 関数の呼び出し */ double a[2][3] = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}}; double b[3][2] = {{1.0, 0.0}, {0.0, 1.0}, {0.0, 0.0}}; double c[2][2]; seki(2, 3, 2, &a[0][0], &b[0][0], &c[0][0]); /* 結果の出力 */ int i1, i2; for (i1 = 0; i1 < 2; i1++) { for (i2 = 0; i2 < 2; i2++) printf("%f ", c[i1][i2]); printf("\n"); } return 0; } /**************************************/ /* 行列の積 */ /* n,m,l : 次元数 */ /* a : n x m */ /* b : m x l */ /* c : 計算結果が入る行列,n x l */ /**************************************/ void seki(int n, int m, int l, double *a, double *b, double *c) { int i1, i2, i3; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < l; i2++) { c[l*i1+i2] = 0; for (i3 = 0; i3 < m; i3++) c[l*i1+i2] += a[m*i1+i3] * b[l*i3+i2]; /* 添え字に注意 */ } } }
int (*sub)(double, char *)
int add(int a, int b) { return a + b; } int main() { int (*fun)(int, int) = &add; printf("和 %d\n", fun(2, 3)); return 0; }
xn+1 = xn - f(xn) / f'(xn)
/****************************/ /* 関数名の受け渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> double newton(double(*)(double), double(*)(double), double, double, double, int, int *); double snx(double); double dsnx(double); int main() { double eps1 = 1.0e-7; double eps2 = 1.0e-10; double x0 = 0.0; int max = 20, ind; double x = newton(snx, dsnx, x0, eps1, eps2, max, &ind); printf("ind=%d x=%f f=%f df=%f\n",ind,x,snx(x),dsnx(x)); return 0; } /*****************************************************/ /* Newton法による非線形方程式(f(x)=0)の解 */ /* fn : f(x)を計算する関数名 */ /* dfn : f(x)の微分を計算する関数名 */ /* x0 : 初期値 */ /* eps1 : 終了条件1(|x(k+1)-x(k)|<eps1) */ /* eps2 : 終了条件2(|f(x(k))|<eps2) */ /* max : 最大試行回数 */ /* ind : 実際の試行回数 */ /* (負の時は解を得ることができなかった) */ /* return : 解 */ /*****************************************************/ #include <math.h> double newton(double(*f)(double), double(*df)(double), double x0, double eps1, double eps2, int max, int *ind) { double x1 = x0; double x = x1; int sw = 0; *ind = 0; while (sw == 0 && *ind >= 0) { sw = 1; *ind += 1; double g = (*f)(x1); if (fabs(g) > eps2) { if (*ind <= max) { double dg = (*df)(x1); if (fabs(dg) > eps2) { x = x1 - g / dg; if (fabs(x-x1) > eps1 && fabs(x-x1) > eps1*fabs(x)) { x1 = x; sw = 0; } } else *ind = -1; } else *ind = -1; } } return x; } /************************/ /* 関数値(f(x))の計算 */ /************************/ double snx(double x) { double y = exp(x) - 3.0 * x; return y; } /********************/ /* 関数の微分の計算 */ /********************/ double dsnx(double x) { double y = exp(x) - 3.0; return y; }
ind=5 x=0.619061 f=0.000000 df=-1.142816
---------------------(C++11)関数オブジェクトとラムダ式-------------------------
/******************************/ /* 関数オブジェクトとラムダ式 */ /* coded by Y.Suganuma */ /******************************/ #include <stdio.h> #include <math.h> class Snx { public: double operator() (double x) { return (double)(exp(x) - 3.0 * x); } }; class DSnx { public: double operator() (double x) { return (double)(exp(x) - 3.0); } }; double newton1(auto, auto, double, double, double, int, int *); // ラムダ式 double newton2(Snx, DSnx, double, double, double, int, int *); // 関数オブジェクト int main() { double eps1 = 1.0e-7; double eps2 = 1.0e-10; double x0 = 0.0; int max = 20, ind; // ラムダ式 auto snx1 = [](double x){ return exp(x) - 3.0 * x; }; auto dsnx1 = [](double x){ return exp(x) - 3.0; }; double x = newton1(snx1, dsnx1, x0, eps1, eps2, max, &ind); printf("ind=%d x=%f f=%f df=%f\n",ind, x, snx1(x), dsnx1(x)); // 関数オブジェクト Snx snx2; DSnx dsnx2; x = newton2(snx2, dsnx2, x0, eps1, eps2, max, &ind); printf("ind=%d x=%f f=%f df=%f\n",ind, x, snx2(x), dsnx2(x)); return 0; } /*****************************************************/ /* Newton法による非線形方程式(f(x)=0)の解 */ /* fn : f(x)を計算する関数 */ /* dfn : f(x)の微分を計算する関数 */ /* x0 : 初期値 */ /* eps1 : 終了条件1(|x(k+1)-x(k)|<eps1) */ /* eps2 : 終了条件2(|f(x(k))|<eps2) */ /* max : 最大試行回数 */ /* ind : 実際の試行回数 */ /* (負の時は解を得ることができなかった) */ /* return : 解 */ /*****************************************************/ // ラムダ式 double newton1(auto f, auto df, double x0, double eps1, double eps2, int max, int *ind) { double x1 = x0; double x = x1; int sw = 0; *ind = 0; while (sw == 0 && *ind >= 0) { sw = 1; *ind += 1; double g = f(x1); if (fabs(g) > eps2) { if (*ind <= max) { double dg = df(x1); if (fabs(dg) > eps2) { x = x1 - g / dg; if (fabs(x-x1) > eps1 && fabs(x-x1) > eps1*fabs(x)) { x1 = x; sw = 0; } } else *ind = -1; } else *ind = -1; } } return x; } // 関数オブジェクト double newton2(Snx f, DSnx df, double x0, double eps1, double eps2, int max, int *ind) { double x1 = x0; double x = x1; int sw = 0; *ind = 0; while (sw == 0 && *ind >= 0) { sw = 1; *ind += 1; double g = f(x1); if (fabs(g) > eps2) { if (*ind <= max) { double dg = df(x1); if (fabs(dg) > eps2) { x = x1 - g / dg; if (fabs(x-x1) > eps1 && fabs(x-x1) > eps1*fabs(x)) { x1 = x; sw = 0; } } else *ind = -1; } else *ind = -1; } } return x; }
----------------------(C++11)関数オブジェクトとラムダ式終わり--------------------
/****************************/ /* 関数名の配列 */ /* coded by y.suganuma */ /****************************/ #include <stdio.h> /* FP は 2 つの int の引数を受け取り,int を返す関数へのポインタであると宣言 */ typedef int (*FP) (int, int); /* 4つの関数を宣言 */ int add(int, int); int sub(int, int); int mul(int, int); int div(int, int); int main() { int i1, x = 12; FP f_tb[] = {&add, &sub, &mul, &div}; /* 関数へのポインタ配列 */ for (i1 = 0; i1 < 4; i1++) printf("result %d\n", f_tb[i1](x, i1+1)); return 0; } /********/ /* 加算 */ /********/ 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); }
result 13 result 10 result 36 result 3
データ型 &別名 = 式;
int &y = x;
x = 10; y = 10;
const
/****************************/ /* 参照渡し */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> void sub(int &, int, int *, char *&, char *, char *); int main() { int x = 10, y = 20, z = 0; char *d1 = new char[6] {'d', 'a', 't', 'a', '1'}; char *d2 = new char[6] {'d', 'a', 't', 'a', '2'}; char d3[6] = "data3"; printf("x %d y %d z %d d1 %s d2 %s d3 %s\n", x, y, z, d1, d2, d3); sub(x, y, &z, d1, d2, d3); printf("x %d y %d z %d d1 %s d2 %s d3 %s\n", x, y, z, d1, d2, d3); return 0; } /********************************/ /* 参照渡しの例 */ /* a : intの参照渡し */ /* b : intのデータ渡し */ /* c : intのアドレス渡し */ /* c1 : アドレスの参照渡し */ /* c2 : アドレスの通常渡し */ /* c3 : 配列の通常渡し */ /********************************/ void sub(int &a, int b, int *c, char *&c1, char *c2, char *c3) // void sub(const int a, ・・・) とすれば,a の値を変更できない { a += 5; b += 5; *c = a + b; c3[1] = 'x'; c1++; c2++; c3++; printf("a %d b %d c %d c1 %s c2 %s c3 %s\n", a, b, *c, c1, c2, c3); }
x 10 y 20 z 0 d1 data1 d2 data2 d3 data3 a 15 b 25 c 40 c1 ata1 c2 ata2 c3 xta3 x 15 y 20 z 40 d1 ata1 d2 data2 d3 dxta3
/****************************/ /* 参照渡し(参照型関数) */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> int x = 10; int &sub(int); int main() { int y = 20; printf("x %d y %d\n", x, y); /* 現在の変数xの値の参照(関数を右辺) */ y = sub(5); printf("x %d y %d\n", x, y); /* 変数xに結果を代入(関数を左辺) */ sub(100) += 3; // 以下の 2 行でも可 // int& (*z)(int) = ⊂ // z(100) += 3; printf("x %d y %d\n", x, y); return 0; } /*********************/ /* 関数が変数xの別名 */ /*********************/ int &sub(int a) { x += a; return x; }
x 10 y 20 x 15 y 15 x 118 y 15
---------------------(C++11)右辺値参照・ムーブセマンティクス-------------------------
int x1 = 10; int& x2 = 10; // error int& x2 = x1; // 左辺値参照 int&& y1 = x1; // error int&& y2 = 20; // 右辺値参照
01 #include <iostream> 02 #include <string> 03 04 using namespace std; 05 06 class Test { 07 public: 08 int *data; 09 // コンストラクタ 10 Test() { 11 data = new int [10000]; 12 cout << " (コンストラクタ)"; 13 } 14 // copy コンストラクタ 15 Test(const Test& da) { 16 data = new int [10000]; 17 copy(da.data, da.data+10000, data); 18 cout << " (copyコンストラクタ)"; 19 } 20 // move コンストラクタ 21 Test(Test&& t) 22 { 23 data = t.data; 24 t.data = nullptr; 25 cout << " (moveコンストラクタ)"; 26 } 27 // デストラクタ 28 ~Test() { 29 delete [] data; 30 } 31 }; 32 33 int main() 34 { 35 // 右辺値参照 36 string&& x = "abc"; 37 string y = x; 38 // string&& z = y; // エラー 39 // string&& z = x; // エラー 40 cout << "右辺値参照 x " << x << " &x " << &x << " y " << y << " &y " << &y << endl; 41 x = "xxx"; 42 cout << " xを変更 x " << x << " &x " << &x << " y " << y << " &y " << &y << endl; 43 y = "yyy"; 44 cout << " yを変更 x " << x << " &x " << &x << " y " << y << " &y " << &y << endl; 45 // move 46 string m3 = "abc"; 47 string m4 = m3; 48 cout << "m3 を m4 に代入(普通)m3 " << m3 << " &m3 " << &m3 << " m4 " << m4 << " &m4 " << &m4 << endl; 49 // move(m3); // 何も起こらない 50 string m5 = move(m3); 51 cout << "m3 を m5 に代入(move)m3 " << m3 << " &m3 " << &m3 << " m5 " << m5 << " &m5 " << &m5 << endl; 52 // 右辺値参照の利用 53 cout << "tm を宣言"; 54 Test tm{}; // Test tm = Test(); 55 tm.data[10] = 10; 56 cout << " tm.data[10] = " << tm.data[10] << endl; 57 58 cout << "tm を t1 に代入,tm の data 変更"; 59 Test t1 = tm; 60 tm.data[10] = 20; 61 cout << " t1.data[10] = " << t1.data[10] << " tm.data[10] = " << tm.data[10] << endl; 62 63 cout << "tm を move し t2 へ"; 64 Test t2 = move(tm); // tmpは以後使用しない 65 cout << " t2.data[10] = " << t2.data[10] << " tm.data = nullptr\n"; 66 67 return 0; 68 }
右辺値参照 x abc &x 0x61fe88 y abc &y 0x61fea0 xを変更 x xxx &x 0x61fe88 y abc &y 0x61fea0 yを変更 x xxx &x 0x61fe88 y yyy &y 0x61fea0
m3 を m4 に代入(普通)m3 abc &m3 0x61feb8 m4 abc &m4 0x61fed0 m3 を m5 に代入(move)m3 &m3 0x61feb8 m5 abc &m5 0x61fee8
tm を宣言 (コンストラクタ) tm.data[10] = 10 tm を t1 に代入,tm の data 変更 (copyコンストラクタ) t1.data[10] = 10 tm.data[10] = 20 tm を move し t2 へ (moveコンストラクタ) t2.data[10] = 20 tm.data = nullptr
----------------------(C++11)右辺値参照・ムーブセマンティクス終わり--------------------
int main()
add 2 3
int main ( int argc, char *argv[], char *envp[] )
/******************************/ /* main関数の引数(数字の和) */ /* coded by Y.Suganuma */ /******************************/ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { /* 引数の内容の出力 */ printf(" 引数の数 %d\n",argc); printf(" プログラム名 %s\n",argv[0]); int i1, k, sum = 0; for (i1 = 1; i1 < argc; i1++) { k = atoi(argv[i1]); /* 文字を整数に変換 */ printf(" %d 番目の引数 %d\n", i1+1, k); sum += k; } /* 結果の表示 */ printf("結果=%d\n", sum); return 0; }
引数の数 3 プログラム名 test 2 番目の引数 2 3 番目の引数 3 結果=5
/*******************************/ /* main関数(環境変数の出力) */ /* coded by Y.Suganuma */ /*******************************/ #include <stdio.h> int main(int argc, char *argv[], char *envp[]) { int i1 = 0; while (envp[i1] != NULL) { printf("%d %s\n", i1+1, envp[i1]); i1++; } return 0; }
/****************************/ /* 関数名のオーバーロード */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> /****************/ /* 文字列の出力 */ /****************/ void print(char* moji) { printf("%s\n", moji); } /*****************/ /* double の出力 */ /*****************/ void print(double dbd) { printf("%f\n", dbd); } /**************/ /* int の出力 */ /**************/ void print(int ind) { printf("%d\n", ind); } /********/ /* main */ /********/ int main() { // 以下,データの型に対応した関数が選択される print("moji-retu"); print(3.14); print(100); return 0; }
moji-retu 3.140000 100
inline int sub(int x, ・・・)
/*********************************/ /* インライン関数と#defineマクロ */ /* coded by Y.Suganuma */ /*********************************/ #include <stdio.h> #include <math.h> #include <time.h> #define ookisa(x, y) sqrt(x * x + y * y) /* マクロによる計算 */ inline double length1(double, double); double length2(double, double); int main() { double a = 3.0; double b = 4.0; double x; long i1; clock_t c1, c2; /* マクロによる計算 */ c1 = clock(); for (i1 = 0; i1 < 1000000; i1++) x = ookisa(a, b); c2 = clock(); printf("計算時間は %f 秒です(マクロ)\n", (double)(c2-c1)/CLOCKS_PER_SEC); /* インライン関数 */ c1 = c2; for (i1 = 0; i1 < 1000000; i1++) x = length1(a, b); c2 = clock(); printf("計算時間は %f 秒です(インライン関数)\n", (double)(c2-c1)/CLOCKS_PER_SEC); /* 普通の関数 */ c1 = c2; for (i1 = 0; i1 < 1000000; i1++) x = length2(a, b); c2 = clock(); printf("計算時間は %f 秒です(普通の関数)\n", (double)(c2-c1)/CLOCKS_PER_SEC); return 0; } /***************************/ /* sqrt(x*x+y*y)(inline) */ /* x,y : 2つのデータ */ /* return : 結果 */ /***************************/ inline double length1(double x, double y) { return sqrt(x * x + y * y); } /*******************************/ /* sqrt(x*x+y*y)(普通の関数) */ /* x,y : 2つのデータ */ /* return : 結果 */ /*******************************/ double length2(double x, double y) { return sqrt(x * x + y * y); }
計算時間は 35 秒です(マクロ) 計算時間は 39 秒です(インライン関数) 計算時間は 40 秒です(普通の関数)
/****************************/ /* 例外処理 */ /* coded by Y.Suganuma */ /****************************/ #include <iostream> #include <math.h> using namespace std; void sq(double x, double y) { if (x < 0.0 && y < 0.0) { char *str = "両方とも負\n"; throw str; } else if (x < 0.0 || y < 0.0) { char *str = "片方が負\n"; throw str; } double z = sqrt(x+y); cout << z << endl; } int main() { try { double x, y; cout << "1 つ目のデータは? "; cin >> x; cout << "2 つ目のデータは? "; cin >> y; sq(x, y); } catch (char *str) { cout << str; } return 0; }
1.73205 両方とも負
/****************************/ /* 例外処理 */ /* coded by Y.Suganuma */ /****************************/ #include <iostream> #include <math.h> #include <string.h> using namespace std; class Negative { public: char *str; double x, y; Negative(char *str, double x, double y) { this->str = new char [100]; strcpy(this->str, str); this->x = x; this->y = y; } void message(int sw) { if (sw == 0) cout << " 1 番目の値を正にして再実行しました\n"; else cout << " データを修正してください\n"; } }; void sq(double x, double y) { if (x < 0.0 && y < 0.0) throw Negative("両方とも負\n", x, y); else if (x < 0.0 || y < 0.0) throw Negative("片方が負\n", x, y); double z = sqrt(x+y); cout << z << endl; } int main() { try { double x, y; cout << "1 つ目のデータは? "; cin >> x; cout << "2 つ目のデータは? "; cin >> y; sq(x, y); } catch (Negative &ng) { cout << ng.str; if (ng.y > 0.0) { ng.message(0); sq(-ng.x, ng.y); } else ng.message(1); } return 0; }
片方が負 1 番目の値を正にして再実行しました 1.73205
---------------------(C++11)例外処理-------------------------
int function( ・・・・・ ) noexcept
{
・・・・・
}
----------------------(C++11)例外処理終わり--------------------
情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |