C言語何でも質問掲示板


アンケートにご協力下さい → >> アンケートフォーム <<

規約と使い方

 
   学校の課題なんですが   
     ・[5280] バグ 
     ・[5282] box 
     ・[5283] 素人 
     ・[5284] バグ 
     ・[5285] 素人 
     ・[5288] バグ 
     ・[5289] バグ 
     ・[5313] 素人 
     ・[5314] バグ 
     ・[5316] box 
     ・[5318] バグ 
     ・[5350] 大阪慕情 
     ・[5352] 素人 
     ・[5353] バグ 
     ・[5354] box 
     ・[5355] 素人 
     ・[5357] バグ 
     ・[5358] 素人 
     ・[5361] むつ 
     ・[5399] 素人 
     ・[5417] 素人 
     ・[5435] Yuki 
     ・[5466] 素人 
     ・[5467] box 
     ・[5473] Yuki 
     ・[5494] 素人 
     ・[5501] box 
     ・[5502] Yuki 
     ・[5718] 素人 
     ・[5721] box 
     ・[5726] 素人 
     ・[5798] Yuki 
     ・[5811] 素人 
   構造体のメンバのメモ ....   
     ・[5731] box 
     ・[5736] parapara 
     ・[5737] box 
     ・[5741] parapara 
   半透明描画したいので ....   
     ・[5734] 管理人 
     ・[5739] へろへろ 
     ・[5740] 管理人 
   メンバポインタ演算子   
     ・[5667] GPGA 
     ・[5722] 組木紙織 
   おひさしぶりです   
     ・[4967] 大工 
     ・[4968] 管理人 
     ・[4969] 管理人 
     ・[4974] むつ 
     ・[4976] ダッシュ 
     ・[4977] ダッシュ 
     ・[4978] 大工 
     ・[4981] 管理人 
     ・[4983] ダッシュ 
     ・[4984] 管理人 
     ・[4985] 管理人 
     ・[4986] 管理人 
     ・[4988] ダッシュ 
     ・[4989] ダッシュ 
     ・[4990] 大工 
     ・[4992] 管理人 
     ・[4997] ダッシュ 
     ・[5004] 管理人 
     ・[5010] ダッシュ 
     ・[5015] Justy 
     ・[5018] 管理人 
     ・[5033] ダッシュ 
     ・[5059] 管理人 
     ・[5065] ダッシュ 
     ・[5067] 管理人 
     ・[5068] 管理人 
     ・[5069] 管理人 
     ・[5259] ダッシュ 
     ・[5263] 管理人 
     ・[5266] ダッシュ 
     ・[5642] 管理人 
     ・[5649] ダッシュ 
     ・[5671] 管理人 
   LINKでpokeがエラ ....   
     ・[5611] asd 
     ・[5670] 管理人 
   音楽ゲームについて   
     ・[5498] Justy 
     ・[5567] 神魔 
     ・[5643] 管理人 
     ・[5661] 神魔 
     ・[5669] 管理人 
   関数の使い分けと読み ....   
     ・[5609] Justy 
     ・[5648] sign 
     ・[5662] Justy 
     ・[5666] sign 
   fscanfの簡易正規表現 ....   
     ・[5410] Justy 
     ・[5412] GPGA 
     ・[5416] Justy 
     ・[5554] GPGA 
     ・[5585] Justy 
   ファイルへの書き込み ....   
     ・[5398] み〜 
     ・[5400] keichan 
     ・[5401] み〜 
     ・[5402] み〜 
     ・[5403] GPGA 
     ・[5404] keichan 
     ・[5405] keichan 
     ・[5406] み〜 
     ・[5407] み〜 
     ・[5408] み〜 
     ・[5418] み〜 
     ・[5419] み〜 
     ・[5420] み〜 
     ・[5421] box 
     ・[5422] miyaza 
     ・[5423] み〜 
     ・[5424] み〜 
     ・[5425] miyaza 
     ・[5426] box 
     ・[5427] み〜 
     ・[5428] フリオ 
     ・[5429] box 
     ・[5438] み〜 
     ・[5440] み〜 
     ・[5441] 組木紙織 
     ・[5442] み〜 
     ・[5443] 組木紙織 
     ・[5444] み〜 
     ・[5445] 組木紙織 
     ・[5446] み〜 
     ・[5447] 組木紙織 
     ・[5448] み〜 
     ・[5449] 組木紙織 
     ・[5450] み〜 
     ・[5452] miyaza 
     ・[5453] み〜 
     ・[5454] miyaza 
     ・[5455] み〜 
     ・[5456] miyaza 
     ・[5457] み〜 
     ・[5458] miyaza 
     ・[5459] 組木紙織 
     ・[5460] box 
     ・[5461] み〜 
     ・[5462] み〜 
     ・[5463] miyaza 
     ・[5464] み〜 
     ・[5465] み〜 
     ・[5472] み〜 
     ・[5474] ※ 
     ・[5475] み〜 
     ・[5476] み〜 
     ・[5477] miyaza 
     ・[5478] miyaza 
     ・[5479] み〜 
     ・[5480] miyaza 
     ・[5481] み〜 
     ・[5482] miyaza 
     ・[5483] ※ 
     ・[5484] み〜 
     ・[5485] ※ 
     ・[5486] み〜 
     ・[5487] み〜 
     ・[5488] miyaza 
     ・[5489] み〜 
     ・[5490] み〜 
     ・[5491] 組木紙織 
     ・[5492] み〜 
     ・[5495] み〜 
     ・[5496] ※ 
     ・[5497] み〜 
     ・[5500] み〜 
     ・[5505] miyaza 
     ・[5506] miyaza 
     ・[5512] み〜 
     ・[5516] み〜 
     ・[5517] ※ 
     ・[5519] み〜 
     ・[5520] miyaza 
     ・[5521] ※ 
     ・[5522] み〜 
     ・[5524] miyaza 
     ・[5525] box 
     ・[5526] み〜 
     ・[5527] み〜 
     ・[5528] miyaza 
     ・[5529] み〜 
     ・[5530] box 
     ・[5531] み〜 
     ・[5532] 組木紙織 
     ・[5533] ※ 
     ・[5534] box 
     ・[5535] み〜 
     ・[5536] miyaza 
     ・[5537] み〜 
     ・[5538] miyaza 
     ・[5539] み〜 
     ・[5540] miyaza 
     ・[5541] miyaza 
     ・[5542] み〜 
     ・[5543] み〜 
     ・[5544] み〜 
     ・[5545] miyaza 
     ・[5546] み〜 
     ・[5547] miyaza 
     ・[5548] み〜 
     ・[5549] み〜 
     ・[5550] miyaza 
     ・[5551] み〜 
     ・[5552] ※ 
     ・[5553] miyaza 
     ・[5555] miyaza 
     ・[5556] み〜 
     ・[5557] miyaza 
     ・[5558] み〜 
     ・[5560] むつ 
     ・[5561] み〜 
     ・[5565] Yuki 
     ・[5566] バグ 
     ・[5569] むつ 
     ・[5570] み〜 
     ・[5571] み〜 
     ・[5572] むつ 
     ・[5573] み〜 
     ・[5574] miyaza 
     ・[5575] miyaza 
     ・[5576] み〜 
     ・[5577] み〜 
     ・[5578] み〜 
     ・[5579] miyaza 
     ・[5580] み〜 
     ・[5581] み〜 
     ・[5582] miyaza 
     ・[5583] miyaza 
     ・[5584] み〜 
   質問です!   
     ・[5562] box 
     ・[5563] むつ 
     ・[5564] いさご 
   リバーシのアルゴリズ ....   
     ・[5503] Yuki 
     ・[5504] GPGA 
     ・[5507] Justy 
     ・[5508] GPGA 
     ・[5509] keichan 
     ・[5510] なぎ 
     ・[5511] 組木紙織 
     ・[5513] なぎ 
     ・[5514] Yuki 
     ・[5515] 組木紙織 
     ・[5518] なぎ 
     ・[5523] 組木紙織 
   用語を簡単に教えてく ....   
     ・[5432] バグ 
     ・[5433] Yuki 
     ・[5434] むつ 
     ・[5469] kuroca 
     ・[5493] めちゃ初心者 
   皆さん、しっかりしま ....   
     ・[5470] しっぽ 
     ・[5471] バグ 
   ご質問です   
     ・[5270] バグ 
     ・[5286] てっぺい 
     ・[5290] バグ 
     ・[5297] むつ 
     ・[5299] てっぺい 
     ・[5339] Yuki 
     ・[5362] teppei 
     ・[5451] asd 
   質問です。   
     ・[5437] Yuki 
   無題   
     ・[5291] GPGA 
     ・[5292] GPGA 
     ・[5293] み 
     ・[5294] み 
     ・[5295] GPGA 
     ・[5296] み〜 
     ・[5298] box 
     ・[5300] み〜 
     ・[5301] み〜 
     ・[5302] box 
     ・[5303] み〜 
     ・[5304] み〜 
     ・[5305] box 
     ・[5306] み〜 
     ・[5307] box 
     ・[5309] み〜 
     ・[5310] バグ 
     ・[5311] み〜 
     ・[5312] バグ 
     ・[5317] み〜 
     ・[5319] み〜 
     ・[5321] GPGA 
     ・[5324] み〜 
     ・[5331] み〜 
     ・[5332] み〜 
     ・[5333] バグ 
     ・[5334] み〜 
     ・[5335] バグ 
     ・[5336] み〜 
     ・[5337] box 
     ・[5338] み〜 
     ・[5340] み〜 
     ・[5341] バグ 
     ・[5342] み〜 
     ・[5343] み〜 
     ・[5344] バグ 
     ・[5345] GPGA 
     ・[5346] Yuki 
     ・[5347] み〜 
     ・[5349] GPGA 
     ・[5351] mi~ 
     ・[5356] GPGA 
     ・[5360] み〜 
     ・[5363] み〜 
     ・[5364] み〜 
     ・[5365] GPGA 
     ・[5366] GPGA 
     ・[5367] み〜 
     ・[5378] み〜 
     ・[5379] み〜 
     ・[5381] GPGA 
     ・[5382] み〜 
     ・[5383] GPGA 
     ・[5384] み〜 
     ・[5385] box 
     ・[5386] み〜 
     ・[5387] GPGA 
     ・[5388] GPGA 
     ・[5389] GPGA 
     ・[5390] み〜 
     ・[5391] むつ 
     ・[5392] み〜 
     ・[5393] GPGA 
     ・[5394] GPGA 
     ・[5395] むつ 
     ・[5396] み〜 

