繰り返し処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
wwi

繰り返し処理について

#1

投稿記事 by wwi » 6年前

現在以下のようなプログラムを作っています
① 3人の名前と年齢をキーボードから入力し、構造体を使って記憶させる。
 ※年齢は0から100までの整数を入力範囲とし、それ以外は範囲外とみなし再入力をさせる旨のメッセージを表示し再入力を待つ。
② プログラムが「誰の年齢を表示させたいか」を聞いてくるので、キーボードから名前を入力する。
③ 入力した名前の年齢が表示され、プログラム終了。
 ※記憶されていない名前が入力された場合は「該当者がいません」と表示しプログラム終了。
自分一人ではわからない部分があります。それは、このプログラムに①での3人の名前を入力するときに『同一の人物名を入力した際に「同一名の人物名が入力されています』と表示させ、再入力を待つ」という処理を付け加えたいのですが、どこになにを付け加えたらいいのかわかりません。

どなたかご教授いただけると嬉しいです。
環境はOS:windows7,コンパイラはVC++です。
C言語は初心者です。よろしくおねがいします

コード:

 
#include <stdio.h>
#include <string.h>

#define N_PERSON 3

struct person {
	char name[20];
	int age;
};

int read_age()
{
	char buf[256];
	int age;
	int is_number;
	int i;
	do{
		scanf("%s", buf);

		is_number = 1;
		for(i = 0; i < strlen(buf); i++) {
			if(!isdigit(buf[i])) {
				is_number = 0;
				age = -1;
				break;
				
			}
			
		}

		if(is_number == 1) {

				age = atoi(buf);
			
		}
		if(age < 0 || age > 100) {
			printf("1から100までの範囲で入力せよ\n");
			
		}
		 } while (age < 0 || age > 100);

		return age;
}


int main()
{
	int i;
	struct person persons[N_PERSON];
	char buf[256];
	int found;


		printf("3人の名前と年齢を教えてください\n");
	for(i = 0; i < N_PERSON; i++) {
		printf("%d人目\n", i + 1);
		scanf("%s", persons[i].name);
		persons[i].age = read_age();
	}



			printf("だれの年齢を表示するか名前を入力してください\n");
			scanf("%s", buf);

			found = -1;
			for(i = 0; i < N_PERSON; i++) {
				if(strcmp(buf, persons[i].name) == 0) {
					found = i;
					break;
				}
			}

			if(found == -1) {

					printf("該当者がいませんでした\n");
				exit(0);
			}
 else {

		 printf("%sは%d歳です。\n", persons[i].name, persons[i].age);
	 
 }
 
}
 

初級者
記事: 200
登録日時: 10年前

Re: 繰り返し処理について

#2

投稿記事 by 初級者 » 6年前

その処理をコンピューターではなく
手で行なうとしたら、どういう風に
しますか?

また、提示のコードは字下げが
乱れている箇所があり、いささか
読みづらいです。
何とかする方がいいと思います。

wwi

Re: 繰り返し処理について

#3

投稿記事 by wwi » 6年前

解答ありがとうございます。
「手で行う」というのは自分自身の手で行うということでしょうか?もし解釈が間違っていたら申し訳ありません。
自分の手で行う場合、まず、①において記憶した文字(名前)と、同じく①において2人目以降で入力された名前を比較し、名前が一致していた場合、「同一名の人物名が入力されています』と表示させ、再入力を待つ」という処理を行います。

アバター
みけCAT
記事: 6351
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: 繰り返し処理について

#4

投稿記事 by みけCAT » 6年前

wwi さんが書きました:「手で行う」というのは自分自身の手で行うということでしょうか?もし解釈が間違っていたら申し訳ありません。
自分の手で行う場合、まず、①において記憶した文字(名前)と、同じく①において2人目以降で入力された名前を比較し、名前が一致していた場合、「同一名の人物名が入力されています』と表示させ、再入力を待つ」という処理を行います。
妥当ですね。
これをプログラムにしましょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

wwi

Re: 繰り返し処理について

#5

投稿記事 by wwi » 6年前

試行錯誤しているのですが上手にできません。strcmpを使って記憶した文字と入力された文字を比較するのは理解できるのですが、どこに何を入れたらいいのか正直手も足も出ません。
サンプルを示していただけると嬉しいです。

かずま

