Cプログラミング演習
中間まとめ1
1
資料の構成
1. 変数種類
前回授業のプログラムを使って確認
int 整数
char 文字
double 浮動小数 など
2. 論理的エラーの発見と解決
ステップ実行機能なども使用して論理
的エラーの発見と解決の練習を行う
3. 条件分岐と繰り返しに関する練習
while if の組み合わせ
2
変数の種類
3
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{
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 = sin( 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;
}
変数は4種類使っている
整数を扱う int
文字を扱う char
整数, 5, -3, 0 など
文字は, 1, 0, 3, -, a など
数字(1, 0, 3 など)も文字の一種
浮動小数を扱う double
3.14, -1.414, 5, 0, -3 など
5, 0, -3 などの整数も浮動小数の一種)
ファイルポインタ
ファイル操作に使う変数
double 型の変数については,
sscanf では %lf」(エルエフ)を,printf ,
fprintf では%f」を,使う決まりになっている 4
#include "stdafx.h"
#include <math.h>
void bar( int len )
{
int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("\n");
return;
}
int _tmain()
{
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;
}
変数は2種類使っている
整数を扱う int
文字を扱う char
整数は, 5, -3, 0 など
文字は, 1, 0, 3, -, a など
数字(1, 0, 3 など)も文字の一種
変数 len int 型なので,
sscanf では%d」を使う決まりになっている
5
論理的エラーの発見と解決
6
例題1.論理的エラーの例
(1)
次ページのプログラムは,構文エラー
は無い(ビルドは問題無くできる)
実行してみると,動作がおかし
資料の手順に従って,原因を探し,解
決しなさい
7
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{
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 = sin( x );
printf( "x= %d, y= %d\n", x, y );
fprintf( fp, "x=, %d, y=, %d\n", x, y );
}
fprintf( stderr, "file d:\\data.csv created\n" );
fclose( fp );
return 0;
}
手順①
まずは,このページのプログラムを
ビルド,実行してみなさい
8
ビルド後の画面
ビルドが正常終了したことを示
すメッセージ
ビルドの手順:
「ビルド」「ソリューションの
ビルド」
「1.正常終了」を確認
9
実行中画面
実行の手順:
「デバッグ」
「デバッグなしで
開始」
実行ウインドウが現れるので,
start_x = 0 Enter
step_x = 0.1 Enter
のように操作してみる 10
実行結果の確認
d ドライブdata.csv
をダブルクリックする
実行の結果,データファイルが生成されるので,
中身を確認してみる
11
結果期待通りになっていない
12
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{
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 = sin( x );
printf( "x= %d, y= %d\n", x, y );
fprintf( fp, "x=, %d, y=, %d\n", x, y );
}
fprintf( stderr, "file d:\\data.csv created\n" );
fclose( fp );
return 0;
}
手順②
元のプログラムに間違いがあることが
分かった.
次ページに正しいプログラムを載せて
いるので,ビルドと実行行ってみなさい
13
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{
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 = sin( 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;
}
x, ydouble 型の変数なので,
sscanf では %lf」を,printf, fprintf
では「%f」を使う決まりになっている
%d」ではなく,「%f」が正しい
14
例題2.論理的エラーの例
(2)
次ページのプログラムは,構文エラー
は無い(ビルドは問題無くできる)
実行してみると,動作がおかしい
資料手順に従って箇所特定しな
さい
15
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{
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 = sin( 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;
}
手順①
まずは,このページのプログラムを
ビルド,実行してみなさい
16
ビルド後の画面
ビルドが正常終了したことを示
すメッセージ
ビルドの手順
「ビルド」「ソリューションの
ビルド」
「1.正常終了」を確認
17
実行中の画面(1/2)
実行の手順:
「デバッグ」
「デバッグ無しで
開始」
実行ウインドウが現れるので,
start_x = 0 Enter
step_x = 0.1 Enter
のように操作してみると・・・ (次ページ) 18
エラーメッセージが出る
表示が止まる
実行中画面(2/2)
19
エラーメッセージが出る
表示が止まる
「中止」をクリックして,実行を中止する 20
実行してみると,動作がおかしいこと
が分かった.
次ページ以降の手順により,テップ
実行で,箇所を特定してみる
21
実行
を示すマーク
実行ウインドウ
が開く
F10」キーを押すとステップ実行
始まる.(マウスカーソルは,
Microsoft Visual Studio .NET に入れておく) 22
変数の値を
観察できる
さらに「F10キーを押すとステップ
実行が続く
マークが進む
23
表示されたメッセージ
printf( "start_x=" );の実行が
終わったので,メッセージが出る
さらに「F10」キーを押すとステップ
実行が続く
マークが進む
変数の値を
観察できる
24
マークはえる
(正常な動作)
入力待状態
(fgets( buf, 256, stdin );実行
終わったので,実行ウインドウに
おけるキーボードからの入力待ち
状態に入っている)
さらに「F10キーを押すとステップ
実行が続く(今度は入力待ち状態
変数の値を
観察できる
25
マークが現れる
読み込んだデータが変数 buf
入ったことが確認できる
ここでは 0 Enter
実行ウインドウで,「0 Enter」と
すると,ステップ実行が再開する
実行ウインドウで「0 Enter」とすると実
行が続く0 の部分は数値ならでも良い) 26
マーク
F10」を押し続けて,「fprintf( fp, "x=", ・・・」
の行に来たときに「F10」を押すと(次ページ) 27
エラーメッセージが出る
(箇所の特定はできた) 28
エラーが
起きた場所
変数 fp を使っている
29
エラーが
きた場所
変数 fp を使っている
fp の値がおかしい.
???」が現れている(慣れる
とすぐに分かるようになる)
30
エラーが
起きた場所
変数 fp を使っている
fp の値がおかしい.
???」が現れている(慣れる
とすぐに分かるようになる)
fp の値は,ここで設定している
31
エラーが
きた場所
変数 fp を使っている
fp の値がおかしい.
???」が現れている(慣れる
とすぐに分かるようになる)
fp の値は,ここで設定している
k」になっているの
が間違い
32
例題2について
ステップ実行での,箇所の特定を行っ
てみた
このように,ステップ実行を行い,変
数の値を変化を確認することが,論理
エラーの解決役立
33
例題3.繰り返しと条件分岐
キーボードから数値(正の整数)を読
み込んで,足し算を続けるプログラム
変数の用途
sum 足し算の結果
buf キーボードから読み込んだ1行分
nキーボードから読み込んだ整数値
34
#include "stdafx.h"
#include <math.h>
int _tmain()
{
int sum;
int n;
char buf[256];
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ:", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
printf ( "%d + %d = %d\n", sum, n, sum + n );
sum = sum + n;
}
else {
break;
}
}
return 0;
}35
36
実行画面
37
実行画面
-2 Enter」のようにして,負の数を与えると,
プログラムの実行が止まる
38
#include "stdafx.h"
#include <math.h>
int _tmain()
{
int sum;
int n;
char buf[256];
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ:", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
printf ( "%d + %d = %d\n", sum, n, sum + n );
sum = sum + n;
}
else {
break;
}
}
return 0;
}
while による繰り返し部分
n 0 のとき実行される部分
n < 0 のとき実行される部分 39
#include "stdafx.h"
#include <math.h>
int _tmain()
{
int sum;
int n;
char buf[256];
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ:", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
printf ( "%d + %d = %d\n", sum, n, sum + n );
sum = sum + n;
}
else {
break;
}
}
return 0;
}
while ( 1 ) , 無条件に繰り返す
という意味になる
(「1」が,常に成り立つ条件式の意味)
この「break;」は,while による繰り返し処理
から抜け出すという意味になる.
n < 0 のとき抜け出す) 40
#include "stdafx.h"
#include <math.h>
int _tmain()
{
int sum;
int n;
char buf[256];
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
printf ( "%d + %d = %d\n", sum, n, sum + n );
sum = sum + n;
}
else {
break;
}
}
return 0;
}}」にセミコロンは付けない
}」にセミコロンは付けない
}」にセミコロンは付けない
41
#include "stdafx.h"
#include <math.h>
int _tmain()
{
int sum;
int n;
char buf[256];
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ:", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
printf ( "%d + %d = %d\n", sum, n, sum + n );
sum = sum + n;
}
else {
break;
}
}
return 0;
}
printf, fprintf では,変数名や式を書く
ことができる
それぞれ対応
42
#include "stdafx.h"
#include <math.h>
int _tmain()
{
int sum;
int n;
char buf[256];
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
printf ( "%d + %d = %d\n", sum, n, sum + n );
sum = sum + n;
}
else {
break;
}
}
return 0;
}sum = sum + n は,sum + n の値を求めて
sum に格納するという意味 43
課題
プログラムの作成と動作確認を行いなさ
い.次の1,2,3のうち1つ以上を各
自で選ぶこと
1. 例題3のプログラムについて,計算結果
を,データファイル d:\sum.csv
に出力するように書き換えなさ
2. for あるいは while を使い,
を求めるプログラムを作成しなさい
3. 例題3のプログラムについて,平均値を
表示できるように書き換えなさ
n
k
kk
1
)1(
44
補足説明.論理的エラーの例
(3)
次ページのプログラムは,構文エラー
は無い(ビルドは問題無くできる)
実行してみると,動作がおかしい
45
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{int sum;
int n;
char buf[256];
FILE *fp;
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してください\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ:", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
fp = fopen( "d:\\data.csv", "w" );
printf ( "%d + %d = %d\n", sum, n, sum + n );
fprintf(fp,"%d, %d, %d\n", sum, n, sum + n );
sum = sum + n;
}
else {break;
}
}return 0;
}
while による繰り返し部分
n 0 のとき実行される部分
n < 0 のとき実行される部分 46
ビルド後の画面
ビルドが正常終了したことを示
すメッセージ
ビルドの手順
「ビルド」「○○のビルド」
47
実行中画面
実行の手順:
「デバッグ」
「実行」
実行ウインドウが現れるので,
整数値をどうぞ 3 Enter
整数値をどうぞ: 4 Enter
整数値をどうぞ: 5 Enter
整数値をどうぞ: 6 Enter
整数値をどうぞ: -2 Enter
のように操作してみる 48
実行結果の確認
z ドライブのdata.csv
をダブルクリックする
実行の結果,データファイルが生成されるので,
中身を確認してみる
49
結果が期待通りになっていない
(1番最後の1行分しか入っていない)
50
#include "stdafx.h"
#include <math.h>
#pragma warning(disable:4996)
int _tmain()
{int sum;
int n;
char buf[256];
FILE *fp;
printf( "整数の足し算を続けます\n" );
printf( "終了したいときは,負の数を入力してくださ\n" );
sum = 0;
while ( 1 ) {
printf( "整数値をどうぞ:", buf );
fgets( buf, 256, stdin );
sscanf_s( buf, "%d\n", &n );
if ( n >= 0 ) {
fp = fopen( "d:\\data.csv", "w" );
printf ( "%d + %d = %d\n", sum, n, sum + n );
fprintf(fp,"%d, %d, %d\n", sum, n, sum + n );
sum = sum + n;
}
else {break;
}
}return 0;
}
fopen でのファイルオープンを
何度も繰り返しているのが原因
(ファイルオープンは1回行うの
が正しい)
51