ce-14. プログラムの実行順序
1
金子邦彦
C プログラミング応用)(全14回)
URL: https://www.kkaneko.jp/pro/c/index.html
C言語プログラムの実行順序の理解、Microsoft Visual
Studio C++のステップ実行機能を用いた変数値変化の観察。
学習内容の構成
1. プログラムの順次実行:メイン関数から始まり上から下
へ順に実行される基本原理
2. ビルドと実行ファイル生成C++ソースファイルからの
実行ファイル生成、構文エラー時の対処
3. 条件分岐if文・else文による条件式の成否に応じた処理
の切り替え
4. 関数呼び出しと戻り:関数呼び出しによるジャンプと
return文による呼び出し元への復帰
5. デバッグ機能:ステップ実行(F10)、ステップイン
F11)、ブレークポイントによる実行制御と変数観察
前提:Microsoft Visual Studio C++の基本操作、C言語の変
数・繰り返し・関数の基礎知識
意義:プログラムの動作原理の理解、デバッグ技法の習得
2
自由落下距離
前回の授業の「例題1」の復習と重要事項の確認
地上で物を落とし始めた後の自由落下距離を求める
重力加速度 g 9.8 とする
自由落下距離を求めるために,プログラム中に,計算
y = ( 9.8 / 2.0 ) * x * x を書く
3
Microsoft Visual Studio C++ の画面構成
4
ファイルなど
が表示される
C++ソースファイ
ルの編集はここで行
ビルド結果が現れ
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
5
自由落下距離の
計算を行っている部分
データファイル名
d:¥¥data.csv
は適切に設定すること
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
6
計算を行っている部分
キーボードからの
データ読み込み
行っている部分
ファイルへの書き出し
を行っている部分
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
7
Cプログラムはメイン関数から
実行開始
プログラムは順次実行
変数 x, y, buf, i, start_x,
step_x, fp をメモリエリア中に確保
printf でメッセージを表示
fgets でキーボードから1行を読み込み
sscanf で数値を読み取って変数に格納
printf でメッセージを表示
fgets でキーボードから1行を読み込み
sscanf で数値を読み取って変数に格納
20回の繰り返し (i = 0, 1, ... 19)
x の値から
( 9.8 / 2.0 ) * x * x
を求め,y に書き込む
「ビルド」による実行ファイルの生成
8
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
C++ソースファイル
その他のファイル
ビルド
Microsoft Visual
Studio C++
「ビルド」により実行ファイル等
が生成される
実行ファイル
構文エラーがあると,
ビルド」時にエラーメッセージが表示される
(実行ファイルは生成されない)
その他,ビルドの結果
として生成されるファイル
「消去(clean)」の操作
9
その他のファイル
ビルド
Microsoft Visual
Studio C++
「消去(clean)」の操作により,
ビルドの結果が消える
(元のソースファイル等は消えない)
実行ファイル
その他,ビルドの結果
として生成されるファイル
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
C++ソースファイル
10
「消去(clean)」の操作
「消去(clean)」の操作を行っても,元のソース
ファイルが消えるわけでは無い(ディスク使用量
節約になる)
構文エラーの例
全角文字
全角文字はプログラム中の決められた場所にしか入れ
てはならない。
コメント
文字列(ダブルクォートで囲まれた部分)
" 抜け
; 忘れ
など
11
ビルド結果が現れる.「1
正常終了,0 失敗・・・」
ならばビルドに成功
ビルドが正常終了し,実行ファイルが生成できた
ことを示すメッセージ
12
13
構文エラーの例(1)
ここでは,セミコロン「;」を入れるのを
忘れている(人間の目では発見が難しい)
ビルドが失敗したことを示すメッセージ
7行目に構文エラー
構文エラーの例(1)
マウスで「構文エラー」とある行をダブルクリックすると,
エディタのカーソルが動く
エラーの付近にマークが付く
14
ここでは,セミコロン「;」を入れるのを
忘れている(人間の目では発見が難しい)
15
構文エラーの例(2)
ここで,「doublr」とあるのはスペルミス
(正しくは,double
ビルドが失敗したことを示すメッセージ
(ミスは1箇所なのに,エラーは多数)
行目に「’doublr:定義されていない識別子です」
データファイル
プログラムでのファイル操作
ファイル生成
ファイル読み出し
ファイル書き込み
16
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
「自由落下距離」のプログラムを実行すると
データファイルが生成される
17
C++ソースファイル
その他のファイル
ビルド
Microsoft Visual
Studio C++
実行ファイル
データファイル
自由落下距離のプログラムを実行すると,
データファイル data.csv が生成される
データファイルに関係
している部分
例題1.自由落下距離
「自由落下距離」のプログラムについて,実行順
を確認するとともに,変数の値の変化を観察する
Microsoft Visual Studio C++ のステップ実行機能を使用
前回の授業で作成した「プロジェクト」を開く
18
#include "stdio.h"
#include <math.h>
#pragma warning(disable:4996)
int main()
{
double x;
double y;
char buf[256];
int i;
double start_x;
double step_x;
FILE* fp;
printf( "start_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &start_x );
printf( "step_x =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &step_x );
fp = fopen( "d:¥¥data.csv", "w" );
for( i = 0; i < 20; i++ ) {
x = start_x + ( i * step_x );
y = ( 9.8 / 2.0 ) * x * x;
printf( "x= %f, y= %f¥n", x, y );
fprintf( fp, "x=, %f, y=, %f¥n", x, y );
}
fprintf( stderr, "file d:¥¥data.csv created¥n" );
fclose( fp );
return 0;
}
19
自由落下距離の
計算を行っている部分
データファイル名
d:¥¥data.csv
は適切に設定すること
20
ビルド後の画面
ビルドが正常終了したこと
を示すメッセージ
ビルドの手順:
「ビルド」「ソリューションのビ
ド」
ビルドが正常終了しない
ときは,プログラム中の
構文エラーを疑う
「1.正常終了」を
確認
実行
を示すマーク
実行ウインドウ
が開く
F10」キーを押すとステップ実行が
始まる.(マウスカーソルは,
Microsoft Visual Studio C++ に入れておく)
21
変数の値を
観察できる
さらに「F10」キーを押すとス
テップ実行が続く
マークが進む
22
表示されたメッセージ
printf( "start_x=" );の実行が
終わったので,メッセージが出る
さらに「F10」キーを押すとス
テップ実行が続く
23
変数の値を
観察できる
マークが進む
入力待ち状態
( fgets( buf, 256, stdin );の実行が
終わったので,実行ウインドウに
おけるキーボードからの入力待ち
状態に入っている)
さらに「F10」キーを押すとステップ実行
が続く(今度は入力待ち状態)
24
マークが
変化
マークが現れる
読み込んだデータが変数 buf
入ったことが確認できる
ここでは 0 Enter
実行ウインドウで,「0 Enter」と
すると,ステップ実行が再開する
実行ウインドウで「0 Enter」とすると実
行が続く0 の部分は数値なら何でも良い)
25
実行手順 (通常実行の場合)
Microsoft Visual Studio C++ 「デバック」
「デバッグなしで開始」
すると,新しいウインドウが開く
新しいウインドウが現れるので, start_x, step_x
の値をキーボードから与える
例えば
start_x = 0
step_x = 0.1
ウインドウは消えるが,d: ドライブに data.csv
(データファイル)が作成されるので,Excel 等で
開き確認する
26
実行手順 (ステップ実行の場合)
Microsoft Visual Studio C++
F10(ファンクションの10)
すると,新しいウインドウが開く
F10」は,Microsoft Visual Studio C++のウインドウ内
にマウスカーソルを入れた状態で押すこと
F10 を押すたびに,1ステップずつ実行が進
27
例題2.平方根の計算
浮動小数データを読み込んで,平方根の計算と表
示を行うプログラムを作る.
但し,負の数の場合には,メッセージを表示する
負の数であるかどうかによって条件分岐を行うために if
文を使う.
例) 9のとき:
-1のとき: メッセージを表示
28
#include "stdio.h"
#include <math.h>
int main()
{
double x;
double y;
char buf[256];
int ch;
printf("x=");
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &x );
if ( x < 0 ) {
printf("負なので計算できません¥n");
}
else {
y = sqrt(x);
printf("sqrt(%f)=%f¥n", x, y);
}
ch = getchar();
ch = getchar();
return 0;
}
条件が成り立つ場合
に実行される部分
条件式
条件が成り立たない
場合に実行される部分
29
#include "stdio.h"
#include <math.h>
int main()
{
double x;
double y;
char buf[256];
int ch;
printf("x=");
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &x );
if ( x < 0 ) {
printf("負なので計算できません¥n");
}
else {
y = sqrt(x);
printf("sqrt(%f)=%f¥n", x, y);
}
ch = getchar();
ch = getchar();
return 0;
}
実行順
(x<0) の場合
30
#include "stdio.h"
#include <math.h>
int main()
{
double x;
double y;
char buf[256];
int ch;
printf("x=");
fgets( buf, 256, stdin );
sscanf_s( buf, "%lf¥n", &x );
if ( x < 0 ) {
printf("負なので計算できません¥n");
}
else {
y = sqrt(x);
printf("sqrt(%f)=%f¥n", x, y);
}
ch = getchar();
ch = getchar();
return 0;
}
実行順
(x0) の場合
31
平方根の計算
32
マークが「if ( x < 0 ) {」に来たときに,
F10」を押すと
y = sqrt(x);」の行にジャンプする
33
条件分岐とは
「ある条件式」が成り立てばAを、成り立たなけ
ればBを実行
34
Yes
No
条件式
if 文と else
「条件式」が成り立てばAを、成り立たなければ
を実行
35
Yes
No
条件式
if ( 条件式 ) {
;
...
}
else {
;
...
}
if
if 文のみを書いて,else 文を書かないこともできる.
「ある条件」が成り立つときに限りAを実行
36
Yes
No
条件式
if ( 条件式 ) {
;
...
}
比較演算
条件式の中には,ふつう,比較演算を書く
演算子 意味
左辺が右辺より小さい
<= 左辺が右辺以下
左辺が右辺より大きい
>= 左辺が右辺以上
== 左辺が右辺と等しい
!= 左辺が右辺と等しくない
37
比較演算の例
if (age >= 20 ){
printf("You may drink alcoholic beverage. ");
}
else{
printf("You may not drink alcoholic
beverage.");
}
38
「左辺が右辺以上」の意味
字下げとセミコロンを忘れないこと
セミコロンを忘れる
プログラムは動かない
字下げを忘れると
プログラムは動くが,
読みづらい
39
if ( 条件式 ) {
;
...
}
else {
;
...
}
if ( 条件式 ) {
;
...
}
字下げ
セミコロン
字下げ
セミコロン
セミコロン
字下げ
例題3.棒グラフでのステップ実行
整数から,その長さだけの棒を表示する関数 bar
を作る
例) 5 → *****
関数 bar を使って,「整数を読み込んで,読み込
んだ長さの棒を表示するメイン関数を作る
ステップ実行(「F10」キー)を行う
40
棒グラフ
#include "stdio.h"
#include <math.h>
void bar( int len )
{
int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("¥n");
return;
}
int main()
{
int len;
char buf[256];
int ch;
printf( "len =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d¥n", &len );
bar( len );
ch = getchar();
ch = getchar();
return 0;
}
41
bar関数
main関数
プログラム実行は
main 関数(メイン
関数)から始まる
複数の関数を含む
プログラム
#include "stdio.h"
#include <math.h>
void bar( int len )
{
int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("¥n");
return;
}
int main()
{
int len;
char buf[256];
int ch;
printf( "len =" );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d¥n", &len );
bar( len );
ch = getchar();
ch = getchar();
return 0;
}
関数呼び出し
プログラム実行順
42
戻り
メイン関数の先頭行
がプログラム実行の始まり
メイン関数内の return
がプログラム実行の終わり
43
ビルド後の画面
ビルドが正常終了したこと
を示すメッセージ
ビルドの手順:
「ビルド」「ソリューションのビ
ド」
ビルドが正常終了しない
ときは,プログラム中の
構文エラーを疑う
ステップ実行
44
F10」キーを押すとステップ実行が始ま
.(マウスカーソルは,
Microsoft Visual Studio C++ 内に入れておく)
さらに「F10」キーを押すとス
テップ実行が続く
マークが進む
変数の値が変化する
45
さらに「F10」キーを押すとス
テップ実行が続く
46
実行ウインドウで「5 Enter」とすると実行
が続く5 の部分は整数なら何でも良い)
47
さらに「F10」キーを押すとス
テップ実行が続く
48
例題3(b).棒グラフでのステップイン
ステップ実行とステップインを行う
ステップ実行(「F10」キー)
ステップイン(「F11」キー)
例題2のプログラムをそのまま使う
49
プログラム実行順
普通,プログラム中の文は,上から下へ順に実行
される
関数呼び出しでは,関数の先頭に「ジャンプ」す
る.
関数呼び出しの例 bar( len );
呼び出された関数の中で return 文に出会うと,関
数呼び出しの場所に戻る.
50
このことは,C言語が「手続き型言語」と言われる理由の1つ
#include "stdio.h"
#include <math.h>
void bar( int len )
{
int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("¥n");
return;
}
int main()
{
int len;
int ch;
printf( "len=" );
scanf( "%d", &len );
bar( len );
ch = getchar();
ch = getchar();
return 0;
}
プログラムの流れ
51
bar 関数
メイン関数
bar( len );
関数呼び出し
return;
プログラムの実行開始
プログラムの実行終了
* printf, scanf
呼び出しについては
図では省略
ステップイン機能
マークが「bar( len );」の行に来たときに
F11 キーを押して,ステップイン機能を使う
52
ステップイン機能
マークが bar 関数の内部に移る
後は,「F10」キーでステップ実行を続ける
53
補足説明事項
54
ブレークポイント
Microsoft Visual Studio C++ のブレークポイント
機能を試す
ブレークポイント
55
Microsoft Visual Studio.NET
でのブレークポイント設定
56
ここをクリックして,ブレークポイントの設定
「●」はブレークポイント設定済みの印
ブレークポイントでプログラム実行が中断するので,
実行結果の画面が消えずに残る