ページ 11

構造体の課題

Posted: 2008年10月21日(火) 12:52
by sg
「名前」「住所」「生年月日」「電話」の四つの項目を持った構造体を定義し、
それぞれの項目にデータを入力しなさい。

また、最大文字数は、名前全角10文字、住所全角64文字、生年月日半角10文字、電話半角16文字とする。

※名前は必ず必要な項目である為、必須入力とする。
※生年月日は半角スラッシュ「/」区切りで、半角数字と半角スラッシュ以外の文字はエラーとする。
※生年月日は、日付の妥当性は考慮しない。
※電話は半角ハイフン「-」区切りで、半角数字と半角ハイフン以外の文字はエラーとする。

Re:構造体の課題

Posted: 2008年10月21日(火) 12:56
by バグ
この課題の何がわからないのでしょうか?

Re:構造体の課題

Posted: 2008年10月21日(火) 13:07
by sg
説明不足でした、ごめんなさい。
※生年月日は半角スラッシュ「/」区切りで、半角数字と半角スラッシュ以外の文字はエラーとする。
※電話は半角ハイフン「-」区切りで、半角数字と半角ハイフン以外の文字はエラーとする。
この二つができないです。

Re:構造体の課題

Posted: 2008年10月21日(火) 14:23
by 管理人
まず少しずつ作ってみましょう。
では、

1:入力は改行で区切るとして、改行が行われるまで文字列に入力データを入れるだけの関数を作って下さい

これが出来たら、今度は

2:その関数に文字列の最大数も渡してやり、オーバーフローになるとエラーになる関数にして下さい。

そして最後に更に

3:そのデータの中に0~9または/以外が入っていたらエラーになる関数にして下さい。

こうしていけば解るはずだと思います。
下に参考に答えを書きますので、最初はこれを見ないで自分でやってみてから答え合わせしてみて下さい。
電話番号もこれと同じ考え方で出来ます。