Name: 素人  ..ぴよぴよ(696ポイント)   Date: 2007/03/10(土) 16:24   No:5278       
Title: 学校の課題なんですが    
下記プログラムで生年月日の入出力は,YYYY/MM形式で行い,西暦が数字4桁で,西暦と月の間に'/'があり,月が01〜12の範囲の数字の2桁になっている7文字の入力のみ受け付け,最初の4文字が数字で5文字目がスラッシュで6、7文字目で1〜12の数字である以外は再入力させたるプログラムです。
やってみたのですが入力はできるのですが判定ができません。
どなたか教えてもらえませんか。

<pre>#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXNAME 11 /* 名前の最大入力文字数 10文字 + '\0' */
#define MYBIRTH 9 /* 生年月日の年の形*/
#define MAXCASE 10 /* 最大ユーザー件数 */

void get_string(char *p_str, int xMaxChar);

struct user
{
char Name[MAXNAME]; /* ユーザ名 */
char MyBirth[MYBIRTH];/* 生年月日*/
};
void main()
{
struct user s_user[MAXCASE];
int Manth;
int i, j = 0;


while( j < MAXCASE ){/* データ入力 */

printf("名前:");
get_string(s_user[j].Name, MAXNAME);


if ( s_user[j].Name[0] == '0' ) {/* 1文字目が'0'のとき */
break;
}


if ( s_user[j].Name[0] == '\0' ) {/* 改行のみのとき */
printf("再入力\n");
continue;
}


/* 生年月日入力 */
printf("生年月日:");

get_string(s_user[j].MyBirth, MYBIRTH);




/* 年の数字チェック */
for (i = 0; i < 4; i++) {/* 各桁の文字が0~9である*/
if( isupper(s_user[j].MyBirth[i] ) != 0 ){


}
else{
printf("数字ではありません\n");
break;
}
}

while( s_user[j].MyBirth[5] == '/'){/*5行目が/である*/

if( s_user[j].MyBirth[6] == '0'){/*6行目が0である*/

if( isupper(s_user[j].MyBirth[7] ) != 0){/*7行目が数字である*/

}
else if (s_user[j].MyBirth[6] == '1'){/*6行目が1である*/

if( '0' <= s_user[j].MyBirth[7] && s_user[j].MyBirth[7] <= 2){/*7行目が0~2である*/

}
else{

printf("数字ではありません\n");
continue;
}
}

}

continue;
}

printf("累計件数 = %d件\n\n", ++j);
}

printf("\n入力データ表示\n");



for (i = 0; i < j; i++) {
printf("%d件目\n", i + 1);
printf("名前 = %s\n", s_user[i].Name);
printf("生年月日 = %s\n", s_user[i].MyBirth);
}
}

void get_string(char *p_str, int xMaxChar)
{
int i = 0;
int C;

while ( (C = getchar()) != EOF && C != '\n' ){
if ( i < xMaxChar - 1 ) {
*p_str = C;
p_str++;
i++;
}
}
*p_str = '\0';
}


