FC2ブログ

記事一覧

平成21年 春期 基本情報技術者試験 午後 問9、C言語

本ページは、平成21年 春期 基本情報技術者試験 午後 問9、C言語の解説です。
問題文、解答、解説の順で掲載しております。


***********************************************************************************************************
無料から学べる講座
http://ai-light.com/itkeiei/

ニコニコチャンネル
http://ch.nicovideo.jp/ai-light

YouTubeチャンネル
https://www.youtube.com/user/ailightcom

Access・Excel倶楽部
http://ai-light.com/accessclub/

株式会社アイライト公式HP
http://www.ai-light.com/
(Access・Excelでシステム開発会社を探されている法人様はこちら)

***********************************************************************************************************

次のCプログラムの説明及びプログラムを読んで,設問1,2に答えよ。

〔プログラムの説明〕

 与えられたパスを絶対パスに変換する関数 convert である。

 階層構造をもつファイルシステムにおいて,ファイルやディレクトリを 特定する文字列をパスという。ルートディレクトリを基準としたパスを絶対パスと呼び, “/”から始まり,各階層を“/”で区切っていく。与えられたパスがディレクトリのとき, 最後の“/”はあってもなくてもよい。例えば,図のディレクトリ e の絶対パスは “/a/d/e”又は“/a/d/e/”で示す。

 一方,カレントディレクトリを基準としたパスを相対パスと呼び,相対パスを 指定するときに階層を一つ上にたどる場合は“..”を用いる。 例えば,図においてディレクトリ c をカレントディレクトリにした場合, ファイル file1.txt の相対パスは“../file1.txt”,ディレクトリ e の相対パスは “../../d/e”又は“../../d/e/”となる。また,カレントディレクトリ自身は “.”又は“./”で示す。

01_総合問題1
関数の仕様は,次のとおりである。
void convert(const char *path,const char *base, char *result);

引数:path 変換前のパス
   base カレントディレクトリの絶対パス
   result 変換後の絶対パス

機能:path が相対パス表記であれば,base を基準にした絶対パス表記に変換し, result に格納する。path が絶対パス表記であれば,result には base に関係なく path をそのまま格納する。

返却値:なし。

 ただし,result が参照する領域は,変換後の文字列を格納するのに十分であるとする。 また,冗長なパス又はパスとして認識できない文字列が引数として与えられることはないものとする。

(2) ファイルシステム上に,指定されたディレクトリやファイルが実際に存在するかどうかのチェックは行わない。

(3) 変換例を表1に示す。

(4) 次のライブラリ関数を用いる。

unsigned int strlen(const char *s);
  機能:文字列 s の長さを計算する。
  返却値:終端を示すナル文字に先行する文字の個数を返す。
int strcmp(const char *s1, const char *s2);
  機能:文字列 s1 と文字列 s2 を比較する。
  返却値: s1 と s2 が同一文字列の場合は0,それ以外の場合は0以外を返す。

int strncmp(const char *s1, const char *s2, int n);
  機能:文字列 s1 と文字列 s2 を先頭から n 文字,又はナル文字までを比較する。
  返却値:比較した n 文字が同一の場合は0を, それ以外の場合(比較が途中で終了した場合も含む)は0以外を返す。

char *strcpy(char *s1, const char *s2);
  機能:文字列 s1 に文字列 s2 をナル文字まで複写する。
  返却値:s1

char *strncpy(char *s1, const char *s2, int n);
  機能:文字列 s1 に文字列 s2 を n 文字複写する。s2 の長さが n 以上の場合は n 文字目までを複写し,n 未満の場合は残りをナル文字で埋める。
  返却値:s1


〔プログラム〕
#include
void convert(const char*, const char*, char*);

void convert(const char *path, const char *base, char *result){

const char *pp, *bp;
char *rp;
int length;

/* pathが絶対パス表記の場合 */
if(*path == '/'){
{ a };
return;
}
/* pathがカレントディレクトリの場合 */
if(!strcmp(path, ".") || !strcmp(path, "./")){
{ b };
return;
}

length = strlen(base);
bp = base + length; /* bpは文字列baseの終端を指す。*/
if(*(bp - 1) == '/')
--bp;

/* pathの先頭部にある".."又は"../"を解析することで,
baseのパス表記のうち,どこまでresultと共通になるかを調べる。*/
for(pp = path; *pp != '\0' && *pp == '.';){
if(!strncmp(pp, "../", 3)){
pp += 3;
while(bp > base && *--bp != '/');
}else if(!strncmp(pp, "./", 2)){
pp += 2;
}else if(!strncmp(pp, "..\0", 3)){
pp += 2;
while(bp > base && *--bp != '/');
}else{
break;
}
}
/* baseのパス表記と共通な部分をresultに複写する。*/
length = { c };
strncpy(result, base, length);

rp = { d };
*rp++ = '/';

/* pathの文字列のうち,先頭部分の"./"や".."を除いた残りの
部分(ppが指す文字列)を,resultの文字列に追加する。 */
strcpy(rp, pp);
return;
}