/* 1の解答例* /

#include <stdio.h>

int get_str(char str[/url]){
	int c,i;
	i=0;
	while((c=getchar())!='\n'){//改行が来るまでループ
		str=c;//文字を格納し
		i++;//加算
	}
	str='\0';//最後に終端記号を入れる
	return 0;//返り値を返す
}

void main(){ 
	char str0[11];//文字列用意
	get_str(str0);//関数を呼ぶ
	printf("%s",str0);
}

実行結果例

1984/09/26
1984/09/26

/* 2の解答例* /

#include <stdio.h>

#define STR0MAX 10 //文字列の長さ(実際の文字の長さで終端記号は含まない)

int get_str(char str[/url], int n){
	int c,ret=0,i;
	i=0;
	while((c=getchar())!='\n'){//改行が来るまでループ
		//オーバーフローしているなら
		if(i>=n){
			ret = -1;//エラー
		}
		else{//そうじゃなかったら
			str=c;//文字を格納し
			i++;//加算
		}
	}
	str='\0';//最後に終端記号を入れる
	return ret;//返り値を返す
}

void main(){ 
	char str0[STR0MAX+1];//文字列用意
	if(get_str(str0,STR0MAX)==-1)//関数を呼ぶ
		printf("エラー\n");
	else
		printf("%s",str0);
}

実行結果例

1984/09/2666
エラー

/* 3の解答例* /

#include <stdio.h>

#define STR0MAX 10 //文字列の長さ(実際の文字の長さで終端記号は含まない)

int get_str(char str[/url], int n){
	int c,ret=0,i;
	i=0;
	while((c=getchar())!='\n'){//改行が来るまでループ
		//オーバーフローしているか、0~9または/以外なら
		if(i>=n || !(c>='0' && c<='9' || c=='/')){
			ret = -1;//エラー
		}
		else{//そうじゃなかったら
			str=c;//文字を格納し
			i++;//加算
		}
	}
	str='\0';//最後に終端記号を入れる
	return ret;//返り値を返す
}

void main(){ 
	char str0[STR0MAX+1];//文字列用意
	if(get_str(str0,STR0MAX)==-1)//関数を呼ぶ
		printf("エラー\n");
	else
		printf("%s",str0);
}

実行結果例

1984/09-26
エラー

Re:構造体の課題

Posted: 2008年10月21日(火) 14:33
by sg
さすが管理人ですね、とても役に立ちました。
3qです。

Re:構造体の課題

Posted: 2008年10月21日(火) 14:44
by バグ
環境が不明なので、推測でしかないのですが…
入力にはscanfを使用するものと考えて、単純に入力を抑止するだけならば…

scanf("%[0123456789[/url]", buf);

こんな書き方もできますが、『エラーとする』とありますので、判定のする必要があるかな?
int IsBirthday(char* pbuf)
{
	for (unsigned int i = 0; i < strlen(pbuf); ++i)
	{
		if (isdigit((int)(*(pbuf + i))) == 0)
		{
			continue;
		}
		else if (*(pbuf + i) != '/')
		{
			return 0;
		}
	}

	return 1;
}
関数化してみました。引数の文字列に数字とスラッシュ以外が見つかると0を返し、見つからなかった場合は1を返します。コンパイルしてないので、エラーが出たらごめんなさい。
電話番号もほぼ同じ方法で判定できますんで、がんばってください。

Re:構造体の課題

Posted: 2008年10月21日(火) 15:08
by たかぎ
> 半角数字と半角スラッシュ以外の文字はエラーとする。

なので...
char 生年月日[10+1+1];
fgets(生年月日, sizeof(生年月日), stdin);
if (生年月日[10] != '\n' || strspn(生年月日, "0123456789/") != 10)
{
  // エラー処理
}
でよいのでは?

Re:構造体の課題

Posted: 2008年10月21日(火) 16:57
by lbfuvab
ツンデレサンプルです。
main関数は用意してません。
色々間違いがあるかもなのでその辺は許してください
#include<stdio.h>
#include<conio.h>

typedef struct{
    char name[21];
    char address[129];
    char birthday[11];
    char phone[16];
}DATA,*LPDATA;

void MyGets(char *buf,int len);       //文字列の入力
int  JudgeStr(char *str,char *JudgeStr);                //JudgeStr内の文字のみの文字列か
void MyGetData(LPDATA lpData);              //データの入力(ツンデレ)

int main(){
    DATA data;
    
    MyGetData(&data);
    getch();
    return 0;
}

void MyGets(char *buf,int len){  //lenはNULL文字含む文字数
    int ch;
    
    while(--len){
        ch=getchar();
        if(ch==EOF || ch=='\n')
            break;
        else
            *buf++=(char)ch;
    }
    *buf='\0';
}

int  JudgeStr(char *str,char *JudgeStr){
    int i;
    while(*str){
        for(i=0;JudgeStr;i++)
            if(JudgeStr == *str)
                break;
        if(!JudgeStr)
            return 0;
        str++;
    }
    return 1;
}

void MyGetData(LPDATA lpData){
    puts("名前を入力しなさいよっ、ふん");
    while(1){
        MyGets(lpData->name,sizeof(lpData->name));
        if(!JudgeStr(lpData->name," \t\n\r\f\v"))
            break;
        puts("ちゃんと入力しなさいよ!!\n"
             "……べ、別に長引いたって嬉しくないんだからねっ!");
    }
    puts("住所を入力しなさい!!");
    MyGets(lpData->address,sizeof(lpData->address));
    puts("電話番号を入力しなさい!!・・・あ、あなたに電話したいなんて言ってないわよ!?");
    while(1){
        MyGets(lpData->phone,sizeof(lpData->phone));
        if(JudgeStr(lpData->phone,"0123456789-"))
            break;
        puts("ちゃんと入力しなさいよ!!\n"
             "べ、別に長引いたって嬉しくなんてないんだからねっ……");
    }
    puts("生年月日を教えなさ・・・っ入力しなさい!");
    while(1){
        MyGets(lpData->birthday,sizeof(lpData->birthday));
        if(JudgeStr(lpData->birthday,"0123456789/"))
            break;
        puts("ちゃんと入力しなさいよ!!\n"
             "べ、別に長引いたって嬉しくなんてないんだからねっ……");
    }
    puts("終わりよ。\n"
         "ま、また訊いて欲しければ訊いてやってもいいわよ・・・");
}

Re:構造体の課題

Posted: 2008年10月21日(火) 17:59
by sg
みんな!ありがとう!