質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

2回答

1692閲覧

関数内で宣言したデータをmain関数でも使えるようにしたい。c言語

entio

総合スコア19

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2019/04/20 08:51

編集2019/04/20 10:19

前提・実現したいこと

画面に「社員番号」「氏名」「給与」を入力して、ファイルに登録するプログラムを作成しています。
データの更新の場合と新規の場合を考えて作成しています。

問題となっているのは、
自分で作成した関数内で使用した構造体をメイン関数でも使用したいがその方法がわからないというものです。
ポインタを使う、メイン関数内で宣言すると言われたのですがわかりませんでした。

関数内で宣言したものをmain関数内で使用するにはポインタを使ってどうすればいいのかという質問で。
すみませんが教えていただけるとありがたいです。

既存データ表示処理の部分で
int X;
X=*rec[0];
という定義をしましたがこれもエラーが出ていて原因がわからないという状況です。
こちらの原因も教えていただけたらなと思います。

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

main関数内でsearch関数内で定義した「rdbuf]という構造体データを使いたいが
main関数で使えないというものです。

エラーメッセージ
main関数内の「rdbuf」を使う場面で
error c2065: 'rdbuf' : underfind
warning c4047: 'argment' : different levels of indirection
というエラーが起きます。

```#include <stdio.h> #include <fcntl.h> #include <memory.h> #include <string.h> #include <io.h> #include <errno.h> #include <math.h> #include <stdlib.h> #include <sys\types.h> #include <sys\stat.h> /*********************************************************************/ /* 定数の定義 */ /*********************************************************************/ #define CR 0x0D #define LF 0x0A #define DATA SYAIN.MAS /*********************************************************************/ /* 構造体の宣言 */ /*********************************************************************/ struct syain_k { char sno[5]; /* 社員番号 */ char name[20]; /* 氏名 */ char salary[7]; /* 給与 */ char crlf[2]; /* CR/LF */ }; /*********************************************************************/ /* 静的変数の定義 */ /*********************************************************************/ /*********************************************************************/ /* 内部関数のプロトタイプ宣言 */ /*********************************************************************/ int numeric_chk(char str,int n); int search(char *sno,struct syain_k *rec); void data_disp(struct syain_k *rec); void touroku(int recno, char *sno,char *name,char *salary); /*********************************************************************/ /* main() メイン関数 */ /*********************************************************************/ int Fd; initial_syori() { Fd = open("SYAIN.DAT",O_CREAT); /*ファイルのオープン*/ } main() { int a; long d; int recno; char sno, name, salary; struct syain_k *rec; while(1) { printf("社員番号を入力してください\n"); scanf("%d",&sno); a=numeric_chk(sno,5); if(a==-1) printf("NUMERICエラー\n"); continue; d=atol(&sno); if(d==99999) return 0; else if(d>=1000&&d<=90000) printf("範囲エラー\n"); continue; recno=search(&sno, rdbuf); if(recno!=0) data_disp(&rebuf); printf("氏名の入力\n"); scanf("%s",name); printf("氏名[%s]\n",name); printf("給与を入力してください\n"); scanf("%s",salary); printf("給与:[%s]\n",salary); touroku(recno, &sno, &name, &salary); } } /*********************************************************************/ /* 数字か文字かのチェック */ /* IN: char *str チェックを行う文字列 */ /* in: int n チェックを行う文字列のバイト数 */ /* 戻り値 0:全て数字: -1:数字以外の文字あり */ /*********************************************************************/ int numeric_chk(str, n) int n; char *str; { int i; for(i=0;i<n;i++) if ((str[i]>='0')&&(str[i]<='9')) continue; else return(-1); } /*********************************************************************/ /* レコードの検索処理 */ /* IN: *sno キー入力された社員番号 */ /* OUT: *rec 社員番号が一致した時の既存レコード */ /* 戻り値 0・・・存在しない */ /* 1〜・・・既存のレコード番号 */ /*********************************************************************/ int search(char *sno, struct syain_k *rec) { struct syain_k rdbuf; int recno=0; int n; long a, b; a=atol(sno); b=atol(rdbuf.sno); lseek(Fd,0L,SEEK_SET); while(1) n=read(Fd,&rdbuf,34); if(n==0) { recno=0; return 0; } else { recno++; if(a==b) return recno; } } /*********************************************************************/ /* 既存データの表示処理 */ /* IN: rec 社員番号が一致した時のレコード */ /*********************************************************************/ void data_disp(struct syain_k *rec) /*表示処理*/ { int X; X=*rec[0]; switch(X) { case0: printf("役員\n"); break; case1: printf("部長\n"); break; case2: printf("課長\n"); break; case3: printf("係長\n"); break; case4: printf("主任\n"); break; default: printf(" \n"); } printf("%s", rdbuf.name[20]); printf("%s", rdbuf.salary[7]); } /*********************************************************************/ /* 登録処理 */ /* IN: recno・・・レコード番号 */ /* 0:更新レコードは存在しない */ /* 1〜:更新するレコード番号 */ /* IN: *sno・・・社員番号 */ /* IN: *name・・・氏名 */ /* IN: *salary・・・給与 */ /*********************************************************************/ void touroku(recno, sno, name, salary) int recno; char *sno, *name, *salary; { struct syain_k wtbuf; memcpy(wtbuf.sno, sno, 5); memcpy(wtbuf.name, name, 20); memcpy(wtbuf.salary, salary, 7); memcpy(wtbuf.crlf, CR/LF, 2); if (recno==0) lseek(Fd,0L,SEEK_END); else lseek(Fd,34*(recno-1),SEEK_SET); write(Fd,&wtbuf,34); } コード ```#

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

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

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

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

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

