🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

4回答

1302閲覧

C言語でmain関数から部品化した関数の処理が終わるとmain関数へと戻る仕組みにしたい。

wesker.alice

総合スコア45

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

0クリップ

投稿2021/01/11 14:47

前提・実現したいこと

前提
c言語を使い、職員の新規登録をしてログインする仕組みを作っています。
作り始めたばかりなのですが、他の部品からmain関数に戻る仕組みにもつながるので今解決しておきたいと思い質問させていただきました。

実現したいこと
main関数からstaff関数を呼び出し、更にtouroku関数を呼び出して仕組みを作っていますが、関数の処理が終わった後に設定したメニュー画面に戻り、戻るを選択するとmain画面に戻る仕組みを作りたいのですが、うまくいきません。

発生している問題・エラーメッセージ

該当のソースコード

main.c

main

1 2#include <stdio.h> 3#include <string.h> 4#include "main.h" 5#include "staff.h" 6#include "common.h" 7 8 9int main(void){ 10 int loop = TRUE; 11 char work[ 128 ]; 12 13 while(loop){ 14 printf( "\n ログイン画面" ); 15 printf( "\n 処理を選択してください" ); 16 printf( "\n 1:職員新規登録" ); 17 printf( "\n 2:ログイン" ); 18 printf( "\n E:終了" ); 19 printf( "\n ? " ); 20 21 /* 処理区分入力 */ 22 work[ 0 ] = '\0'; 23 scanf( "%s", work ); 24 25 /* 入力桁数チェック -> 1 以外 ? */ 26 if( strlen( work ) != 1 ) { 27 printf( "¥n 入力ミスです" ); 28 continue; 29 } 30 31 switch( work[ 0 ] ) { 32 case '1': /* 職員新規登録 */ 33 staff(); 34 break; 35 case '2': /* ログイン */ 36 //login( ); 37 break; 38 case 'e': /* 終了 */ 39 case 'E': 40 loop = FALSE; 41 break; 42 default: 43 printf( "¥n 入力ミスです" ); 44 break; 45 } 46 47 return 0; 48} 49} 50

main,h

main

1int main(void);

staff.c

#include <stdio.h> #include<string.h> #include"staff.h" #include "common.h" #include"otameshi.h" int staff_new(){ int loop = TRUE; char work[ 128 ]; while(loop){ printf( "\n ■1.職員新規登録メニュー■" ); printf( "\n 処理を選択してください" ); printf( "\n 1:職員新規登録" ); printf( "\n 2:お試しデータ登録" ); printf( "\n E:戻る" ); printf( "\n ? " ); /* 処理区分入力 */ work[ 0 ] = '\0'; scanf( "%s", work ); /* 入力桁数チェック -> 1 以外 ? */ if( strlen( work ) != 1 ) { printf( "¥n 入力ミスです" ); continue; } switch( work[ 0 ] ) { case '1': /* 職員新規登録 */ //otameshi(); break; case '2': /*お試しデータ登録 */ otameshi(); break; case 'e': /* 戻る */ case 'E': loop = FALSE; break; default: printf( "¥n 入力ミスです" ); break; } return OK; } return 0; }

staff.h

int staff(); int otameshi();

otameshi.c

#include <stdio.h> #include<string.h> #include"staff.h" #include "common.h" #include"otameshi.h" int otameshi() { FILE * fp = NULL; int loop = TRUE; char work[ 128 ]; while(loop){ printf("お試しデータをバイナリファイルに書き込みますか?( y / n )\n"); /* 処理区分入力 */ work[ 0 ] = '\0'; scanf( "%s", work ); /* 入力桁数チェック -> 1 以外 ? */ if( strlen( work ) != 1 ) { printf( "¥n 入力ミスです" ); continue; } switch( work[ 0 ] ) { case 'y': /* 職員新規登録 */ case 'Y': // セーブデータをバイナリの書き込みでオープン fp = fopen( "staff.bin", "wb"); if(fp == NULL){ printf("ファイルが開けませんでした\n"); return 1; } STAFF staff[]= { //職員コード 職員パスワード {0001, 1234}, {0002, 2345}, {0003, 1234}, }; // バイナリファイルに書き込み fwrite(staff, sizeof(STAFF), sizeof(staff) / sizeof(staff[0]), fp); printf("ファイルに保存しました。\n"); fclose(fp); loop = FALSE; break; case 'n': /* お試しデータの登録をしない場合 */ case 'N': printf(" お試しデータの登録は行いませんでした。\n"); loop = FALSE; break; case 'e': /* 戻る */ case 'E': break; default: printf("文字入力ミスです。\n"); break; } } return OK; }

otameshi.h

int otameshi();

common.h

