C言語プログラミングに関する以下の問に答えよ。ただし、\は¥と同じである。
[1] 次のプログラムの出力結果を示せ。
#include <stdio.h>
int main(void){
int a = 0x1234;
printf("%x %d %x %x %x\n", a, a, a+10, a&0xc3c3, a<<2);
return(0);
}[2] 大きさnの整数型の1次元配列aについて要素を逆順に並べ替える関数fnc1を作成した。関数fnc1は,引数としてaとnをとるものとする。例えば,配列aをa[0]=1, a[1]=2, a[2]=3とし,n=3としてこの関数を呼ぶと,a[0]=3, a[1]=2, a[2]=1と並べ替えられる。空欄1から4を適切に埋めよ。
_____1_____ fnc1(int a[], int n){
int dum,i;
for(i = 0; _____2_____; _____3_____ ){
dum = a[i];
a[i] = a[ _____4_____ ];
a[ _____4_____ ] = dum;
}
}[3] 2つのベクトルの内積を計算する関数fnc2を再帰的プログラミングにより作成した。2つのベクトルは,それぞれ浮動小数点数型の1次元配列aとbに,それらのサイズは整数型の変数nに代入されて関数fnc2へ渡される。空欄1から4を適切に埋めよ。
_____1_____ fnc2(float a[], float b[], int n){
if(_____2_____){
return (a[_____3_____] * b[_____3_____]
+ fnc2(a, b,_____3_____));
}else{
return (_____4_____);
}
}[4] 文字列を操作するプログラムとその実行結果を以下に示す。ただし,scpyは文字列をコピーする関数,slenは文字列の長さを返す関数である。空欄1から6を適切に埋めよ。
#include <stdio.h>
char *scpy(char *s, char *t)
{
int i = 0;
while((_____1_____) != '\0')
_____2_____;
return(s);
}
int slen(char *s) {
int n = 0;
while(_____3_____) n++;
return(n);
}
int main(void) {
char a[5] = {
'A', 'B', '\0', '1', '2'};
char *b = "ABC";
char c[10] = "";
int i, n;
scpy(c, b);
n = slen(c);
b++;
for(i = 0; b[i] != '\0'; i++)
c[n++] = b[i];
printf("n = %d\n", n);
printf("a = %s\n", a);
printf("c = %s\n", c);
return(0);
}実行結果
n = [ 4 ]
a = [ 5 ]
c = [ 6 ]
解答:
[1]
変数 の初期値は16進数で である。
%x は16進数形式、%d は10進数形式で値を出力する。
の10進数表現は である。
は10進数の10を加算するため、 となる。
について、各ビットの論理積を計算すると となる。
は左に2ビットシフトさせる演算であり、値は4倍となるため となる。
[2]
関数 fnc1 は値を返さないため、戻り値の型は void となる。
配列の要素を逆順に並べ替えるため、配列の先頭から中央に向かって対称な位置の要素と交換を行う。したがって、ループの継続条件はインデックス が配列サイズの半分未満であることとし、反復ごとに を ずつ増加させる。
インデックス に対応する配列の後方からのインデックスは である。
[3]
関数 fnc2 は浮動小数点数の要素を用いて内積を計算するため、戻り値の型は float となる。
再帰的プログラミングにおいて、残りの要素数が存在する間計算を続けるため、分岐条件は とする。
要素のインデックスは配列の末尾から処理するため とし、再帰呼び出しの際もサイズを 減らすための引数として を渡す。
再帰のベースケースに達したときの戻り値は となる。
[4]
関数 scpy では、ポインタ の指す文字をポインタ の指す位置に代入し、その代入された文字が終端文字 '\0' でないかを判定する。文字をコピーするたびにインデックス をインクリメントして次の文字に進む。
関数 slen では、参照している文字が終端文字でない間ループを回して文字数を数える。
メイン関数において、scpy(c, b) が実行された後、配列 には "ABC" が格納され、その長さ は となる。
b++ によってポインタ は1文字進み "BC" を指すようになる。
続くループ処理によって配列 の末尾にポインタ の内容が追加され、 の文字列は "ABCBC" となる。この過程で2文字が追加されるため、最終的な の値は となる。
配列 はインデックス に終端文字 '\0' を含んでいるため、printf で文字列として出力されるのはその前までの "AB" となる。
这几道题目主要考察了C语言中的基础语法规则以及底层内存操作逻辑。第一题要求熟练掌握不同进制的格式化输出以及按位与和左移等位运算规则,需要准确将十六进制数转换为二进制进行计算。第二题通过循环实现数组元素的逆序排列,关键在于认识到循环次数只需要达到数组长度的一半,并通过总长度减去当前索引再减一的数学关系找到对称位置的元素进行原地交换。第三题通过递归的方式求解两个向量的内积,需要正确设置递归的边界条件,即当剩余元素个数大于零时继续递归运算,并在每次递归时将数组索引减一以从后向前访问元素,直到数组处理完毕后返回浮点数零。第四题涉及字符串的底层拷贝与长度计算机制,需要注意C语言中的字符串本质上是以空字符结尾的字符数组,在主程序执行过程中指针的移动会直接改变字符串的起始读取位置,循环操作巧妙地将向后移动一位后读取到的子串追加到了另一个目标字符串的末尾,由于目标数组初始化时内存已经清零,所以即使没有在追加后显式地手动添加结尾空字符,利用预设的零值内存依然能够确保字符串正确截断并输出。