substract
を用いて
ベクトルの差と
ベクトルの差を計算します.
コメント部分に何かを足してプログラムを完成して下さい.
ただし既にあるプログラム部分を変更してはいけません.
vector_subtract0.c |
---|
#include<stdio.h> /***関数subtractの宣言***/ int main(void){ double a[7], b[7], c[5], d[5]; int i; double a_sub_b[7], c_sub_d[5]; a[0]=0.1; a[1]=0.2; a[2]=0.3; a[3]=0.4; a[4]=0.5; a[5]=0.6; a[6]=0.7; b[0]=1.1; b[1]=2.2; b[2]=3.3; b[3]=4.4; b[4]=5.5; b[5]=6.6; b[6]=7.7; c[0]=0.5; c[1]=0.6; c[2]=0.7; c[3]=0.8; c[4]=0.9; d[0]=11.0; d[1]=22.1; d[2]=33.2; d[3]=44.3; d[4]=55.4; printf("a:\n"); for(i=0;i<7;i++){ printf("a[%d]=%f\n", i, a[i]); } printf("b:\n"); for(i=0;i<7;i++){ printf("b[%d]=%f\n", i, b[i]); } /***関数subtractの呼出***/ printf("a_sub_b:\n"); for(i=0;i<7;i++){ printf("a_sub_b[%d]=%f\n", i, a_sub_b[i]); } printf("c:\n"); for(i=0;i<5;i++){ printf("c[%d]=%f\n", i, c[i]); } printf("d:\n"); for(i=0;i<5;i++){ printf("d[%d]=%f\n", i, d[i]); } /***関数subtractの呼出***/ printf("c_sub_d:\n"); for(i=0;i<5;i++){ printf("c_sub_d[%d]=%f\n", i, c_sub_d[i]); } return 0; } /***関数subtractの定義***/ |
この問題は、配列を処理する関数を自作するものです。 int型やdouble型などの単一の値を処理する関数を自作する技術に加えて、 配列を関数で処理する際に配列の性質を理解しておく必要があります。
関数を自作する場合には、その関数を宣言・定義した上で、 呼び出すことになります。
宣言するためには、必要となる(1つ以上の)引数の型と返却値の型を決めなければなりません。
引数は次の通りです
void subtract(double *lhs, double *rhs, int size, double *result); |
実引数aは配列aの名前でプログラム内では配列の先頭要素のアドレスを表すので、 aだけではその配列の要素数が分かりません。 そこで、配列名とは別に配列の要素数(仮引数sizeに実引数7や5)を指定する必要があるのです。
結果はやを表す配列となるのですが、C言語では配列を返却することができません。 そこで、結果を表す配列a_sub_bやc_sub_dも関数subtractの実引数にして(仮引数をdouble *resultにして)、 関数subtract内で計算結果をa_sub_bやc_sub_dに対応する仮引数resultの各要素に代入します。 結果の処理をこのように引数を用いることにしたので、 本来結果を処理するために使われる返却値は不要となるので返却値の型をvoidにします。
定義するためには宣言と同じように始めて実際の処理を書きます。 実引数a,bやc,dに対応する仮引数lhs,rhsの各要素の差を 実引数7や5に対応する仮引数size個分計算して、 実引数a_sub_bやc_sub_dに対応する仮引数resultの各要素に代入します。
void subtract(double *lhs, double *rhs, int size, double *result){ int i; for(i=0;i<size;i++){ result[i]=lhs[i]-rhs[i]; } return; } |
vector_subtract.c |
---|
#include<stdio.h> void subtract(double *lhs, double *rhs, int size, double *result); int main(void){ double a[7], b[7], c[5], d[5]; int i; double a_sub_b[7], c_sub_d[5]; a[0]=0.1; a[1]=0.2; a[2]=0.3; a[3]=0.4; a[4]=0.5; a[5]=0.6; a[6]=0.7; b[0]=1.1; b[1]=2.2; b[2]=3.3; b[3]=4.4; b[4]=5.5; b[5]=6.6; b[6]=7.7; c[0]=0.5; c[1]=0.6; c[2]=0.7; c[3]=0.8; c[4]=0.9; d[0]=11.0; d[1]=22.1; d[2]=33.2; d[3]=44.3; d[4]=55.4; printf("a:\n"); for(i=0;i<7;i++){ printf("a[%d]=%f\n", i, a[i]); } printf("b:\n"); for(i=0;i<7;i++){ printf("b[%d]=%f\n", i, b[i]); } subtract(a, b, 7, a_sub_b); printf("a_sub_b:\n"); for(i=0;i<7;i++){ printf("a_sub_b[%d]=%f\n", i, a_sub_b[i]); } printf("c:\n"); for(i=0;i<5;i++){ printf("c[%d]=%f\n", i, c[i]); } printf("d:\n"); for(i=0;i<5;i++){ printf("d[%d]=%f\n", i, d[i]); } subtract(c, d, 5, c_sub_d); printf("c_sub_d:\n"); for(i=0;i<5;i++){ printf("c_sub_d[%d]=%f\n", i, c_sub_d[i]); } return 0; } void subtract(double *lhs, double *rhs, int size, double *result){ int i; for(i=0;i<size;i++){ result[i]=lhs[i]-rhs[i]; } return; } |
a
の先頭文字からヌル文字の直前までの文字数を
画面表示します.
コメント部分に何かを足してプログラムを完成して下さい.
ただし既にあるプログラム部分を変更してはいけません.
strlength0.c |
---|
#include<stdio.h> int main(void){ char *a="bcdef"; char *p=a; while(1){ if(/***ここに何か書く***/){ break; } /***ここに何か書く***/ } printf("%d\n", p-a); return 0; } |
この問題は文字列操作の内で文字列を書き換えない類のものです。 文字列には可視文字以外に最後にヌル文字(もしくは、終端文字)があるという知識と 基本的には配列と同じように扱うことの知識が必要とされます。
基本方針は、char型へのポインタを用意して、処理対象文字列の先頭要素を指すようにし、 指した要素の文字がヌル文字でない限りポインタをインクリメントして次の文字を指すようにします。 ヌル文字を指したときのポインタと処理対象文字列の先頭要素のアドレスの差が目的の文字数になります。
雛型プログラムではp-aを画面表示しているので、aでなくpをインクリメントします。
strlength.c |
---|
#include<stdio.h> int main(void){ char *a="bcdef"; char *p=a; while(1){ if(*p=='\0'){ break; } p++; } printf("%d\n", p-a); return 0; } |
a
を保持するための必要十分な記憶領域を確保して変数p
に対応づけ,
確保された記憶領域に文字列a
をコピーします.
コメント部分に何かを足してプログラムを完成して下さい.
ただし既にあるプログラム部分を変更してはいけません.
dstrcpy0.c |
---|
#include<stdio.h> #include<string.h> #include<stdlib.h> int main(void){ char *a="bcdef"; char *p; int n=strlen(a), i; /***ここに何か書く***/ if(/***ここに何か書く){ printf("out of memory\n"); /***ここに何か書く***/ } for(i=0;i<n;i++){ /***ここに何か書く***/ } /***ここに何か書く***/ printf("%s\n", p); free(p); return 0; } |
この問題は、malloc関数を用いて必要な大きさ分の領域を確保することと、 文字列操作の内で文字列を書き換える類のものです。
malloc関数の使い方については、丸覚えするのが良いでしょう。 nには文字列aのヌル文字を含まない文字数が格納されていることを踏まえて、 malloc関数を用いてchar型(n+1)個分の領域を確保します。 nより1つ多いのはヌル文字のためです。 エラー処理も行って下さい。
文字列のコピーについては基本的には配列と同じです。 文字数が分からない場合にはコピー元のヌル文字を確認しながらコピーすることになりますが、 今は文字数が分かっているので文字数n分コピーして、 最後にヌル文字を代入します。
dstrcpy.c |
---|
#include<stdio.h> #include<string.h> #include<stdlib.h> int main(void){ char *a="bcdef"; char *p; int n=strlen(a), i; p=malloc((n+1)*sizeof(char)); if(p==NULL){ printf("out of memory\n"); exit(1); } for(i=0;i<n;i++){ p[i]=a[i]; } p[i]='\0'; printf("%s\n", p); free(p); return 0; } |
ヌル文字の代入を忘れてもたまたまうまくコピー先pが表示される場合がありますが、 たまたまです。 続けて、より文字数の少ない文字列を上書きすると、ヌル文字の代入をしておかないと 前の文字列の残骸も表示されてしまいます。
dstrcpy_lostnull.c(誤り) |
---|
#include<stdio.h> #include<string.h> #include<stdlib.h> int main(void){ char *a="bcdef"; char *p; char *b="ghi"; int n=strlen(a), i; p=malloc((n+1)*sizeof(char)); if(p==NULL){ printf("out of memory\n"); exit(1); } for(i=0;i<n;i++){ p[i]=a[i]; } /***敢えてヌル文字代入を忘れてみる。***/ printf("%s\n", p); /***たまたまうまく表示されるかも知れない***/ /***続けて、より文字数の少ないbをコピーする***/ /***nに文字列bの文字数を代入***/ n=strlen(b); /***n文字分bをpにコピー***/ for(i=0;i<n;i++){ p[i]=b[i]; } /***コピー先pを表示してみる***/ printf("%s\n", p); free(p); return 0; } |