#include <stdio.h> /* 計測データ表ファイル名 */ #define TRUE 1 //* 真 #define FALSE 0 //* 偽 #define OK 0 //* 正常 #define CANCEL 1 //* 処理中止 #define NG -1 //* 異常 /*職員テーブル*/ typedef struct staff_tbl{ int code; // 職員コード int pass; // 職員パスワード }STAFF;

試したこと

実行結果(コンソール画面)です。

ログインメニュー 処理を選択してください 1:職員新規登録 2:ログイン E:終了 ? 1 ■1.職員新規登録メニュー■ 処理を選択してください 1:職員新規登録 2:お試しデータ登録 E:戻る ? 2 お試しデータをバイナリファイルに書き込みますか?( y / n ) y ファイルに保存しました。(←ここで終了してしまいます。)

本来の実現したい流れ

ログインメニュー 処理を選択してください 1:職員新規登録 2:ログイン E:終了 ? 1 ■1.職員新規登録メニュー■ 処理を選択してください 1:職員新規登録 2:お試しデータ登録 E:戻る ? 2 お試しデータをバイナリファイルに書き込みますか?( y / n ) y ファイルに保存しました。 ■1.職員新規登録メニュー■ 処理を選択してください 1:職員新規登録 2:お試しデータ登録 E:戻る ? E ログインメニュー 処理を選択してください 1:職員新規登録 2:ログイン E:終了 ? E

補足情報(FW/ツールのバージョンなど)

Eclipse 2019-12
訳あってCプロジェクトでツールチェーンMinGW GCCで開発しています。

macOS Catalina ver10.15.7

そのほかの情報が必要であれば分かる範囲で追記します。
何卒よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

修正ました。変更箇所は、//変更 //削除 のコメントをいれてます。

main.c

C

1#include <stdio.h> 2#include <string.h> 3#include "main.h" 4#include "staff.h" 5#include "common.h" 6 7 8int main(void){ 9 int loop = TRUE; 10 char work[ 128 ]; 11 12 while(loop){ 13 printf( "\n ログイン画面" ); 14 printf( "\n 処理を選択してください" ); 15 printf( "\n 1:職員新規登録" ); 16 printf( "\n 2:ログイン" ); 17 printf( "\n E:終了" ); 18 printf( "\n ? " ); 19 20 /* 処理区分入力 */ 21 work[ 0 ] = '\0'; 22 scanf( "%s", work ); 23 24 /* 入力桁数チェック -> 1 以外 ? */ 25 if( strlen( work ) != 1 ) { 26 printf( "¥n 入力ミスです" ); 27 continue; 28 } 29 30 switch( work[ 0 ] ) { 31 case '1': /* 職員新規登録 */ 32 staff(); 33 break; 34 case '2': /* ログイン */ 35 //login( ); 36 break; 37 case 'e': /* 終了 */ 38 case 'E': 39 loop = FALSE; 40 break; 41 default: 42 printf( "¥n 入力ミスです" ); 43 break; 44 } 45 } 46 return 0; //変更 47} 48

staff.c

C

1#include <stdio.h> 2#include<string.h> 3#include"staff.h" 4#include "common.h" 5#include"otameshi.h" 6 7 8int staff(){ //変更 9 10 int loop = TRUE; 11 char work[ 128 ]; 12 13 while(loop){ 14 printf( "\n ■1.職員新規登録メニュー■" ); 15 printf( "\n 処理を選択してください" ); 16 printf( "\n 1:職員新規登録" ); 17 printf( "\n 2:お試しデータ登録" ); 18 printf( "\n E:戻る" ); 19 printf( "\n ? " ); 20 21 /* 処理区分入力 */ 22 work[ 0 ] = '\0'; 23 scanf( "%s", work ); 24 25 /* 入力桁数チェック -> 1 以外 ? */ 26 if( strlen( work ) != 1 ) { 27 printf( "¥n 入力ミスです" ); 28 continue; 29 } 30 31 switch( work[ 0 ] ) { 32 case '1': /* 職員新規登録 */ 33 //otameshi(); 34 break; 35 case '2': /*お試しデータ登録 */ 36 otameshi(); 37 break; 38 case 'e': /* 戻る */ 39 case 'E': 40 loop = FALSE; 41 break; 42 default: 43 printf( "¥n 入力ミスです" ); 44 break; 45 } 46 //return OK; //削除 47 } 48 return 0; 49} 50

otameshi.c

C