Re: 繰り返し処理について

#6

投稿記事 by かずま » 6年前

wwi さんが書きました:サンプルを示していただけると嬉しいです。
read_name() という関数にしてみました。

コード:

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

#define N_PERSON 3

struct person {
    char name[20];
    int age;
};

int read_age(void)
{
    char buf[256], c;
    int age;

    for (;;) {
        scanf("%255s", buf);
        if (sscanf(buf, "%d%c", &age, &c) == 1 && age >= 1 && age <= 100)
            return age;
        puts("1から100までの範囲で入力せよ");
    }
}

void read_name(struct person *persons, int n)
{
    int i;

    for (;;) {
        scanf("%19s", persons[n].name);
        for (i = 0; i < n; i++)
            if (strcmp(persons[i].name, persons[n].name) == 0) break;
        if (i == n) return;
        puts("その名前は既にあります。違う名前をお願いします");
    }
}

int main(void)
{
    int i;
    struct person persons[N_PERSON];
    char buf[256];

    puts("3人の名前と年齢を教えてください");
    for (i = 0; i < N_PERSON; i++) {
        printf("%d人目\n", i + 1);
        read_name(persons, i);
        persons[i].age = read_age();
    }
    puts("だれの年齢を表示するか名前を入力してください");
    scanf("%255s", buf);
    for (i = 0; i < N_PERSON; i++)
        if (strcmp(buf, persons[i].name) == 0) break;
    if (i == N_PERSON)
        puts("該当者がいませんでした");
    else
        printf("%sは%d歳です。\n", persons[i].name, persons[i].age);
    return 0;
}

wwi

Re: 繰り返し処理について

#7

投稿記事 by wwi » 6年前

ありがとうございました。名前の入力を処理する関数を別に作ればよかったんですね。
とても勉強になりました

かずま

Re: 繰り返し処理について

#8

投稿記事 by かずま » 6年前

wwi さんが書きました:名前の入力を処理する関数を別に作ればよかったんですね。
関数を別に作るかどうかは本質的な問題ではありません。 やりたいことは、
(1) 名前を読む
(2) その名前が既に存在するかどうか調べる
(3) 存在していれば、メッセージを表示し、(1) に戻る

関数を別に作らなくても次のように書けます。

コード:

#include <stdio.h>
#include <string.h>

#define N_PERSON 3

struct person {
    char name[20];
    int age;
};

int read_age(void)
{
    char buf[256], c;
    int age;

    for (;;) {
        scanf("%255s", buf);
        if (sscanf(buf, "%d%c", &age, &c) == 1 && age >= 1 && age <= 100)
            return age;
        puts("1から100までの範囲で入力せよ");
    }
}

int main(void)
{
    int i, j;
    struct person persons[N_PERSON];
    char buf[256];

    printf("%d人の名前と年齢を教えてください\n", N_PERSON);
    for (i = 0; i < N_PERSON; i++) {
        printf("%d人目\n", i + 1);
        for (;;) {
            scanf("%19s", persons[i].name);
            for (j = 0; j < i; j++)
                if (strcmp(persons[j].name, persons[i].name) == 0) break;
            if (j == i) break;
            puts("その名前は既にあります。違う名前をお願いします");
        }
        persons[i].age = read_age();
    }
    puts("だれの年齢を表示するか名前を入力してください");
    scanf("%255s", buf);
    for (i = 0; i < N_PERSON; i++)
        if (strcmp(buf, persons[i].name) == 0) break;
    if (i == N_PERSON)
        puts("該当者がいませんでした");
    else
        printf("%sは%d歳です。\n", persons[i].name, persons[i].age);
    return 0;
}
read_age() も関数にせずに書けます。そうすると、プログラム全体の
行数も減ります。でも、main() がデカくなります。
機能ごとに関数に分けたほうが、見やすくなるということです。

ところで、read_age() が wwiさんのものとは違う書き方をしていますが、
それは気になりませんか?

wwi

Re: 繰り返し処理について

#9

投稿記事 by wwi » 6年前

かずまさん
ありがとうございます。確かに書き方はいろいろあるということですよね。勉強します
read_age()の書き方ですが、if分の中身を理解しながら参考にさせて頂いています。いまのところ自分なりに理解はできていると思います。

閉鎖

“C言語何でも質問掲示板” へ戻る