696ポイント を手に入れた。


Name: バグ  ..プログラマー(29,515ポイント)   Date: 2007/03/10(土) 16:56   No:5280     
Title: Re:学校の課題なんですが    
こんにちは(^-^)

まず、確認したい事があるのですが…判定ができないというのは、どのように判定したいのに出来ないという事なのでしょうか?

こういう場合に、現状ではこんな現象が起こっていて、こうしたいのに出来ない。というのを詳しく教えていただけますか?

あ、それから、生年月日の月の判定は、strtol関数を利用されてはいかがでしょうか?
文字列をlong型の数値に変換する関数なので、変換した値が1〜12の範囲に納まっていなければ、再入力するようにすれば、スッキリしそうな気がしますよ(^-^)


245ポイント を手に入れた。

Name: box  ..熟練のプログラマー(54,858ポイント)   Date: 2007/03/10(土) 17:27   No:5282     
Title: Re:学校の課題なんですが    
要するに、ある文字列を"/"で区切って、4桁(1000〜9999の範囲)と
2桁(1〜12の範囲)の数値を取り出したいわけですから、
strtok関数とstrtol関数あたりを使ってみてはいかがでしょうか。


297ポイント を手に入れた。

Name: 素人  ..ぴよぴよ(827ポイント)   Date: 2007/03/10(土) 17:29   No:5283     
Title: Re:学校の課題なんですが    
バグ様、返信有難うございます。

生年月日を1234/12と入力しても数字では数字ではありませんと出てしまうのです。それに再入力にもなりません。再入力の仕方もよくわかりません。

123/09や1234/13や1234/111などのYYYY/MM式にあってないときにエラーとして再入力をさせたいのです。

strtol関数の使い方が解りません。MyBirth[6]とMyBirth[7]でも扱えるのでしょうか。

乱文ですいませんが教えていただけないでしょうか


131ポイント を手に入れた。

Name: バグ  ..プログラマー(29,464ポイント)   Date: 2007/03/10(土) 18:07   No:5284     
Title: Re:学校の課題なんですが    
ということは、年は必ず4文字、スラッシュは必ず5文字目、月は必ず2文字でないと駄目という事でいいですか?


51ポイント を落としてしまった。

Name: 素人  ..ぴよぴよ(879ポイント)   Date: 2007/03/10(土) 18:45   No:5285     
Title: Re:学校の課題なんですが    
はい。そうです。YYYY/MMの7文字入力するよにしたいのです。

2倍のポイントを手に入れた! 52ポイント を手に入れた。

Name: バグ  ..プログラマー(30,036ポイント)   Date: 2007/03/10(土) 20:43   No:5288     
Title: Re:学校の課題なんですが    
まず、年の判定ですが、user構造体のメンバ変数であるMyBirthの[0]〜[3]までの4文字が全て数字であった場合にOKという判定になりますよね。という事は、文字が数値であるかどうかを判定する事ができれば解決するはずです。素人さんのソースを見ていると、isupper関数を使われていますが、この関数は英大文字を判定するものですので、今回の件では数字かどうかを判定するisdigit関数を使うのが良いかと思います。

それから、スラッシュ( '/' )の判定ですが、[5]の値を参照していますが、[0]から数えて[4]番目の値になるはずですから、ここも直してください。

最後に月の判定ですが、前の書き込みで紹介しましたstrtol関数を利用するのが良いかと思います。

char *pCheck
nMonth = strtol( &s_user[j].MyBirth[5] , &pCheck , 10 );

使い方はこんな感じです。1番目の引数は調べたい文字列の先頭アドレス、2番目は調べた文字列の最終アドレスが格納されるポインタのポインタになります。3番目は基数となり、今回は10進数ですから10と入力してください。これで、nMonthに文字列からlong型に変更された値が入力されていますので、nMonthの値が1〜12でない場合NGとすればいい訳です。

これらの3つの判定が全てOKであれば、この文字列は問題無いと判断できると思いますので、この3つ全てがOKになるまでは再入力を繰り返すようにすればいけるかと思います。


572ポイント を手に入れた。

Name: バグ  ..プログラマー(30,066ポイント)   Date: 2007/03/10(土) 20:45   No:5289     
Title: Re:学校の課題なんですが    
>>文字が数値

すみません、『文字が数字』の間違いでした(^_^;)


30ポイント を手に入れた。

Name: 素人  ..ぴよぴよ(956ポイント)   Date: 2007/03/11(日) 18:41   No:5313     
Title: Re:学校の課題なんですが    
バク様返信ありがとうございます。


>char *pCheck
>nMonth = strtol( &s_user[j].MyBirth[5] , &pCheck , 10 );

なのですが、MyBirth[5] の値がnMonth にlong型に変更された入るとMyBirth[6]番目の値はどうすればいいのでしょうか。






77ポイント を手に入れた。

Name: バグ  ..プログラマー(30,723ポイント)   Date: 2007/03/11(日) 18:59   No:5314     
Title: Re:学校の課題なんですが    
strtol関数は指定したアドレスから、数字以外の文字が見つかるまで調べてくれる関数なんですね。

つまり、今回は[5]のアドレスを引数として渡していますので、[5]から調査を開始して[6]、[7]、[8]…と数字以外が見つかるまでどんどんと調べる訳です。

例えば【2007/03】こんな文字列だった場合…

2…[0]
0…[1]
0…[2]
7…[3]
/…[4]
1…[5]
2…[6]
0…[7]

こんな感じで格納されていますから、[5]の'1'から調査を開始して、[7]の'0'で終了する訳です。


140ポイント を手に入れた。

Name: box  ..熟練のプログラマー(55,049ポイント)   Date: 2007/03/11(日) 19:29   No:5316     
Title: Re:学校の課題なんですが    
> 例えば【2007/03】こんな文字列だった場合…
>
> 1…[5]
> 2…[6]
> 0…[7]

質問者のかたが混乱しそうです。

'0'…[5]
'3'…[6]
'\0'…[7]


2ポイント を手に入れた。