1#include <stdio.h> 2#include<string.h> 3#include"staff.h" 4#include "common.h" 5#include"otameshi.h" 6 7 8int otameshi() 9{ 10 11 12 FILE * fp = NULL; 13 int loop = TRUE; 14 char work[ 128 ]; 15 16 while(loop){ 17 printf("お試しデータをバイナリファイルに書き込みますか?( y / n )\n"); 18 19 /* 処理区分入力 */ 20 work[ 0 ] = '\0'; 21 scanf( "%s", work ); 22 23 /* 入力桁数チェック -> 1 以外 ? */ 24 if( strlen( work ) != 1 ) { 25 printf( "¥n 入力ミスです" ); 26 continue; 27 } 28 29 30 switch( work[ 0 ] ) { 31 case 'y': /* 職員新規登録 */ 32 case 'Y': 33 // セーブデータをバイナリの書き込みでオープン 34 fp = fopen( "staff.bin", "wb"); 35 if(fp == NULL){ 36 printf("ファイルが開けませんでした\n"); 37 return 1; 38 } 39 STAFF staff[]= 40 { 41 //職員コード 職員パスワード 42 {0001, 1234}, 43 {0002, 2345}, 44 {0003, 1234}, 45 }; 46 47 48 // バイナリファイルに書き込み 49 fwrite(staff, sizeof(STAFF), sizeof(staff) / sizeof(staff[0]), fp); 50 printf("ファイルに保存しました。\n"); 51 fclose(fp); 52 loop = FALSE; 53 break; 54 case 'n': /* お試しデータの登録をしない場合 */ 55 case 'N': 56 printf(" お試しデータの登録は行いませんでした。\n"); 57 loop = FALSE; 58 break; 59 case 'e': /* 戻る */ 60 case 'E': 61 loop = FALSE; //追加 62 break; 63 default: 64 printf("文字入力ミスです。\n"); 65 break; 66 } 67 } 68 return OK; 69} 70

投稿2021/01/12 00:09

tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wesker.alice

2021/01/12 07:33

ありがとうございます! 修正助かります!
guest

0

ベストアンサー

main.cの最後のところ

C

1 return 0; 2 } 3}

なんか変な気がしませんか?
}に対応する{を探してその影響を考えると

C

1int main(void){ 2 while(loop){ 3 //イロイロな処理 4 return 0; 5 } 6}

イロイロな処理が終わるとreturnがあるので、whileループは繰り返すことなく関数を終了してしまいます(continueでも無い限り)。mainに戻っていないのではなく、戻った途端に終了しているのでしょう。

staff_new関数も同様の構造になっているので期待の動作をしないのでは。returnの使い方になにか勘違いがあったりしませんか?

それと、本題ではありませんが、main関数には(他の関数と違って特別に)プロトタイプ宣言は不要です。

投稿2021/01/11 22:20

編集2021/01/11 22:22
thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wesker.alice

2021/01/12 08:10 編集

ご回答ありがとうございます。 各while内のreturnを消したら望んでいる処理に修正されました。 whileについての理解が足りていませんでした。 staff関数もotameshi関数もint型なのでreturn 0が必要ですが、whileにはreturnがそもそもいらない(今回のケース)という事だったんだなと気づきました。 returnの使い方も理解が低いまま、使っていました。 今C言語を学んでいて理解がまだ足りていない部分も多々あってwhile文など基礎の部分を再確認して理解を深めて正しく使えるようにしていこうと思います。 main関数のプロトタイプ宣言が不要という事も教えていただきありがとうございます。 まだまだ奥が深いですね。なぜプロトタイプが必要でないのかも調べていこうと思います。
thkana

2021/01/12 12:39

> whileにはreturnがそもそもいらない(今回のケース)という事だったんだなと気づきました。 いや、今回に限らずいつでも、whileとreturnとは全く関係ありません。whileループの中で関数を終えたいというのならreturn してもいいですけれど。 > なぜプロトタイプが必要でないのか 言ってしまうと、そういうことに決めたから、です。main関数はプログラムの開始点(Entry point)ですので特別扱いです。
guest

0

main の while-loop 内に return があるため、loopを回れないのでは?

投稿2021/01/11 15:12

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wesker.alice

2021/01/12 07:17

ご回答ありがとうございます。 thkanaさんにもご指摘いただいた部分で、returnを削除してビルドしてみると希望通りに動きました。 ありがとうございます。
guest

0

c

1 case '2': /*お試しデータ登録 */ 2 otameshi(); 3 break;

breakしたら当然そうなるのでは?

違うわ、これswitchのbreakだ。正しい指摘はthkanaさんの回答を参照してください。

お詫びにtatsu99さんの回答をwandboxで動かしたものをおいておきます。
https://wandbox.org/permlink/khSyRBPrxZgQGIlo

投稿2021/01/11 15:10

編集2021/01/12 03:25
yumetodo

総合スコア5852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wesker.alice

2021/01/12 07:19 編集

ご回答ありがとうございます。 thkanaさんの回答をベストアンサーにさせていただきました。 URLもありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問