Download : sample-001.c
/*
* 2020/06/19 sample-001.c
*/
/*
* "Hello, World" again
*/
#include <stdio.h>
int main ( int argc, char *argv[] ) {
printf ( "Hello, World\n" ); /* "Hello, World" という文字列と改行 ( "\n" ) を表示する */
return 0;
}
$ ./sample-001.exe Hello, World $
Download : sample-002.c
/*
* 2020/06/19 sample-002.c
*/
/*
* プログラム・ノックアウト (1)
*/
#include <stdio.h>
int main ( int argc, char *argv[] ) {
/* まず、printf をノックアウト */
return 0;
}
$ ./sample-002.exe $
Download : sample-003.c
/* * 2020/06/19 sample-003.c */ /* * プログラム・ノックアウト (2) */ /* * main 関数もなくしたら ? */ /* ここには何もない */
$ cc -c sample-003.c $ cc -o sample-003.exe sample-003.o /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 0 が無効なシンボル索引 11 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 1 が無効なシンボル索引 12 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 2 が無効なシンボル索引 2 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 3 が無効なシンボル索引 2 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 4 が無効なシンボル索引 11 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 5 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 6 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 7 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 8 が無効なシンボル索引 12 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 9 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 10 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 11 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 12 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 13 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 14 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 15 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 16 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 17 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 18 が無効なシンボル索引 13 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): 再配置 19 が無効なシンボル索引 21 を持っています /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): 再配置 0 が無効なシンボル索引 2 を持っています /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: 関数 `_start' 内: (.text+0x20): `main' に対する定義されていない参照です collect2: error: ld returned 1 exit status $
Download : sample-004.c
/*
* 2020/06/19 sample-004.c
*/
/*
* プログラム・ノックアウト (3)
*/
/*
* #include <stdio.h> // #include を無くした
*/
int main ( int argc, char *argv[] ) {
printf ( "Hello, World\n" ); /* この行で「警告」が出る */
return 0;
}
$ cc -c sample-004.c sample-004.c: In function ‘main’: sample-004.c:15:3: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default] printf ( "Hello, World\n" ); /* この行で「警告」が出る */ ^ $
Download : sample-005.c
/*
* 2020/06/19 sample-005.c
*/
/*
* プログラム・ノックアウト (4)
*/
/*
* #include <stdio.h> // #include を無くした
*/
int main ( int argc, char *argv[] ) {
/* printf も使わないと、「警告」はなくなった */
return 0;
}
$ ./sample-005.exe $
Download : sample-006.c
/*
* 2020/06/19 sample-006.c
*/
/*
* プログラム・ノックアウト (5)
*/
void main ( void ) { /* int を void に変更, 引数宣言もなくして良い */
/* return 0; を削って、空っぽにする */
}
/*
最も短い C 言語プログラムの実現
*/
$ ./sample-006.exe $
Download : sample-007.c
/*
* 2020/06/19 sample-007.c
*/
/*
* プログラム・ノックアウト (6)
*/
/*
* #include の代りに printf の extern 宣言
*/
extern int printf ( const char *message, ... );
/* 「extern void printf ( char *message );」 ではない ?? */
/*
* main
*/
int main ( int argc, char *argv[] ) {
printf ( "Hello, World\n" ); /* 「警告」が消えた */
return 0;
}
$ ./sample-007.exe Hello, World $
Download : sample-008.c
/*
* 2020/06/19 sample-008.c
*/
#include <stdio.h>
/*
* 文字列を三度表示する : 関数定義の例
*/
void threeTimesPrint ( char *message ) {
printf ( message ); /* 一度目 */
printf ( message ); /* ニ度目 */
printf ( message ); /* 三度目 */
}
/*
* main
*/
int main ( int argc, char *argv[] ) {
threeTimesPrint ( "Hello\n" ); /* 関数呼出しの例 */
threeTimesPrint ( "こんにちは\n" );
return 0;
}
$ ./sample-008.exe Hello Hello Hello こんにちは こんにちは こんにちは $
Download : sample-009.c
/*
* 2020/06/19 sample-009.c
*/
#include <stdio.h>
/*
* echo_char ( char ch )
* char ch -- 引数で指定された文字
* 引数で指定された文字を『』付で出力
*/
void echo_char ( char ch ) {
printf ( "『" );
putchar ( ch ); /* 引数で指定された文字を出力する */
printf ( "』" );
}
/*
* main
*/
int main ( int argc, char *argv[] ) {
printf ( "何か文字を入れてから[Enter]キーを押す : " );
echo_char ( getchar() ); /* getchar() で文字を読込み、それを出力 */
putchar ( '\n' );
return 0;
}
A
$ ./sample-009.exe < sample-009.in 何か文字を入れてから[Enter]キーを押す : A 『A』 $
Download : sample-010.c
/*
* 2020/06/19 sample-010.c
*/
/*
* extern 宣言
*/
extern void println ( char *message );
extern void nprinttail ( char *tail, char *message );
/*
* n 回数の繰返し
*/
int main ( int argc, char *argv[] ) {
println ( "毎回改行「Hello」: " );
nprinttail ( "\n\n\n", "Hello" );
println ( "3 回目, 7 回目だけ改行「Hello」: " );
nprinttail ( "12\n456\n", "Hello" );
return 0;
}
$ ./sample-010.exe $
Download : sample-011.c
/*
* 2020/06/19 sample-011.c
*/
#include <stdio.h>
/*
* 文字の扱い
*/
int main ( int argc, char *argv[] ) {
printf ( "abc\n" ); /* 「abc(改行)」とでる */
printf ( "abc\n" + 1 ); /* 「bc(改行)」とでる ( 1 を加えると短くなる ) */
putchar ( 'A' ); /* 「A」とでる */
putchar ( '\n' ); /* 「(改行)」とでる */
putchar ( 'A' + 1 ); /* 文字に 1 を加えると ? */
putchar ( '\n' ); /* 「(改行)」とでる */
return 0;
}
$ ./sample-011.exe abc bc A B $
Download : sample-012.c
/*
* 2020/06/19 sample-012.c
*/
/*
* extern 宣言
*/
extern void printcharln ( char ch );
/*
* 文字の扱い(2)
*/
int main ( int argc, char *argv[] ) {
printcharln ( 'A' + 1 ); /* 'B' になった */
printcharln ( 'B' + 1 ); /* 'C' になる */
printcharln ( 'A' + 1 + 1 ); /* これも 'C' になる */
printcharln ( 'A' + 0 ); /* これはもちろん 'A' */
printcharln ( 'A' + 10 ); /* 'A', 'B', .., 'J', 'K' になるはず */
printcharln ( 'A' + 25 ); /* 'Z' !! */
printcharln ( 'Z' + 1 ); /* ??? */
return 0;
}
$ ./sample-012.exe $
Download : sample-013.c
/*
* 2020/06/19 sample-013.c
*/
/*
* extern 宣言
*/
extern void nprintcharln ( char *n, char ch );
extern void printcharln ( char ch );
extern void println ( char *string );
/*
* 文字の扱い(3)
*/
int main ( int argc, char *argv[] ) {
println ( "'A' から 10 個 :" );
nprintcharln ( "1234567890", 'A' );
println ( "'U' から 10 個 :" );
nprintcharln ( "1234567890", 'U' );
println ( "'k' から 10 個 :" );
nprintcharln ( "1234567890", 'k' );
println ( "'0' から 10 個 :" );
nprintcharln ( "1234567890", '0' );
println ( "'9' + 1 は.. :" );
printcharln ( '9' + 1 ); /* 残念ながら "10" ではない */
return 0;
}
$ ./sample-013.exe $
Download : sample-014.c
/*
* 2020/06/19 sample-014.c
*/
/*
* extern 宣言
*/
extern void println ( char *string );
extern void printonedigit ( int n );
extern void printonedigitln ( int n );
/*
* 整数
*/
int main ( int argc, char *argv[] ) {
println ( "整数値 0 の出力" );
printonedigitln ( 0 ); /* 「'0'」 でも 「"0"」 でもなく 「0」 */
println ( "整数値 9 の出力" );
printonedigitln ( 9 ); /* 一桁は OK */
println ( "整数値 11 の出力" );
printonedigitln ( 11 ); /* 上手く行かない */
println ( "整数値 1 + 1 の出力" );
printonedigitln ( 1 + 1 ); /* やっと計算がでてきた */
println ( "整数値 5 - 2 の出力" );
printonedigitln ( 5 - 2 ); /* 引算 */
println ( "整数値 3 * 2 の出力" );
printonedigitln ( 3 * 2 ); /* かけ算 */
println ( "整数値 8 / 3 の出力" );
printonedigitln ( 8 / 3 ); /* 小数点以下は余りは切り捨て */
println ( "整数値 8 % 3 の出力" );
printonedigitln ( 8 % 3 ); /* 余りは「%」をで計算 */
println ( "整数値 8 - ( 8 / 3 ) * 3 の出力" );
printonedigitln ( 8 - ( 8 / 3 ) * 3 ); /* 余りを求めるもう一つの方法 */
return 0;
}
$ ./sample-014.exe $
Download : sample-015.c
/*
* 2020/06/19 sample-015.c
*/
/*
* extern 宣言
*/
extern void println ( char *string );
extern void printpositiveint ( int n );
extern void printpositiveintln ( int n );
/*
* 整数
*/
int main ( int argc, char *argv[] ) {
println ( "整数値 0 の出力" );
printpositiveintln ( 0 );
println ( "整数値 11 の出力" );
printpositiveintln ( 11 );
println ( "整数値 12345 の出力" );
printpositiveintln ( 12345 );
println ( "整数値 12 * 34 の出力" );
printpositiveintln ( 12 * 34 );
return 0;
}
$ ./sample-015.exe $
Download : sample-016.c
/*
* 2020/06/19 sample-016.c
*/
#include <stdio.h>
/*
* check_star_char
*/
void check_star_char ( char ch ) {
if ( ch == '*' ) { /* ch の中身が '*' かどうかをチェック */
printf ( "これは「*」です\n" );
} else {
printf ( "これは「*」ではありません\n" );
}
}
/*
* main
*/
int main ( int argc, char *argv[] ) {
check_star_char ( getchar() ); /* getchar() で文字を読込み、それを出力 */
return 0;
}
A
$ ./sample-016.exe < sample-016.in A これは「*」ではありません $
#include <stdio.h>
int main(void) {
putchar ( '#' ); /* 文字「#」を画面に出力する */
putchar ( 'A' + 1 ); /* 'A' + 1 => 65 + 1 => 66 => 'B' */
putchar ( 97 ); /* 97 => 'a' */
putchar ( '\n' ); /* 「(エスケープシーケンスで表現された)改行」を画面に出力する */
return 0;
}
#include <stdio.h>
int main(void) {
printf ( "A" ); /* 文字列「A」(「A」という一つの文字からなる文字列 ) */
/* 文字「A」('A')とは異なる */
/* 長さ 1 の文字列 */
/* "A" -> { 'A', '\0' } */
/* 長さ k の文字列は、
k 個の文字 + NUL 文字 ('\0')
の
k + 1 個のものからなる構造を持つ
=> 分解が可能
*/
/*
文字列の先頭の文字を取り出す
頭に「*」をつける
*/
putchar ( *"abc" ); /* "abc" -> { 'a', 'b', 'c', '\0' } */
/* *"abc" -> 'a' */
/*
文字列に +1 すると、文字列から、
先頭の文字を取り除いた、残り
を得ることができる
*/
putchar ( '\n' );
printf ( "abc" + 1 ); /* "abc" + 1 -> "bc" */
putchar ( '\n' );
putchar ( *("abc" + 1) ); /* *("abc" + 1) -> *"bc" -> 'b' */
putchar ( '\n' );
putchar ( "abc"[1] ); /* *(文字列 + n) -> 文字列[n] */
putchar ( '\n' );
return 0;
}
#include <stdio.h>
void func(void) {
printf ( "関数呼び出し\n" );
}
int main(void) {
printf ( "main 1\n" );
func();
printf ( "main 2\n" );
return 0;
}
#include <stdio.h>
/*
p-003.c の main 関数の部分を取り出した
*/
extern void func(void); /* プロトタイプ宣言(extern 宣言) */
int main(void) {
printf ( "main 1\n" );
func();
printf ( "main 2\n" );
return 0;
}
#include <stdio.h>
/*
p-003.c の func 関数の部分を取り出した
*/
void func(void) {
printf ( "関数呼び出し\n" );
}
#include <stdio.h>
extern void func(void); /* 他のファイルで定義された関数 */
int main(void) {
printf ( "main 1\n" );
func();
func();
func();
printf ( "main 2\n" );
return 0;
}
#include <stdio.h>
int main(void) {
printf ( "Hello, World\n" );
return 0;
}
#include <stdio.h>
int main(void) {
/*
printf ( "Hello, World\n" );
*/
/* printf をなくすと、画面に文字列が出なくなる */
/* => printf が「画面に文字列を出す」機能を持つ */
return 0;
}
/*
#include <stdio.h>
int main(void) {
printf ( "Hello, World\n" );
return 0;
}
*/
/* 全部削除してみる */
/*
リンク時で、エラー(main がないという..)になる
=> 少なくても、C 言語でプログラムを作成する場合は、
どこかで、main を作る必要がある
*/
/*
#include <stdio.h>
*/
extern int printf( const char *string, ... ); /* printf 関数の extern 宣言 */
int main(void) {
printf ( "Hello, World\n" );
return 0;
}
/*
#include <stdio.h>
*/
/* printf を使わないならば、#include も不要 */
/* <<参考>>
strcmp を使う場合は、「#include <string.h>」が必要だった.
=> string.h の中に strcmp の extern 宣言(等)がある
*/
int main(void) {
/*
printf ( "Hello, World\n" );
*/
return 0;
}
#include <stdio.h>
/* int */ void main(void) {
printf ( "Hello, World\n" );
/*
return 0;
*/
/*
return 0; -> int と関係がある
*/
}
#include <stdio.h>
int main(void) {
printf ( "Hello, World\n" );
return 99; /* 0 => 99 */
}
#include <stdio.h>
int main(void) {
printf ( "Hello, World\n" );
return 0;
}
#include <stdio.h>
/*
命令「printf ( "Hello, World\n" );」に
「printHello」という名前を付ける
関数(printHello)の定義
*/
void printHello (void) {
printf ( "こんにちわ、みなさん\n" );
}
/* 関数の定義は、それだけでは意味がない */
int main(void) {
printHello();
printf ( "Hello, World\n" );
printf ( "Hello, World\n" );
printf ( "Hello, World\n" );
printHello(); /* 関数(printHello)の呼び出し */
/* 名前を付けた命令が、ここで実行される */
printHello(); /* 一度定義した関数は、何度でも呼び出せる */
return 0;
}
#include <stdio.h>
int main(void) {
printf ( "こんにちわ、みなさん\n" );
printf ( "Hello, World\n" );
printf ( "Hello, World\n" );
printf ( "Hello, World\n" );
printf ( "こんにちわ、みなさん\n" );
printf ( "こんにちわ、みなさん\n" );
return 0;
}
#include <stdio.h>
int main(void) {
printf ( "こんにちわ、鈴木さん\n" );
printf ( "今日は、雨が降って、いやですね\n" );
printf ( "そう言えば、鈴木さんのところは、お子さんがいるそうですね\n" );
printf ( "風邪をひかないとよいですね\n" );
printf ( "それでは、さようなら\n" );
printf ( "こんにちわ、田中さん\n" );
printf ( "今日は、雨が降って、いやですね\n" );
printf ( "そう言えば、田中さんのところは、お子さんがいるそうですね\n" );
printf ( "風邪をひかないとよいですね\n" );
printf ( "それでは、さようなら\n" );
printf ( "こんにちわ、佐藤さん\n" );
printf ( "今日は、雨が降って、いやですね\n" );
printf ( "そう言えば、佐藤さんのところは、お子さんがいるそうですね\n" );
printf ( "風邪をひかないとよいですね\n" );
printf ( "それでは、さようなら\n" );
return 0;
}
#include <stdio.h>
void aisatu( char *name ) {
printf ( "こんにちわ、" );
printf ( name );
printf ( "さん\n" );
printf ( "今日は、雨が降って、いやですね\n" );
printf ( "そういえば、" );
printf ( name );
printf ( "さんのところは、お子さんがいるそうですね\n" );
printf ( "風邪をひかないとよいですね\n" );
printf ( "それでは、さようなら\n" );
}
int main(void) {
aisatu ( "鈴木" );
aisatu ( "田中" );
aisatu ( "佐藤" );
return 0;
}
#include <stdio.h>
extern void aisatu( char *name );
int main(void) {
aisatu ( "鈴木" );
aisatu ( "田中" );
aisatu ( "佐藤" );
return 0;
}
void aisatu( char *name ) {
printf ( "こんにちわ、" );
printf ( name );
printf ( "さん\n" );
printf ( "今日は、雨が降って、いやですね\n" );
printf ( "そういえば、" );
printf ( name );
printf ( "さんのところは、お子さんがいるそうですね\n" );
printf ( "風邪をひかないとよいですね\n" );
printf ( "それでは、さようなら\n" );
}
#include <stdio.h>
#include <string.h>
void printUchar ( char ch ) {
/*
変数の宣言に char * ではなく char を使う
*/
putchar ( ch - 'a' + 'A' );
/* ch に英小文字が入っている時に、その英大文字を出力する */
/* !! ch には「文字」 */
}
void printUpper ( char *str ) {
if ( !strcmp ( str, "" ) ) {
/* Do Nothing */
} else {
/*
先頭の文字を小文字から大文字変換して出力する
*/
printUchar ( *str ); /* 実引数に「文字」を指定する */
printUpper ( str + 1 ); /* 再帰呼び出し */
}
}
int main(void) {
printUpper( "abc" ); /* 大文字で出力をしたい */
printf ( "\n" );
return 0;
}
「関数」という考え方
「関数の定義」とは(What) ?
「プログラムの一部」に「名前」を付ける事
「名前」を「関数名」と呼ぶ
「プログラムの断片」を「関数の本体」と呼ぶ
関数をどうやって利用する(How to) ?
「関数名」を指定するだけで「関数本体」が実行される(関数呼出し)
!! 関数呼び出しをする部分で実行する命令を、
!! 関数定義と関数呼び出しに置き換えている
!! <= 置き換える前の状況を考えると、
!! 関数の定義はなくても、目的(プログラムの実行結果)が実現できる
!! => 関数がなくてもよいのでは ??
関数を定義する理由は (Why) ?
「プログラムの断片」に「名前」が付けられるので、分かり易い
もちろん、「断片の内容に対応した分り易い名前をつければ..」だが..
# 名前つける機会(権利)が与えられる
# => 機会をつかみ、権利を行使して、良い名前を付けて欲しい
「関数名前」を指定するだけで「関数本体」が実行される
何度も「同じ事」をする場合に便利(プログラムが短くなる)
記述が増えると「同じ」である事を保証するコストが大きくなる
関数を定義する
=> 関数名が同じなら、それに対応する本体も同一
=> 本体同士の比較より、関数名の比較の方が(普通..)簡単なので..
関数定義(とその関数の利用により..) 同一性のチェックが楽になる
「引数」を利用する事により「色々な断片」を「一つの関数本体」にまとめられる
複数のプログラムの断片があり、一部だけが異なる場合、
「変数」を導入する事により、同一化できる
=> 引数付き関数を導入する
<= コピペじゃいけないのか ??
=> コピペで問題が解決できるのでは ??
=> コピペをすると、
もし、そのコピー元に誤りがあったら、
コピー先にも誤りを作る事になる
「コピペ」がバグの増殖を促す
関数を作る事によって、
バグの『増殖』を防ぐ事ができる
一箇所の「関数本体」を直すだけで、多数の場所の命令を直す効果がある
「関数」の表現方法
具体例:
関数定義
void printHello(void) {
printf ( "Hello, World\n" );
}
int main(void) {
printHello(); /* 関数呼び出し */
}
関数定義(の文法)
「関数定義」は、「関数頭部」と「関数本体」に分けられる
例:
関数頭部 「void printHello(void)」
関数本体 「{printf ( "Hello, World\n" );}」
「関数頭部」は、「関数の値の型宣言」「関数名」「仮引数変数宣言」に分けられる
例:
関数の値の型宣言 「void」
関数名 「printHello」
仮引数変数宣言 「(void)」
「関数宣言」は、void(これまで)/int(main だけ)
「関数名」は、自由に决めて良い(他と重複すると駄目だが..)
「仮引数宣言」は、「(」+「仮引数宣言並び」+「)」
「仮引数宣言並び」は、
「void」 引数がない場合
か、
「char *変数名」のカンマ(,)区切
=> 引数の個数だけ並べる ( , は引数の区切り記号 )
「関数本体」は、「{」+「命令列」+「}」
関数呼出し(の文法)
「関数呼出し」は、「関数名」+ 「実引数並び」
例
関数名 printHello
実引数並び ()
「実引数並び」は、
'()' 引数がない場合
か、
'(' + 「式」のカンマ並び + ')'
=> それぞれの式を計算した値が、対応する
仮引数変数の値になる
!! 仮引数変数の個数と実引数変数の個数は一致している必要がある
!! => 一致していないと「(コンパイル)エラー」になる
文字を引数に持つ関数と型宣言
これまでの関数
引数がないか、文字列を引数としていた
「char *」をお呪いとし、関数を呼び出す時に、文字列を指定
=> printf 関数 (引数として文字列を取る)
これまでの(自作した..)関数は、引数(文字列)を、
基本、そのまま、他の関数の引数に与えていた
例: printf, strcmp
例外 : putchar 関数 : 引数が「文字」(「文字列」ではなく)
「文字」を引数に持つ関数の場合
仮引数変数宣言のところを「char」とする必要がある
型宣言(データの種類)
「char *」/「char」は実は、「引数の型」を表現していた
「char *」は「文字列」
「char」は「文字」
!! => 一般論として、変数に入るデータの種類(型)を、仮引数変数宣言で指定する
!! 呼び出しの時も、その型の実引数を与える
変数に、その型と異る型の値を入れようとすると「エラー」になる
C のプログラムで扱うデータの型は(基本)文字列
=> 一種類の型しか扱っていない
<= 複数の種類の型を利用する
「型」の違いを意識する必要がある
「型」= <「値の取りうる範囲を表す集合」、「その値を利用する演算の集合」>
例: 小学校で学ぶ、「整数」=> < { 0, +1, -1, +2, -2, .. }, { +, -, *, / } >
「3 次元ベクトル空間」=> < { (x,y,z) | x, y, z 実数 }, { 定数倍, 和 } >
「値の集合」と「演算」
データを処理する時に、
そのデータの型がわからないと
そのデータの処理(演算の適用)ができない
=> 常に「データの『型』」を意識する必要がある
「文字」に 「1 を加える」と、「次の文字」
「文字列」に 「1 を加える」と、「短くなった文字列」
同じ「1 を加える」という「演算」でも、「意味」が異る
「演算」と「型」は「一組」で考える必要がある
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20210604-01.c
/*
* 20210604-01-QQQQ.c
* 「Hello, World」+[改行] を画面に出力するプログラム
*/
#include <stdio.h>
/*
* main
*/
int main ( void ) {
/*
** この部分を完成させなさい
*/
return 0;
}
$ ./20210604-01-QQQQ.exe Hello, World $
Download : 20210604-02.c
/*
* CDATE FILENAME
*
* キーボードから一文字入力し、その文字によって異る国の挨拶をする
*/
#include <stdio.h>
/*
* hello ( char contry )
* char contry : 国を表す一文字
* j : 日本
* e : 英語
* c : 中国
* f : フランス語
* g : ドイツ語
*/
void hello ( char cmd ) {
if ( cmd == 'j' ) { /* 'j' の時は、日本語にする */
printf ( "こんにちは\n" );
} else if ( cmd == 'e' ) { /* 'e' の時は、英語にする */
/*
** この部分を完成させなさい
*/
} else if ( cmd == 'c' ) { /* 'c' の時は、中国語にする */
printf ( "ニイハオ\n" );
} else if ( cmd == 'f' ) { /* 'f' の時は、フランス語にする */
printf ( "Bonjour\n" );
/*
** この部分を完成させなさい
*/
printf ( "Guten tag\n" );
} else { /* どれでもなければ.. */
printf ( "???\n" );
}
}
/*
* main
*/
int main( void )
{
printf ( "国を表す文字を入力してください\n" );
printf ( "\tj\t日本\n" );
printf ( "\te\t英語\n" );
printf ( "\tc\t中国\n" );
printf ( "\tf\tフランス\n" );
printf ( "\tg\tドイツ\n" );
printf ( "> " );
hello ( getchar() ); /* getchar() で文字を入力し、それに対応する結果を出す */
return 0;
}
f
$ ./20200619-02-QQQQ.exe 国を表す文字を入力してください j 日本 e 英語 c 中国 f フランス g ドイツ > f Bonjour $
Download : 20210604-03.c
/*
* CDATE FILENAME
*
* キーボードから一行(改行まで..)文字列を読込み、それを逆順に出す
*/
#include <stdio.h>
/*
* reverse ( char contry )
* char cmd : どのメッセージにするかを表す文字
*
*/
void reverse_line ( char ch ) {
if ( ch == '\n' ) { /* 改行ならば.. */
/* なにもしなくてよい */
} else { /* そうでなければ.. */
/*
** この部分を完成させなさい
*/
}
}
/*
* main
*/
int main( void )
{
reverse_line ( getchar() ); /* 最初の文字を読み込んで .. */
putchar ( '\n' ); /* 改行を出力 */
return 0;
}
abc123
$ ./20200619-03-QQQQ.exe abc123 321cba $