プログラミング入門 情報科学演習
2014.01.20
Back to index page
- 本日の作業内容
- 小テストの結果について
以下の提出が不備でした.
コンパイルエラー b1331 b1359 s131108 b1204 b1281
セグメンテーション違反 b1309 b1323 b1206 b1223
解答用紙不使用 b1229
以下は問題のあるプログラムの例です.参考にしてください.
char header[3][5] = {"2014", "1", "16"};
printf("\nMy student number: s134099\n\n");
printf("%d",str);
|
何故,インデントする?何故文字列を分ける?何故 %d ?何故2次元の配列?
for(i=0; i<10; i++)
printf("%c", str[i]);
|
インデントもおかしいですが,このように配列の要素を超えて表示させる for 文の使用が大変多くありました.前回の授業でも言いましたが,要素の個数にはよく注意していて下さい.上のように余分に表示させると,下のようになってしまいます.
ヌル文字まで出てきてしまいました.
static char str[11] = {"2014.1.16",};
printf("%s\n",str[11]);
|
11番目には「文字」はあっても「文字列」は無いので %s で受けられるものがありません.ですので,結果は以下のように
無いと怒られます.
for(i=0;i<9;i++)
printf("%d",str[i]);
|
文字ですので,%d では無いですね.強引に表示させると,
のようになります.
- 宿題の結果について
採点できない答案はありませんでした.安心しました.ただ,問題のある解答はたくさん出ていましたので,以下に簡単に説明します.
printf("str1: \"%s\", str2: \"%s\"",str1,str2);
printf("\n\n");
printf("str1: \"%s\", str2: \"%s\"",str2,str1);
|
絶対にやっちゃだめ!な解答ですね.0点です.配列の中身を入れ換えようとしていません.題意はあくまで「中身の入れ換え」です.表示はおまけです.
int i;
char str1[4] = "abc";
char str2[4] = "def";
printf("str1:%c",34);
for(i=0; i<=3; i++)
printf("%c", str1[i]);
printf("%c, str2:%c", 34, 34);
for(i=0; i<=3; i++)
printf("%c", str2[i]);
printf("%c\n", 34);
printf("str1:%c",34);
for(i=0; i<=3; i++)
printf("%c", str2[i]);
printf("%c, str2:%c", 34, 34);
for(i=0; i<=3; i++)
printf("%c", str1[i]);
printf("%c", 34);
|
何をしようしとしているのか,もうわかりません.やって欲しいことは配列の中身の入れ換えです.しかも,結果は以下のように崩れています.
str1:"abc^@", str2:"def^@"
str1:"def^@", str2:"abc^@"
|
出力時に less で確認するようにと何度も説明しています.
for ( i= 0 ; i <= 3 ; i ++ ){
printf("%c",str1[i]);
str1[i] = str2[i];
}
printf("\", str2: \"");
for ( i= 0 ; i <= 3 ; i ++ ){
printf("%c",str2[i]);
str2[i] = str1[i];
}
printf("\"\nstr1: \"");
for ( i= 0 ; i <= 3 ; i ++ ){
printf("%c",str1[i]);
}
printf("\", str2: \"");
for ( i= 0 ; i <= 3 ; i ++ ){
printf("%c",str2[i]);
}
|
これもいったい何をしようとしているのか?
str1: "abc^@", str2: "def^@"
str1: "def^@", str2: "def^@"
|
で,やっぱり出力は崩れています.訳の分からないことになったら少しは変だと疑ってください.
printf("str1: ""%c%s%c""," "str2: ""%c%s%c\n",a[0],str1,a[0],a[0],str2,a[0]);
strcpy(a, str1);
strcpy(str1, str2);
strcpy(str2, a);
a[0]=34;
printf("str1: ""%c%s%c""," "str2: ""%c%s%c\n",a[0],str1,a[0],a[0],str2,a[0]);
|
これも何がしたいのか分かりません.
printf("str1:\"%s\",",str1);
printf("str2:\"%s\"\n",str2);
strcpy(str1, "abc");
strcpy(str2, "def");
strcpy(str1, str2);
printf("str1:\"%s\",",str1);
strcpy(str2, "def");
strcpy(str1, "abc");
strcpy(str2, str1);
printf("str2:\"%s\"",str2);
|
これもどうしたいのかがわかりません.
strcpy(a, str1);
printf("str1: \"%s\" ",str1);
printf("str2: \"%s\"\n",str2);
strcpy(str1, str2);
printf("str1: \"%s\" ",str1);
printf("str2: \"%s\"\n\n",a);
|
結局,配列の値を入れ換えて表示するようにはなっていません.
char *p = "abc";
printf("\"str1: %s\",",str1);
strcpy(str1, str2);{
printf("str2: \"%s\"\n", str1);
}
printf("\"str1: %s\",",str2);
strcpy(str1, p);{
printf("str2: \"%s\"\n", str1);
}
strcpy(str1, "");
printf("%s\n", str1);
|
これもわかりません.
for(i=0; i<=2; i++){
num=str1[i];
str1[i]=str2[i];
str2[i]=num;
}
|
中身の入れ換えはこれで出来るのですが,今回の宿題は strcpy の練習だったので,減点です.
以下はインデントの問題です.
printf("str1:%s, str2:%s\n", str1, str2);
strcpy(tmp,str1);
printf("str1: \"%s\", str2: \"%s\"\n",str1,str2);
strcpy(str1,str2);
strcpy(str2,tmp);
printf("str1: \"%s\", str2: \"%s\"",str1,str2);
|
何故インデント?
printf("\n\n---------------------\n\n");
return(0);
}
|
まだいました.いい加減,昔のコピペをやめて自分で入力してください.
main()
{
char str1[4] = "abc";
char str2[4] = "def";
|
以前から指摘していますが,インデントが多すぎです.どれだけ下げれば気が済むのでしょうか?
- less について
この後でも説明しますが,配列の要素の数を超えて文字列表示処理を行うとヌル文字を始めと表示できない文字が含まれるため,変な文字が画面に表示されます.通常のターミナルでは見えないのですが,ページャである less に処理を渡すと見えるようになります.プログラムの間違いを検出するためにも less で確認する習慣をつけてください.一度 less の処理に入ると終了するためには Q のキーを押さないといけないことに注意してください.
ただし,less による表示を行うと,エラーメッセージが表示されない場合があります.セグメンテーション違反などは表示されません.ですので,less なしでの表示も確認しましょう.
- 前回の復習
文字列配列の要素数と添字
整数型の配列のときと異なる要素の考え方について理解の足らない人が多く見られました.もう一度よく確認してください.
- 文字列の考え方
文字列(複数の文字の組合せ)はそれ自体が配列です.ですので,整数型で定義していた変数ならば,
のように定義していたのですが,数値としての100は値が一つなのに対して,文字列としての100であれば3つの文字の列として扱われるので,それだけで配列となり,以下のように定義しないといけなくなります.
- NULL文字
文字列は複数の値を持つということで,どこが文字列の終わりなのかを示す記号であるNULL文字が必ず必要となります.そのため,要素の個数は文字数+1となります.
char a[4] = {'1', '0', '0', '\0'};
|
のような定義方法であれば,要素が4つというのがよくわかりますが,これは面倒なので,以下のような定義が便利なのですが,その際にはヌル文字まで含めた要素の個数に注意してください.
- 添字
上のような要素として1,0,0の3つを持つ文字列配列の要素を for 文を使用して順に表示する場合,以下のような添字なので対応に注意が必要です.
添字 |
0 |
1 |
2 |
3 |
値 |
'1' |
'0' |
'0' |
'\0' |
上記のような添字との対応なので,for 文で順に表示する際には,変数 i は0から2までと要素のサイズよりも2つ小さい i = 2 までになります.
配列のサイズよりも1つだけ小さい i まで反復処理を行なう例が前回も多く見られました.その間違いに気づくためにも,処理を less に渡すことを忘れないでください.
$ ./a.out | less
- %s の意味
教科書のp.21で %s はすでに紹介されていたのですが,文字列を扱うようになると頻繁に使用するようになります.前回のテキストでも説明しておきましたが,文字1つずつは %c ですが,文字列単位で出力するときには %s が便利です.
char a[3] = "ab";
char b[3][3] = {"ab", "bc", "ca"};
printf("%s\n", a);
printf("%s\n", b[0]);
for(i=0; i<=2; i++)
printf("%s\n", b[i]);
|
のように使用できます.文字列単位で扱えるということは,文字順を示す添字が不要なので,配列の添字が省略できることに注意してください.
- 実習
実習の演習問題は当日ご案内します.
- 宿題
授業の終わりに宿題の案内をします.ただし,問題を見ることができるのは21日以降です.レポート提出システムから閲覧してください.
目次ページに戻る