cateye

2019/04/20 09:00

<code>を選んでその中にソースを貼り付けて下さい。このままでは読む気がしません。 また、関数内のデータはその関数以外では不可視です。 “メイン関数内で宣言する”と言われるように、main()で宣言してポインタを渡せば済むと思いますが?
entio

2019/04/20 10:22

すみません<code>内にソースを貼り付けました。 ポインタを渡すという考えや方法がいまいちわからないです。 例文なども見つからず困っていました。
cateye

2019/04/20 10:48 編集

かなり古い書き方ですが? 書籍や講義で教わりましたか? 旧 int numeric_chk(str, n) int n; char *str; { 新↓ int numeric_chk(char *str, int n) { こっちは新しい?? int search(char *sno, struct syain_k *rec)←これが「ポイントを渡す」ということです。 {
entio

2019/04/20 10:52

すみません、まだ古い新しいの区別がつかずよく分からないです。 書き方は講義で教わりました。 古い方を覚えておけば新しい書き方にも対応できると言っていました。
pepperleaf

2019/04/20 11:54

余談ですが、 > 古い方を覚えておけば新しい書き方にも対応できると言っていました。 程度次第。 今時、K&RのC言語がコンパイルできるか? Pythonも 2 と 3では互換性無いと言うし、、。
episteme

2019/04/20 12:51

1985あたりでANSI-draftがでてるから、その頃には消えかけてるんじゃないかなソレ...
raccy

2019/04/20 13:48 編集

文法としてはC11でもまだ残ってます。n1570の6.9.1の13でサンプル付き説明までありますので。C11で削除されたのはgetsぐらいでしょうか。(C++とかならC++11からautoの変更など互換性無い部分が多そうですけど、Cは互換性はほぼ保っているような気がします)
raccy

2019/04/20 13:53

あ、ただ、6.11.7で将来廃止予定と書いていますので、C2xではなくなる可能性はありますね。どちらにしても、使わない方が良いでしょう。
guest

回答2

0

//
/
レコードの検索処理 /
/
IN: *sno キー入力された社員番号 /
/
OUT: *rec 社員番号が一致した時の既存レコード /
/
戻り値 0・・・存在しない /
/
1〜・・・既存のレコード番号 /
/
/
int search(char *sno, struct syain_k *rec)

なぜrecを渡しているのか考えるとよいでしょう。


この状況から貴方がコレを完成させるには途方もない努力が必要です。
具体的には学生が100時間くらいかけて学ぶくらいの量です。

とにかく、教科書を頭から読み直す事をおすすめします。

とりあえず、意図通りに動かないだろう箇所だけ列挙

  • char型は1文字しか格納できません。

c

1char sno, name, salary;
  • おそらく{}の付け忘れ
while(1) n=read(Fd,&rdbuf,34);
  • bが自動的に変更されたりはしないので、自分で変換し直さなければいけない

c

1if(a==b)
  • 出力方法を復習してください

c

1printf("%s", rdbuf.name[20]); 2printf("%s", rdbuf.salary[7]);
  • 無理

c

1memcpy(wtbuf.crlf, CR/LF, 2);

どうしてもわからない場所があれば答えますが、できれば自力で調べてみてください。

投稿2019/04/21 05:58

asm

総合スコア15147

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

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

entio

2019/04/21 06:36

回答ありがとうございます。 •char型は1文字しか格納できません char sno; char name; char salary; •おそらく{}の付け忘れ while(1) { … return recno; } •無理 wtbuf.crlf[0] = CR; wtbuf.crlf[1] = LF; 上の3つは直しましたが、後の if(a==b)とprintfで出力できない理由がわかりませんでした。 b=atol(rdbuf.sno); とbもatol関数で変換しているのでいいのではないかということと、 printfで文字列を出力する際は%sを使いnullが出るまで表示されると書いてあったので、この表現のどこが違うかわからないことです。 この2つを教えていただければなと思います。
asm

2019/04/21 07:06

> if(a==b) 端的に言うとb=atoi(rdbuf.sno);の位置が問題です。 if直上に持ってくる必要があります。 b=atoi(rdbuf.sno);のあとにrdbufを書き換えたところでbの値は変化しません。 > printf("%s", rdbuf.name[20]); これでは、rdbufのnameの21番目の値を表示しようとします。 printf("%s", rdbuf.name);でよいです。
entio

2019/04/21 07:40

ありがとうございます。 確かにb=atoi(rdbuf.sno);の位置が違っていたと理解できました。 n=read(Fd,&rdbuf,34); この後で宣言しないと意味がないことがわかりました。 printfの仕組みも理解できました。 構造体を出力する場合は、今回の場合はrdbuf.nameだけですべての文字列を呼んでくれるんですね。 丁寧に教えてもらいありがとうございます。
asm

2019/04/21 07:53

> 構造体を出力する場合は、今回の場合はrdbuf.nameだけですべての文字列を呼んでくれる 構造体とは無関係ですし、すべての文字列というと語弊があります。 char name[20];は文字の配列なので、文字列の配列とは違います。 rdbuf.name[20]で帰ってくるのは21番目の1文字です。 printf("%s")で渡すのは、文字列の先頭へのアドレスなので &(rdbuf.name[0])を渡すことになりますが、 C言語では配列の名前だけが置いてあった場合、先頭へのアドレスに読み替えるという仕様があるので rdbuf.nameになります。
entio

2019/04/21 09:22

文字の配列と文字列の配列の違いを理解できていませんでした。 rdbuf.name[20]は21番目のアドレスの文字を表示しろとなっていたんですね。 解説していただきありがとうございます。
guest

0

ベストアンサー

残念ながら私の環境(Linux+clang)ではコンパイルできません。
が、新旧乱れた書き方が見受けられます。これでは、最新のコンパイラではワーニングの嵐になってしまうと思われます。
気がついた所
ファイルはopen()ではなくfopen()を使いましょう。
main()に戻り値がない?→int main(void)
numeric_chk()はisdigit()で出来ます。
文字列はmemcpy()ではなくstrcpy()を使いましょう。
write(Fd, &wtbuf, 34);はwrite(Fd, &wtbuf, sizeof(wtbuf));
また、
int X;
X = *rec[0];
は、↓になるかと
X= atoi(rec->sno);
//
などなど・・・最新でなくてもいいですがc言語の仕様を確認して下さい。
「追記」
苦しんで覚えるC言語
・・・ついでにポインタ渡のサンプル

c

1usr ~/Project/test % cc t2.c 2usr ~/Project/test % ./a.out 32:test 4usr ~/Project/test % cat t2.c 5#include <stdio.h> 6#include <string.h> 7 8typedef struct { 9 int num; 10 char name[12]; 11} Member; 12 13static void set(Member *mbp) 14{ 15 mbp->num = 2; 16 strcpy(mbp->name, "test"); 17} 18 19int main(void) 20{ 21 Member mb; 22 set(&mb); 23 printf("%d:%s\n", mb.num, mb.name); 24 // 25 return 0; 26} 27usr ~/Project/test %

投稿2019/04/20 11:05

編集2019/04/20 11:40
cateye

総合スコア6851

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

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

cateye

2019/04/20 11:18 編集

知らない関数などは、C言語関数辞典http://www.c-tipsref.comで確認しましょうd^^
entio

2019/04/20 12:12

丁寧な解説、サンプルまで載せていただいていただきありがとうございます。 write文の訂正の解説もとても納得できました。 アドバイスを参考にして解いてみたいと思います。 ありがとうございました。
entio

2019/04/21 06:44

すみません、一つ解説してもらったところで質問があるのですが、 X = *rec[0]; は、↓になるかと X= atoi(rec->sno); の部分でchar型をint型に直すというのは分かったのですが、 (rec-<sno)がどんな作業をしているかわからなかったです。 X=atoi(*rec[0]);ではだめなのでしょうか? 何度も質問して申し訳ないですがぜひ教えていただけたらと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問