設問1 プログラム中の{ }に入れる正しい答えを, 解答群の中から選べ。

a,b に関する解答群
ア strcpy(base, path)     イ strcpy(base, result)
ウ strcpy(path, base)      エ strcpy(path, result)
オ strcpy(result, base)     力 strcpy(result, path)


c に関する解答群
ア bp ‐base     イ bp - path
ウ pp - base     エ pp - path

d に関する解答群
ア base + length       イ bp + length
ウ path + length       エ pp + length
オ result + length

設問2 表2の引数列で関数 convert を呼んだときのプログラムの動作について,表2中の{ }に入れる正しい答えを,解答群の中から選べ。ただし, プログラム中の{ a }~{ d }には 正しい答えが入っているものとする。

e に関する解答群
ア ../d/       イ ../../../../d/
ウ /         エ /../d/
オ /d/        力 d/

f,g に関する解答群
ア /a/b/c/d      イ /a/b/c/d/
ウ /a/b/cd       エ /a/b/cd/
オ d          力 d/

***********************************************************************************************************
無料から学べる講座
http://ai-light.com/itkeiei/

ニコニコチャンネル
http://ch.nicovideo.jp/ai-light

YouTubeチャンネル
https://www.youtube.com/user/ailightcom

Access・Excel倶楽部
http://ai-light.com/accessclub/

株式会社アイライト公式HP
http://www.ai-light.com/
(Access・Excelでシステム開発会社を探されている法人様はこちら)

***********************************************************************************************************
********************************************************************************
解答
問1
答 aカ 答 bオ 答 cア 答 dオ

問2
答 eオ 答 fイ 答 gア

********************************************************************************
解説
#include
#includeは別のファイルで宣言されている関数をファイルに埋め込むことができる。
string.hではstrcpyなど文字列操作に関する関数が定義されている。

void convert(const char*, const char*, char*);
関数の定義は宣言している。

const char *pp, *bp;
const修飾子は指定した変数が定数であるを示す。定数であるということは、変数のように中身が変更できなくなる。これによって人為的なミスを防ぐことが出来る。

if(*path == '/')
*pathの一文字目に'/'が入っているか確認している。問題文にある通り絶対パスの場合は “/”から始まるから、c言語のコメントの通り、pathが絶対パス表記であるかを確認している。

{ a }
関数の仕様により、絶対パス表記であれば,result には base に関係なく path をそのまま格納する。よって、{ a }は「カ」となる。

strcmp(path, ".")
ライブラリ関数の通り、pathという文字列全体と"."を比べて、pathが"."と同一であれば、”0”となる。If文は0以外であれが真として扱われ、0であれば偽と扱われる。よってそのままでは同一の時に偽と判断されてしまう。そこで、!strcmp(path, ".")の!で否定を行う。否定は、偽の場合「真」となり、真の場合「偽」となる。

if(!strcmp(path, ".") || !strcmp(path, "./"))
ではコメントにある通り、pathがカレントディレクトリである場合の処理を行う。関数の仕様により、baseには カレントディレクトリの絶対パスが入っているよって、結果、*result
に*baseをセットしてやればよいことがわかる。よって、{ b }は、「オ」となる。

bp = base + length
lengthには”base”の文字列数が入っている。
base は、文字列ポインタで最初のアドレスが入っている。文字列のアドレスは下図のように連番になっている。例えば、下図のような文字列の時、lengthは文字列が”abc””であることから”3”となる。baseに先頭のアドレス”100”が入っているとすると、base + lengthは103となり、終端文字である\0が入る。*(bp - 1)することにより、文字列の最終文字が入る。
アドレス 値
100 a
101 b
102  c
103 \0

for(pp = path; *pp != '\0' && *pp == '.';)以下
ロジックを解析する場合には具体的な値を想定していけば、わかりやすい。
例えば、path=../../b/c/ 、base=/a/d/e/とする。