Name: バグ  ..プログラマー(30,688ポイント)   Date: 2007/03/11(日) 19:49   No:5318     
Title: Re:学校の課題なんですが    
あら?携帯からだと¥0が0しか表示されないみたいですね…(;^_^A
失礼しましたm(__)m


35ポイント を落としてしまった。

Name: 大阪慕情  ..ぴよぴよ(2ポイント)   Date: 2007/03/12(月) 14:04   No:5350     
Title: 使ってやってください。    
#include <stdio.h>
#include <string.h>
#define NUM 7
#define ON 1
#define NO 0
int check(char *cp){
int ia=ZERO;ic=ZERO;
char *kp;
ib=strlen(cp);
kp=cp;
if(strlen(cp)==NUM){
for(;*kp!='\n';kp++){
         switch(kp-cp){
case 0:if(*kp=='1') ia++;break;
case 1:if(*kp=='9') ia++;break;
case 2:if(*kp>='0' && *kp<='9') ia++;break;
case 3:if(*kp>='0' && *kp<='9') ia++;break;
case 4:if(*kp=='/') ia++;break;
case 5:if(*kp=='1') ia++;break;
case 6:if(*kp>='1' && *kp<='2') ia++;break;
default:;break;
}
}
if(ia==7) ic=1;
else ic=ZERO;
}
else ic=ZERO;
return(ic);
}
int main(void){
char *ap;
int ib;
printf("Year?=");scanf("%s",ap);printf("\n");
ib=check(ap);
if(ib=ON) printf("%s\n",*ap);
else return(0);
return(0);
}



2ポイント を手に入れた。

Name: 素人  ..かけだし(1,743ポイント)   Date: 2007/03/12(月) 16:35   No:5352     
Title: Re:学校の課題なんですが    
皆様の意見を参考に組んでみたのですが、12345/12でもエラーにならずに通過してしまいます。
後、処理が全てOKでなら無限ループを抜けたいのですがそれもうまくできていません。
処理の仕方に問題があると思うのですがどこを直せばいいのか検討がつきません。
教えていただけないでしょか。

<pre>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXNAME 11 /* 名前の最大入力文字数 10文字 + '\0' */
#define MYBIRTH 7 /* 生年月日の年の形*/
#define MAXCASE 10 /* 最大ユーザー件数 */

void get_string(char *p_str, int xMaxChar);

struct user{

char Name[MAXNAME]; /* ユーザ名 */
char MyBirth[MYBIRTH];/* 生年月日*/

};

void main(){

struct user s_user[MAXCASE];
int nMonth;
int i, j = 0;


while( j < MAXCASE ){/* データ入力 */

printf("名前:");
get_string(s_user[j].Name, MAXNAME);


if ( s_user[j].Name[0] == '0' ) {/* 1文字目が'0'のとき */
break;
}


if ( s_user[j].Name[0] == '\0' ) {/* 改行のみのとき */
printf("再入力\n");
continue;
}

while(1){
/* 生年月日入力 */
printf("生年月日:");

get_string(s_user[j].MyBirth, MYBIRTH);




/* 年の数字チェック */
for (i = 0; i < 4; i++) {/* 各桁の文字が0~9である*/
if( isdigit(s_user[j].MyBirth[i] ) != 0 ){


}
else{
printf("数字ではありません\n");
break;
}
}

while( s_user[j].MyBirth[4] == '/'){/*5行目が/である*/

char *pCheck;
nMonth = strtol( &s_user[j].MyBirth[5] , &pCheck , 10 );

if( 1 <= nMonth || nMonth <= 12){

/*無限ループ抜ける処理がしたいです*/
}

//continue;
}

printf("累計件数 = %d件\n\n", ++j);
}

printf("\n入力データ表示\n");



for (i = 0; i < j; i++) {
printf("%d件目\n", i + 1);
printf("名前 = %s\n", s_user[i].Name);
printf("生年月日 = %s\n", s_user[i].MyBirth);
}
}

void get_string(char *p_str, int xMaxChar){

int i = 0;
int C;

while ( (C = getchar()) != EOF && C != '\n' ){
if ( i < xMaxChar - 1 ) {
*p_str = C;
p_str++;
i++;
}
}
*p_str = '\0';
}



787ポイント を手に入れた。

Name: バグ  ..プログラマー(32,238ポイント)   Date: 2007/03/12(月) 16:55   No:5353     
Title: Re:学校の課題なんですが    
while( s_user[j].MyBirth[4] == '/'){/*5行目が/である*/


この行は何を見ているのでしょうか?(^_^;)
もし、スラッシュかどうかの判定をしたいのであれば…

if( s_user[j].MyBirth[4] == '/' )
{
// OK時の処理
}
else
{
// NG時の処理
}

こんな感じでいけると思いますよ(^-^)


41ポイント を手に入れた。

Name: box  ..熟練のプログラマー(55,127ポイント)   Date: 2007/03/12(月) 17:18   No:5354     
Title: Re:学校の課題なんですが    

> #define MYBIRTH 7 /* 生年月日の年の形*/
>
> char MyBirth[MYBIRTH];/* 生年月日*/

"YYYY/MM"の形式のデータを格納するには1バイト不足しています。
終端の'\0'の分を追加して、8バイト確保してください。



38ポイント を手に入れた。

Name: 素人  ..かけだし(1,894ポイント)   Date: 2007/03/12(月) 17:25   No:5355     
Title: Re:学校の課題なんですが    
バグ様、早い返信ありがとうございます。

while( s_user[j].MyBirth[4] == '/'){/*5行目が/である*/

char *pCheck;
nMonth = strtol( &s_user[j].MyBirth[5] , &pCheck , 10 );

if( 1 <= nMonth || nMonth <= 12){

/*無限ループ抜ける処理がしたいです*/


この処理で5行目が/の場合、月の処理が1〜12かを調べることをさせたいのですが、おかしいのでしょうか。


151ポイント を手に入れた。

Name: バグ  ..プログラマー(32,262ポイント)   Date: 2007/03/12(月) 17:51   No:5357     
Title: Re:学校の課題なんですが    
if( 1 <= nMonth || nMonth <= 12)

この判定文がおかしいです。

nMonthが1より小さい、もしくは、12よりも小さい場合に真となっています。つまり、1以下でないと真となりません。

今回の場合でしたら、1以上でなおかつ、12以下の場合に真としなければいけませんよね?


24ポイント を手に入れた。

Name: 素人  ..かけだし(1,979ポイント)   Date: 2007/03/12(月) 18:33   No:5358     
Title: Re:学校の課題なんですが    
返信ありがとうございます。

if( nMonth >= 1 && nMonth <= 12) と直しましたが12345/12でもエラーになりません。

5行目が/ではないの何故エラーにならないのでしょうか。


85ポイント を手に入れた。

Name: むつ  ..入門者(4,077ポイント)   Date: 2007/03/12(月) 19:56   No:5361     
Title: Re:学校の課題なんですが    
 以下のソースを掲示する事で混乱してしまうかもしれませんが、
頭のリフレッシュと思ってください。
 構造体に格納する前に入力文字のチェックを済ませておきたいので
キーを押した段階で入力チェックしています。(西暦のチェックは省略しています)
使用コンパイラ:Borland C++Compiler 5.5

// ============================================================================
// 年月入力判定 part.2
//
// ※入力を受け付けない場合、ウィンドウを閉じる
// ============================================================================
#include <stdio.h>
#include <conio.h>

int main( void )
{
int num, key;
char birthday[ 8 ];
// 変数の初期化( num = 0は1番目の入力を指す )
num = 0;
printf( "When is your birthday?(YYYY/MM) " );
while( num < 7 ) {
// 0〜9 または / 入力 キーコードをkeyに代入
key = getch();
// case num: 何番目の入力か
switch( num ) {
// '/'の入力
case 4:
if( key == 47 ) {
birthday[ 4 ] = putchar( key );
num++;
}
break;
case 5:
// 0と1以外はスルー
if( key == 48 || key == 49 ) {
birthday[ 5 ] = putchar( key );
num++;
}
break;
case 6:
// 1〜9月の場合
if( birthday[ 5 ] == 48 ) {
if( key > 48 && key <= 57 ) {
birthday[ 6 ] = putchar( key );
num++;
}
}
// 10〜12月の場合
if( birthday[ 5 ] == 49 ) {
if( key >= 48 && key <= 50 ) {
birthday[ 6 ] = putchar( key );
num++;
}
}
break;
// 0〜9の入力
default:
if( key >= 48 && key <= 57 ) {
birthday[ num ] = putchar( key );
num++;
}
}
}
printf( "\nYour birthday is.. %s\n", birthday );
return 0;
}


616ポイント を手に入れた。

Name: 素人  ..かけだし(2,064ポイント)   Date: 2007/03/13(火) 13:07   No:5399     
Title: Re:学校の課題なんですが    
むつさんソースありがとうございます。
でも、結構混乱しています。
やりたいことは、格納してからのチェックなのです・・・。
チェックしていく流れは少しわかりました。ありがとうございます。


85ポイント を手に入れた。

Name: 素人  ..かけだし(2,147ポイント)   Date: 2007/03/13(火) 19:15   No:5417     
Title: Re:学校の課題なんですが    
先生に課題で入出力以外のライブリ関数以外の仕様を禁止されてしまいました。
また始めの段階に戻ってしまいました。全てのチェックにおいて正しくないかを判定し再入力をするように変更したいです。

チェック項目は

1.入力された文字が7文字でない

2.配列のi番目の文字が数字でない

3.配列の0〜3番目の文字に不正な文字が含まれていたらエラー

4.配列の4番目の文字がスラッシュでない

5.配列の5,6番目の文字が00〜12でない


誰か書き方をご教授お願いします。


83ポイント を手に入れた。

Name: Yuki  ..上級者(16,910ポイント)   Date: 2007/03/14(水) 11:19   No:5435     
Title: Re:学校の課題なんですが    
とりあえず、どんな状況かわからないので、
今できているソースを載せてみてください。

うまくいかないところ等も具体的に書いてもらえると、
アドバイスしやすいです。


91ポイント を手に入れた。

Name: 素人  ..入門者(3,033ポイント)   Date: 2007/03/14(水) 22:30   No:5466     
Title: Re:学校の課題なんですが    
Yuki様、回答ありがとうございます。

今できているのはこのような感じです。
生年月日の再入力のところでcontinue文を使ってしまったため名前の再入力まで戻ってしまいます。
これを生年月日だけの再入力にしたいです。

7文字入力してもエラーになってしまいます。57行目でif(i <= 8 )が間違っていると思うのですがよくわかりません。


月の判定でが00〜12までか判定仕様として6、7文字目が数字の文字でないかどうかをチェックすると同時に数値化を行い、そのあとで、数値化した値が、0〜12までかどうか判定したいのですが、ここはまったく書き方がわかりません。

乱文ですいませんが、よろしくおねがいします。


#include <stdio.h>

#include <stdlib.h>

#define MAXNAME 11 /* 名前の最大入力文字数 10文字 + '\0' */
#define MYBIRTH 9 /* 生年月日の年の形*/
#define MAXCASE 10 /* 最大ユーザー件数 */

void get_string(char *p_str, int xMaxChar);

struct user{
char Name[MAXNAME]; /* ユーザ名 */
char MyBirth[MYBIRTH];
};

void main(){


struct user s_user[MAXCASE];
int Manth;
int i, j = 0;


while( j < MAXCASE ){// データ入力


printf("名前:");
get_string(s_user[j].Name, MAXNAME);


if ( s_user[j].Name[0] == '0' ) {// 1文字目が'0'のとき

break;
}


if ( s_user[j].Name[0] == '\0' ) {//改行のみのとき

printf("再入力\n");
continue;
}


printf("生年月日:");


get_string(s_user[j].MyBirth, MYBIRTH);

/* 年の数字チェック */
if(i <= 8 ){
printf("7文字数値が入力されていません。\n");
continue;
}
for (i = 0; i < 4; i++) {//各桁の文字が0~9以外のときエラー
if( s_user[j].MyBirth[i] < '0' || '9' < s_user[j].MyBirth[i] ){
printf("数字以外が入力されました\n");
continue;
}
}

if(s_user[j].MyBirth[4] != '/'){

printf("正しい入力でありません\n");
continue;
}

/* for( i=5; i <7; i++){
if(s_user[j].MyBirth[i] < '0' || '9' < s_user[j].MyBirth[i]){

printf("月の入力が違います\n");
continue;
}
}*/

printf("累計件数 = %d件\n\n", ++j);
}

printf("\n入力データ表示\n");



for (i = 0; i < j; i++) {
printf("%d件目\n", i + 1);
printf("名前 = %s\n", s_user[i].Name);
printf("生年月日 = %s/\n", s_user[j].MyBirth[i]);
}
}

void get_string(char *p_str, int xMaxChar){
int i = 0;
int C;

while ( (C = getchar()) != EOF && C != '\n' ){
if ( i < xMaxChar - 1 ) {
*p_str = C;
p_str++;
i++;
}
}
*p_str = '\0';
}


2倍のポイントを手に入れた! 886ポイント を手に入れた。

Name: box  ..熟練のプログラマー(54,927ポイント)   Date: 2007/03/14(水) 23:27   No:5467     
Title: Re:学校の課題なんですが    

年月チェックの例です。適当に修正しちゃってください。

#include <stdio.h>
#include <stdlib.h>

#define NG (0)
#define OK (!NG)

int is_valid_y_m(char *s);

int main(void)
{
char *str[] = {
"2007/01",
"2007/09",
"2007/10",
"2007/12",
"0001/01",
"1000/01",
"9999/12",
"2007/00",
"2007/13",
"2007/20",
"200a/01",
"2007/0b",
"2007.01",
"2007/010",
"999/12",
"10000/01",
};
int i;

for (i = 0; i < sizeof(str) / sizeof(str[0]); i++) {
printf("'%s' → ", str[i]);
if (is_valid_y_m(str[i]))
printf("%d年%d月\n",
(int) strtol(str[i], NULL, 10),
(int) strtol(str[i]+5, NULL, 10));
else
printf("NG\n");
}
return 0;
}

int is_valid_y_m(char *s)
{
char *p;
int n;

for (p = s, n = 0; *p; p++, n++) {
switch (n) {
case 0: case 1: case 2: case 3:
if (*p < '0' || '9' < *p) return NG;
break;
case 4:
if (*p != '/') return NG;
break;
case 5:
if (*p != '0' && *p != '1') return NG;
break;
case 6:
if (*(p-1) == '0') {
if (*p < '1' || '9' < *p) return NG;
}
else
if (*p < '0' || '2' < *p) return NG;
break;
default:
return NG;
}
}
return OK;
}


500ポイント を落としてしまった。

Name: Yuki  ..上級者(17,479ポイント)   Date: 2007/03/15(木) 08:46   No:5473     
Title: Re:学校の課題なんですが    
>生年月日の再入力のところでcontinue文を使って...

正しい生年月日が入力するまで、再度入力させるループを
新しく追加してみてはいかがでしょう。


>7文字入力してもエラーになってしまいます。57行目で...

ここでiは何に使用していますか?
想像するに、入力された文字数を確認したいのだと思いますが、
入力用のget_string関数内で宣言されているiとmain関数のiは
別のものになります。
get_string関数の戻り値として文字数を返し、main関数のiに
格納してみてはいかがでしょう。

ちなみに、if文の直前にiの値がどうなっているかprintfで
見てみるとわかりやすいですよ。


>月の判定でが00〜12までか判定仕様として...

サンプルです。

char ymd_str[] = "2007/03/15";
char buf[5];
int man;

if(( ymd_str[5] >= '0' && ymd_str[5] <= '9' )&&( ymd_str[6] >= '0' && ymd_str[6] <= '9' )){
printf( "月は数字です。\n" );
sprintf( buf, "%.2s", &ymd_str[5] );
man = atoi( buf );
printf( "man:%d\n", man );
}
else{
printf( "月は数字以外です。\n" );
}




514ポイント を手に入れた。

Name: 素人  ..入門者(4,350ポイント)   Date: 2007/03/15(木) 11:31   No:5494     
Title: Re:学校の課題なんですが    
box様、Yuki様回答ありがとうございます。

atoi関数を使わずに処理しなければいけないので、s_user[j].MyBirth[5]とs_user[j].MyBirth[6]を数字とだけ判定はしたのですが、それからは、MyBirth[5]が0か1か判定し0ならMyBirth[6]が1〜9かMyBirth[5]が1ならMyBirth[6]が0〜2かで判定しなければいけないのでしょか。

>get_string関数の戻り値として文字数を返し、main関数のiに格納してみてはいかがでしょう。

どのようにiに格納すればよいのでしょか。文字数は、get_stringのMYBIRTHには入っていないのですか。関数の仕組みがよくわかっていないもので教えていただけないでしょか。


<pre>#include <stdio.h>
#include <stdlib.h>

#define MAXNAME 11 /* 名前の最大入力文字数 10文字 + '\0' */
#define MYBIRTH 9 /* 生年月日の年の形*/
#define MAXCASE 10 /* 最大ユーザー件数 */

void get_string(char *p_str, int xMaxChar);

struct user{
char Name[MAXNAME]; /* ユーザ名 */
char MyBirth[MYBIRTH];
};

void main(){


struct user s_user[MAXCASE];
int Manth;
int j = 0;
int i;


while( j < MAXCASE ){// データ入力


printf("名前:");
get_string(s_user[j].Name, MAXNAME);


if ( s_user[j].Name[0] == '0' ) {// 1文字目が'0'のとき

break;
}


if ( s_user[j].Name[0] == '\0' ) {//改行のみのとき

printf("再入力\n");
continue;
}

printf("i値:%d\n",i);
printf("生年月日:");

for(;;){
get_string(s_user[j].MyBirth, sizeof(s_user[j].MyBirth));

if(i <= 8 ){

printf("7文字数値が入力されていません。\n");
continue;

}
for (i = 0; i < 4; i++) {//各桁の文字が0~9以外のときエラー
if( s_user[j].MyBirth[i] < '0' || '9' < s_user[j].MyBirth[i] ){
printf("数字以外が入力されました\n");
continue;
}
}

if(s_user[j].MyBirth[4] != '/'){

printf("正しい入力でありません\n");
continue;
}

if(( s_user[j].MyBirth[5] >= '0' && s_user[j].MyBirth[5] <= '9' )&&( s_user[j].MyBirth[6] >= '0' && s_user[j].MyBirth[6] <= '9' )){

printf("月の入力正解\n");

}

else{
printf("月の入力が違います\n");
continue;
}
break;
}

printf("累計件数 = %d件\n\n", ++j);
}

printf("\n入力データ表示\n");



for (i = 0; i < j; i++) {
printf("%d件目\n", i + 1);
printf("名前 = %s\n", s_user[i].Name);
printf("生年月日 = %s/\n", s_user[j].MyBirth[i]);
}
}

void get_string(char *p_str, int xMaxChar){
int i = 0;
int C;

while ( (C = getchar()) != EOF && C != '\n' ){
if ( i < xMaxChar - 1 ) {//配列の(xMaxChar -1)文字まで有効
*p_str = C;
i++;
p_str++;
}
}
*p_str = '\0';
}


1,317ポイント を手に入れた。

Name: box  ..熟練のプログラマー(55,268ポイント)   Date: 2007/03/15(木) 12:47   No:5501     
Title: Re:学校の課題なんですが    

> atoi関数を使わずに処理しなければいけない

atoi関数もstrtol関数も使っていないサンプルです。
is_valid_y_m関数では、戻り値がゼロ以外の場合に限り、
第2引数(年)と第3引数(月)の内容が有効です。


#include <stdio.h>

#define NG (0)
#define OK (!NG)

int is_valid_y_m(char *s, int *y, int *m);

int main(void)
{
char *str[] = {
"2007/01",
"2007/09",
"2007/10",
"2007/12",
"0001/01",
"1000/01",
"9999/12",
"2007/00",
"2007/13",
"2007/20",
"200a/01",
"2007/0b",
"2007.01",
"2007/010",
"999/12",
"10000/01",
};
int year, month, i;

for (i = 0; i < sizeof(str) / sizeof(str[0]); i++) {
printf("'%s' → ", str[i]);
if (is_valid_y_m(str[i], &year, &month))
printf("%d年%d月\n", year, month);
else
printf("NG\n");
}
return 0;
}

int is_valid_y_m(char *s, int *y, int *m)
{
char *p;
int n;

for (p = s, *y = *m = n = 0; *p; p++, n++) {
switch (n) {
case 0: case 1: case 2: case 3:
if (*p < '0' || '9' < *p) return NG;
*y = *y * 10 + (*p - '0');
break;
case 4:
if (*p != '/') return NG;
break;
case 5:
if (*p != '0' && *p != '1') return NG;
*m = *m * 10 + (*p - '0');
break;
case 6:
if (*(p-1) == '0') {
if (*p < '1' || '9' < *p) return NG;
}
else
if (*p < '0' || '2' < *p) return NG;
*m = *m * 10 + (*p - '0');
break;
default:
return NG;
}
}
return OK;
}


341ポイント を手に入れた。

Name: Yuki  ..上級者(17,815ポイント)   Date: 2007/03/15(木) 13:08   No:5502     
Title: Re:学校の課題なんですが    
>atoi関数を使わずに処理しなければいけないので...

atoi関数を使わないのであれば、それが1番よさそうですね。



>どのようにiに格納すればよいのでしょか。文字数は、get_stringのMYBIRTHには入っていないのですか。関数の仕組みがよくわかっていないもので教えていただけないでしょか。

get_string関数が終了する直前に変数iをprintfしてみてください。
【入力された文字数】が入っていると思います。

この数値を利用してmain関数のif(i <= 8 )をしたいのだと思うのですが、
main関数とget_string関数の変数iは同じ名前でも、異なる変数ですので、
main関数のiには【入力された文字数】はありません。


これを解決するために、get_string関数の型を現在voidとなっているものを
intに変更し、関数が終わる直前にreturn i;を追加してください。

次に、main関数でget_string関数を呼び出す際に、戻り値をiで受けてください。
i = get_string(s_user[j].MyBirth, sizeof(s_user[j].MyBirth));

これで関数間の値の受け渡しができます。


ちなみに、MYBIRTHは【最大入力文字数】なので、【入力された文字数】とは異なります。



336ポイント を手に入れた。

Name: 素人  ..初心者(5,520ポイント)   Date: 2007/03/17(土) 13:10   No:5718     
Title: Re:学校の課題なんですが    
box様、Yuki様回答ありがとうございます。

組み直しなのですが、7文字以上かを判定するところで7文字入力しているのにエラーになってしまいます。
iの値も確認したのですが7が表示されるのですが何故エラーになってしまうのでしょか。
>【最大入力文字数】なので、【入力された文字数】
が違うのでしょうか。


#include <stdio.h>
#include <stdlib.h>

#define MAXNAME 11 /* 名前の最大入力文字数 10文字 + '\0' */
#define MYBIRTH 9 /* 生年月日の年の形*/
#define MAXCASE 10 /* 最大ユーザー件数 */

int get_string(char *p_str, int xMaxChar);

struct user{
char Name[MAXNAME]; /* ユーザ名 */
char MyBirth[MYBIRTH];
};

void main(){


struct user s_user[MAXCASE];
int Manth;
int j = 0;
int i;


while( j < MAXCASE ){// データ入力


printf("名前:");
get_string(s_user[j].Name, MAXNAME);


if ( s_user[j].Name[0] == '0' ) {// 1文字目が'0'のとき

break;
}


if ( s_user[j].Name[0] == '\0' ) {//改行のみのとき

printf("再入力\n");
continue;
}


printf("生年月日:");

for(;;){
//get_string(s_user[j].MyBirth, MYBIRTH);
i = get_string(s_user[j].MyBirth, sizeof(s_user[j].MyBirth)-1);
printf("i値:%d\n",i);
if(i <= 8 ){//8文字以上の入力の場合エラー

printf("7文字以上が入力されました。\n");
continue;

}
for (i = 0; i < 4; i++) {//各桁の文字が0~9以外のときエラー
if( s_user[j].MyBirth[i] < '0' || '9' < s_user[j].MyBirth[i] ){
printf("数字以外が入力されました\n");
continue;
}
}

if(s_user[j].MyBirth[4] != '/'){//4文字目が/じゃない

printf("正しい入力でありません\n");
continue;
}

if( s_user[j].MyBirth[5] >= '0' && s_user[j].MyBirth[5] <= '9' ){//5桁目の文字が0~9である
if(s_user[j].MyBirth[5] == '0'){//5桁目が0の時
if( s_user[j].MyBirth[6] >= '1' && s_user[j].MyBirth[6] <= '9' ){//6桁目は1〜9である
break;
}
}

else if(s_user[j].MyBirth[5] == '1'){//5桁目が1の時
if( s_user[j].MyBirth[6] >= '0' && s_user[j].MyBirth[6] <= '2' ){//6桁目は0〜2でる
break;
}
}
}

else{
printf("月の入力が違います\n");
continue;
}

}

printf("累計件数 = %d件\n\n", ++j);
}

printf("\n入力データ表示\n");



for (i = 0; i < j; i++) {
printf("%d件目\n", i + 1);
printf("名前 = %s\n", s_user[i].Name);
printf("生年月日 = %s/\n", s_user[j].MyBirth[i]);
}
}

int get_string(char *p_str, int xMaxChar){
int i = 0;
int C;

while ( (C = getchar()) != EOF && C != '\n' ){
if ( i < xMaxChar - 1 ) {//配列の(xMaxChar -1)文字まで有効
*p_str = C;
i++;
p_str++;
}
}
*p_str = '\0';
return i;
}


1,170ポイント を手に入れた。

Name: box  ..熟練のプログラマー(55,863ポイント)   Date: 2007/03/17(土) 13:26   No:5721     
Title: Re:学校の課題なんですが    

> 組み直しなのですが、7文字以上かを判定するところで7文字入力しているのにエラーになってしまいます。
> iの値も確認したのですが7が表示されるのですが何故エラーになってしまうのでしょか。

中身のロジックはほとんど見ていませんので、気がついたところだけ。

> if(i <= 8 ){//8文字以上の入力の場合エラー
>
> printf("7文字以上が入力されました。\n");

ここの記述は、
 ・if文の判定条件
 ・コメントの内容
 ・printf関数中のメッセージ
のお互いが食い違っています。そろえてください。


100ポイント を手に入れた。

Name: 素人  ..初心者(6,246ポイント)   Date: 2007/03/17(土) 15:12   No:5726     
Title: Re:学校の課題なんですが    
box様すいませんでした。直しました。

#include <stdio.h>
#include <stdlib.h>

#define MAXNAME 11 /* 名前の最大入力文字数 10文字 + '\0' */
#define MYBIRTH 9 /* 生年月日の年の形*/
#define MAXCASE 10 /* 最大ユーザー件数 */

int get_string(char *p_str, int xMaxChar);

struct user{
char Name[MAXNAME]; /* ユーザ名 */
char MyBirth[MYBIRTH];
};

void main(){


struct user s_user[MAXCASE];
int Manth;
int j = 0;
int i;


while( j < MAXCASE ){// データ入力


printf("名前:");
get_string(s_user[j].Name, MAXNAME);


if ( s_user[j].Name[0] == '0' ) {// 1文字目が'0'のとき

break;
}


if ( s_user[j].Name[0] == '\0' ) {//改行のみのとき

printf("再入力\n");
continue;
}


printf("生年月日:");

for(;;){
//get_string(s_user[j].MyBirth, MYBIRTH);
i = get_string(s_user[j].MyBirth, sizeof(s_user[j].MyBirth)-1);
printf("i値:%d\n",i);
if(i < 8 ){//7文字以上の入力の場合エラー

printf("7文字以上が入力されました。\n");
continue;

}
for (i = 0; i < 4; i++) {//各桁の文字が0~9以外のときエラー
if( s_user[j].MyBirth[i] < '0' || '9' < s_user[j].MyBirth[i] ){
printf("数字以外が入力されました\n");
continue;
}
}

if(s_user[j].MyBirth[4] != '/'){//4文字目が/じゃない

printf("正しい入力でありません\n");
continue;
}

if( s_user[j].MyBirth[5] >= '0' && s_user[j].MyBirth[5] <= '9' ){//5桁目の文字が0~9である
if(s_user[j].MyBirth[5] == '0'){//5桁目が0の時
if( s_user[j].MyBirth[6] >= '1' && s_user[j].MyBirth[6] <= '9' ){//6桁目は1〜9である
break;
}
}

else if(s_user[j].MyBirth[5] == '1'){//5桁目が1の時
if( s_user[j].MyBirth[6] >= '0' && s_user[j].MyBirth[6] <= '2' ){//6桁目は0〜2でる
break;
}
}
}

else{
printf("月の入力が違います\n");
continue;
}

}

printf("累計件数 = %d件\n\n", ++j);
}

printf("\n入力データ表示\n");



for (i = 0; i < j; i++) {
printf("%d件目\n", i + 1);
printf("名前 = %s\n", s_user[i].Name);
printf("生年月日 = %s/\n", s_user[j].MyBirth[i]);
}
}

int get_string(char *p_str, int xMaxChar){
int i = 0;
int C;

while ( (C = getchar()) != EOF && C != '\n' ){
if ( i < xMaxChar - 1 ) {//配列の(xMaxChar -1)文字まで有効
*p_str = C;
i++;
p_str++;
}
}
*p_str = '\0';
return i;
}


726ポイント を手に入れた。

Name: Yuki  ..上級者(18,060ポイント)   Date: 2007/03/19(月) 11:18   No:5798     
Title: Re:学校の課題なんですが    
> printf("i値:%d\n",i);
> if(i < 8 ){//7文字以上の入力の場合エラー
> printf("7文字以上が入力されました。\n");

このif文で真になるケースはiが8より小さい場合ですよね。
なのにメッセージが「7文字以上が入力されました。」はおかしくないですか?



また生年月日に「2007/03/19」を入力したい場合、

> //get_string(s_user[j].MyBirth, MYBIRTH);
> i = get_string(s_user[j].MyBirth, sizeof(s_user[j].MyBirth)-1);

> while ( (C = getchar()) != EOF && C != '\n' ){
> if ( i < xMaxChar - 1 ) {//配列の(xMaxChar -1)文字まで有効

だと7文字までしか受け付けてもらえないようなのですが・・・。
プログラムの仕様を見直す必要があると思います。


83ポイント を手に入れた。

Name: 素人  ..初心者(6,268ポイント)   Date: 2007/03/19(月) 13:31   No:5811 解決!     
Title: Re:学校の課題なんですが    
Yuki様回答ありがとうございます。
メッセージはおかしかったので直しました。
プログラムは年と月だけなので大丈夫です。
無事にできました。
色々教えてくださって、ありがとうございました。


22ポイント を手に入れた。



Name: parapara  ..かけだし(1,370ポイント)   Date: 2007/03/17(土) 16:23   No:5728       
Title: 構造体のメンバのメモリ配置について    
独学で勉強してる者ですが、又分からない事が出てきており、困っております。

下記の状態(ソースに質問書いてある)なんですが,ご助言お願いします。
#include<stdio.h> //共用体で86系レジスタを表現する
#include<stdlib.h>
#include<string.h>
struct hregs{
unsigned char al; //ここでalとahは隣接することを宣言してるみたいなんですが、
unsigned char ah; //構造体のメンバ同士って必ず隣接する物なんでしょうか?
};
typedef union regs{
struct hregs h;
unsigned short int ax;
}Regs;
int main(void){
Regs reg;
reg.h.ah=0x1A;
reg.h.al=0x2B;
printf("ah:%X\n",reg.h.ah);
printf("al:%X\n",reg.h.al);
printf("ax:%hX\n",reg.ax);

return(EXIT_SUCCESS);
}


264ポイント を手に入れた。


Name: box  ..熟練のプログラマー(56,216ポイント)   Date: 2007/03/17(土) 17:01   No:5731     
Title: Re:構造体のメンバのメモリ配置について    

> unsigned char al; //ここでalとahは隣接することを宣言してるみたいなんですが、
> unsigned char ah; //構造体のメンバ同士って必ず隣接する物なんでしょうか?

この場合は、すぐ隣同士のアドレスに配置されます。
一方、

#include <stdio.h>

typedef struct __STRUCT {
char c;
int n;
} STRUCT;

int main(void)
{
STRUCT s;

printf("s.cのアドレス:%p\n", &s.c);
printf("s.nのアドレス:%p\n", &s.n);
return 0;
}

このプログラムを実行すると、結果は例えば次のようになります。

【実行結果の例】
s.cのアドレス:0012FF84
s.nのアドレス:0012FF88

s.nのアドレスは、0012FF85であってもよさそうに思えますが、
実際はそうなりません。
これは、メンバー配置の際に「境界合わせ(alignment)」を行なっているからです。
私のところでは、メンバーの開始アドレスが必ず4の倍数になるように
境界を調整しています。「4バイトバウンダリー(4 bytes boundary)」
あるいは「ワードバウンダリー(word boundary)」といいます。
この例では、0012FF85〜0012FF87の3バイトは、未使用のままとなります。
このような、未使用領域のことを「パディング(padding)」といいます。
CPUによっては、4バイトではなく8バイトバウンダリー(ダブルワードバウンダリー)の
場合もあります。

なお、s.cとs.nとの間に別のメンバーの領域があるわけではないので、
隣接しているといえなくもないです。
「隣接」をどう定義するかによると思います。



90ポイント を手に入れた。

Name: parapara  ..かけだし(1,960ポイント)   Date: 2007/03/17(土) 19:38   No:5736     
Title: Re:構造体のメンバのメモリ配置について    
1バイトと1バイトだと、境界越えしないために隙間なく隣接する。
1バイトと4バイトだと境界越えしてしまう為、
次の記憶領域に配置されパディングが発生するという事ですね?
毎回ありがとうございます。疑問が氷解しスッキリしました。

一応まだ質問にしときます。これで合ってるでしょうか?