for(pp = path;・・・・・
でppに“../../b/c/“に文字の先頭アドレスをセットする。
if(!strncmp(pp, "../", 3))でppの最初の3つの文字が"../"かどうかを判別している。
この例であると、最初の3つの文字が"../"であるから、ifの中に入ってくる。

pp += 3
で3つアドレスを移動する。よって、ppに“../「.」./b/c/“の「」の部分のアドレスが設定される。

while(bp > base && *--bp != '/');
でbpは文字列“base=/a/d/e「/」”の「」のアドレスが設定されている。--bpでbpは一つ前の文字のアドレスである文字列 “base=/a/d/「e」/”の「」の文字アドレスが設定される。
--bp != '/'までループするということなので、文字列“base=/a/d「/」e/”の「」の文字アドレスが入る。

ここで何をしているかという相対パスをたどりながら、絶対パスを求めていることがわかる。ここまでの処理で、相対パスの“../b/c/は、絶対パスの/a/d/であることがわかる。

For文でループするので、この例の最終結果は、
ppに文字列“../../「b」/c/“の「」の部分のアドレスが設定され、
bpに文字列“base=/a「/」d/e/」” の「」の部分のアドレスが設定される。

{ c }
では、resultに”/a/”の部分をセットしたい。baseは文字列”「/」a/”の「」の文字アドレスが入っており、bpには文字列” /a「/」”の文字アドレスが入っている。よって、lengthは、
bp- baseで求めらるので、解答はアとなる。

厳密には、下表のようになっているとすると、bp- baseは2となる。

アドレス  値
100 /
101 a
102 /

strncpy(result, base, length)
で2文字をコピーすることから、resultには” /a/”ではなく、” /a”の文字が入っている。よって、*rp++ = '/'でresultに” /a/”が入ることになる。

これは、設問2にも関わることであるが、baseの最終文字が”/”で終わってなくても、rusultを求める過程で、”/”という文字が必ずセットされる。

{ d }
strcpy(rp, pp)で、resultにセットされている”/a/”にppの”b/c/”をセットしたいので、rpには、resultをセットしてその文字列アドレスを最終文字にしておく必要がある。
よって、result+lengthを行う必要があるので、解答はオとなる。

***********************************************************************************************************
無料から学べる講座
http://ai-light.com/itkeiei/

ニコニコチャンネル
http://ch.nicovideo.jp/ai-light

YouTubeチャンネル
https://www.youtube.com/user/ailightcom

Access・Excel倶楽部
http://ai-light.com/accessclub/

株式会社アイライト公式HP
http://www.ai-light.com/
(Access・Excelでシステム開発会社を探されている法人様はこちら)

***********************************************************************************************************

設問2

{ e }
pathを順に遡っていくと以下のようになる。
path=../../../../d/  base=/a/b/c/
path=../../../d/  base=/a/b/
path=../../d/  base=/a/
path=../d/  base=/

path=../d/  base=/のとき、
for(pp = path; *pp != '\0' && *pp == '.';)のループ条件「*pp != '\0' && *pp == '.'」は満たしているので、ループの中に入ってくる。
if(!strncmp(pp, "../", 3))もif文を満たしているので、ifの中に入ってくる。よって、pp += 3となり、path=d/となる。
while(bp > base && *--bp != '/');でbase=””となる。

設問1より、resultの結果は*rp++ = '/'で”/”が足され”/d/”となる。よって、解答はオとなる。

{ f }{ g }
設問1で解説した通り、baseの文字が”/a/b/c”であっても必ず、”/”は文字が足されるので、解答のウとかエになることはない。また、pathの文字はstrcpy(rp, pp)で、そのまま足されているので、fの解答は/a/b/c/d/となり解答はイであり、gの解答は/a/b/c/d       となり解答はアとなる。

参考:平成21年 春期 基本情報技術者試験 午後 問09
関連記事

コメント

コメントの投稿

非公開コメント

adwords

外部リンク

カテゴリーメニュー 改

当社のシステム開発の詳細

当社はaccess-excelでの小規模システム開発を中心に年間に50社以上の開発実績がございます。詳細は06-6599-8890ないしinfo@ai-light.comまで今すぐお問合せください

メールフォーム

こちらからも簡単にメールを送付できます。当社のサービスに関してご質問がございましたら、よろしければ、ご利用ください。直接お電話の場合は06-6599-8890までご連絡ください。

名前:
メール:
件名:
本文:

検索フォーム

広告

最新記事

Lc.ツリーカテゴリー

全記事表示リンク

プロフィール

itkeieinews

Author:itkeieinews
ITと経営ニュースへようこそ!
アイライトIT経営研究会
株式会社アイライト
電話でのお問合せは06-6599-8890
Email:info@ai-light.com

お気に入り

本サイトをそのまま消してしまうと、もう探せなくなってしまうかもしれません。 当社はいずれお役に立てることがあるかと思いますので、よろしければお気に入りにご登録ください。

ブロとも申請フォーム