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

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

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

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

Q&A

解決済

4回答

1999閲覧

c言語 ファイルの検索・更新

entio

総合スコア19

C

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

0グッド

0クリップ

投稿2019/04/24 00:51

社員番号(5byte)氏名(20byte)給与(7byte)CR/LF固定(2byte)
このデータをファイルに登録するプログラムを作っています。
新規で登録する場合と更新する場合を考えなければならないのですが、
更新がうまく作動していません。
具体的にはレコードの検索処理内のbの値がずっと0のままになっています。
原因が分かるでしょうか?

#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.DAT" /*********************************************************************/ /* 構造体の宣言 */ /*********************************************************************/ 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(DATA,O_RDWR|O_CREAT, S_IREAD | S_IWRITE); } main() { struct syain_k rdbuf; int a; long d; int recno; char sno[6]; char name[21]; char salary[8]; initial_syori(); while(1) { printf("社員番号を入力してください\n"); scanf("%s",sno); a=numeric_chk(sno, 5); if (a==-1) { printf("NUMERICエラー\n"); continue; } d=atol(sno); if (d==99999L) { return 0; } else if ((d<1000L)||(d>90000L)) { printf("範囲エラー\n"); continue; } recno = search(sno, &rdbuf); if (recno!=0) data_disp(&rdbuf); printf("氏名の入力\n"); scanf("%s",name); printf("氏名[%s]\n",name); printf("給与を入力してください\n"); scanf("%s",salary); a=numeric_chk(salary, 7); if (a==-1) { printf("NUMERICエラー\n"); continue; } printf("給与:[%s]\n",salary); touroku(recno, sno, name, salary); } } /**************************************l*******************************/ /* 数字か文字かのチェック */ /* IN: char *str チェックを行う文字列 */ /* in: int n チェックを行う文字列のバイト数 */ /* 戻り値 0:全て数字: -1:数字以外の文字あり */ /*********************************************************************/ int numeric_chk(char *str, int n) { int i; for(i=0;i<n;i++) { if ((str[i]>='0')&&(str[i]<='9')) { continue; } else { return(-1); } } return 0; } /*********************************************************************/ /* レコードの検索処理 */ /* IN: *sno キー入力された社員番号 */ /* OUT: *rec 社員番号が一致した時の既存レコード */ /* 戻り値 0・・・存在しない */ /* 1~・・・既存のレコード番号 */ /*********************************************************************/ int search(char *sno, struct syain_k *rec) { int recno; int n; long a, b; recno = 0; a = atol(sno); lseek(Fd,0L,SEEK_SET); while(1) { n = read(Fd,&rec,sizeof(struct syain_k)); b=atol(rec->sno); if (n==0) { recno=0; return 0; } else { recno++; if(a==b) printf("P1"); getch(); return recno; } } } /*********************************************************************/ /* 既存データの表示処理 */ /* IN: rec 社員番号が一致した時のレコード */ /*********************************************************************/ void data_disp(struct syain_k *rec) /*表示処理*/ { int X; X=atoi(rec->sno); 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", rec->name); printf("%s", rec->salary); } /*********************************************************************/ /* 登録処理 */ /* 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); wtbuf.crlf[0]=CR; wtbuf.crlf[1]=LF; if (recno==0) lseek(Fd,0L,SEEK_END); else lseek(Fd,34*(recno-1),SEEK_SET); write(Fd,&wtbuf,sizeof(wtbuf)); } コード

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

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

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

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

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

guest

回答4

0

ファイルをopenしたなら、closeしましょう
closeしないとファイルは空ですぜ

投稿2019/04/24 00:55

y_waiwai

総合スコア87719

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

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

stdio

2019/04/24 01:27

それ以前にwhile(1)内のインデントが汚いのは一番に気になりますよね。
guest

0

データの確認とポインタの理解が不足しておられるようです.

レコードの検索処理内のbの値がずっと0のまま

b の値が 0 なのでは無く, この場合 b=atol(rec->sno); の rec->sno の値がおかしいはずです.

n = read(Fd,&rec,sizeof(struct syain_k));

n の値を確認して, 読み込めているかのチェックが必要です.
rec は int search(char *sno, struct syain_k *rec) ですので struct syain_k のポインタです.
'&' は必要無いのではないでしょうか.

投稿2019/04/24 01:02

編集2019/04/24 01:05
jimbe

総合スコア12543

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

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

entio

2019/04/24 04:07

回答ありがとうございます。 おっしゃる通りrecの&をなくしたところ無事に作動しました!
guest

0

ベストアンサー

こちらの環境ではコンパイルできないので、気になった所・・・
int numeric_chk(char *str, int n)・・・文字列(\0終端)を渡しているのになぜサイズがいるんでしょう?・・・また、呼び出し元でマジックナンバー(7など)をハードコーディングしているのは?
・・・他にもありますmemcpy()とか・・・
//
open()やscanf()などエラーチェックがないのは致命的。
前回の質問でも言いましたが、新旧入り乱れたコーディングです。インデントもいい加減。気をつけましょう。
・・あと「このソースコンパイル通ってますか?」
case0: printf("役員\n");はcase 0: printf("役員\n");ですね?(他のcaseも)
//
全体的にエラーチェックが抜けています。特にファイル操作についてはディスクそのものを壊してしまう可能性も有るのですべてチェックするようにしましょう。
「追記」clang-formatでフォーマットしたものを貼り付けておきます。・・・これがベターではないですが^^;

c

1#include <stdio.h> 2#include <fcntl.h> 3#include <memory.h> 4#include <string.h> 5//#include <io.h> 6#include <errno.h> 7#include <math.h> 8#include <stdlib.h> 9#include <sys/types.h> 10#include <sys/stat.h> 11/*********************************************************************/ 12/* 定数の定義 */ 13/*********************************************************************/ 14#define CR 0x0D 15#define LF 0x0A 16#define DATA "SYAIN.DAT" 17/*********************************************************************/ 18/* 構造体の宣言 */ 19/*********************************************************************/ 20struct syain_k { 21 char sno[5]; /* 社員番号 */ 22 char name[20]; /* 氏名 */ 23 char salary[7]; /* 給与 */ 24 char crlf[2]; /* CR/LF */ 25}; 26/*********************************************************************/ 27/* 静的変数の定義 */ 28/*********************************************************************/ 29/*********************************************************************/ 30/* 内部関数のプロトタイプ宣言 */ 31/*********************************************************************/ 32int numeric_chk(char *str, int n); 33int search(char *sno, struct syain_k *rec); 34void data_disp(struct syain_k *rec); 35void touroku(int recno, char *sno, char *name, char *salary); 36/*********************************************************************/ 37/* main() メイン関数 */ 38/*********************************************************************/ 39int Fd; 40initial_syori() 41{ 42 Fd = open(DATA, O_RDWR | O_CREAT, S_IREAD | S_IWRITE); 43} 44main() 45{ 46 struct syain_k rdbuf; 47 int a; 48 long d; 49 int recno; 50 char sno[6]; 51 char name[21]; 52 char salary[8]; 53 54 initial_syori(); 55 while (1) { 56 printf("社員番号を入力してください\n"); 57 scanf("%s", sno); 58 a = numeric_chk(sno, 5); 59 if (a == -1) { 60 printf("NUMERICエラー\n"); 61 continue; 62 } 63 d = atol(sno); 64 if (d == 99999L) { 65 return 0; 66 } else if ((d < 1000L) || (d > 90000L)) { 67 printf("範囲エラー\n"); 68 continue; 69 } 70 recno = search(sno, &rdbuf); 71 if (recno != 0) 72 data_disp(&rdbuf); 73 74 printf("氏名の入力\n"); 75 scanf("%s", name); 76 printf("氏名[%s]\n", name); 77 78 printf("給与を入力してください\n"); 79 scanf("%s", salary); 80 a = numeric_chk(salary, 7); 81 if (a == -1) { 82 printf("NUMERICエラー\n"); 83 continue; 84 } 85 printf("給与:[%s]\n", salary); 86 87 touroku(recno, sno, name, salary); 88 } 89} 90/**************************************l*******************************/ 91/* 数字か文字かのチェック */ 92/* IN: char *str チェックを行う文字列 */ 93/* in: int n チェックを行う文字列のバイト数 */ 94/* 戻り値 0:全て数字: -1:数字以外の文字あり */ 95/*********************************************************************/ 96int numeric_chk(char *str, int n) 97{ 98 int i; 99 for (i = 0; i < n; i++) { 100 if ((str[i] >= '0') && (str[i] <= '9')) { 101 continue; 102 } else { 103 return (-1); 104 } 105 } 106 return 0; 107} 108/*********************************************************************/ 109/* レコードの検索処理 */ 110/* IN: *sno キー入力された社員番号 */ 111/* OUT: *rec 社員番号が一致した時の既存レコード */ 112/* 戻り値 0・・・存在しない */ 113/* 1~・・・既存のレコード番号 */ 114/*********************************************************************/ 115int search(char *sno, struct syain_k *rec) 116{ 117 int recno; 118 int n; 119 long a, b; 120 recno = 0; 121 122 a = atol(sno); 123 lseek(Fd, 0L, SEEK_SET); 124 while (1) { 125 n = read(Fd, &rec, sizeof(struct syain_k)); 126 b = atol(rec->sno); 127 if (n == 0) { 128 recno = 0; 129 return 0; 130 } else { 131 recno++; 132 if (a == b) 133 printf("P1"); 134 getch(); 135 return recno; 136 } 137 } 138} 139/*********************************************************************/ 140/* 既存データの表示処理 */ 141/* IN: rec 社員番号が一致した時のレコード */ 142/*********************************************************************/ 143void data_disp(struct syain_k *rec) /*表示処理*/ 144{ 145 int X; 146 X = atoi(rec->sno); 147 switch (X) { 148 case 0: 149 printf("役員\n"); 150 break; 151 case 1: 152 printf("部長\n"); 153 break; 154 case 2: 155 printf("課長\n"); 156 break; 157 case 3: 158 printf("係長\n"); 159 break; 160 case 4: 161 printf("主任\n"); 162 break; 163 default: 164 printf(" \n"); 165 } 166 printf("%s", rec->name); 167 printf("%s", rec->salary); 168} 169/*********************************************************************/ 170/* 登録処理 */ 171/* IN: recno・・・レコード番号 */ 172/* 0:更新レコードは存在しない */ 173/* 1~:更新するレコード番号 */ 174/* IN: *sno・・・社員番号 */ 175/* IN: *name・・・氏名 */ 176/* IN: *salary・・・給与 */ 177/*********************************************************************/ 178void touroku(int recno, char *sno, char *name, char *salary) 179// char *sno, *name, *salary; 180{ 181 struct syain_k wtbuf; 182 memcpy(wtbuf.sno, sno, 5); 183 memcpy(wtbuf.name, name, 20); 184 memcpy(wtbuf.salary, salary, 7); 185 wtbuf.crlf[0] = CR; 186 wtbuf.crlf[1] = LF; 187 if (recno == 0) 188 lseek(Fd, 0L, SEEK_END); 189 else 190 lseek(Fd, 34 * (recno - 1), SEEK_SET); 191 192 write(Fd, &wtbuf, sizeof(wtbuf)); 193}

こちらでコンパイラ通すため一部変えています(#include <io.h>のコメント化とか)。・・・エラーが出るので実行ファイルは出来ません^^;

投稿2019/04/24 01:27

編集2019/04/24 03:15
cateye

総合スコア6851

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

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

cateye

2019/04/24 01:36 編集

波括弧({})がホワイトスミスなのも気になりますが・・・まぁ、統一されていればいいとも思うw
entio

2019/04/24 02:59

回答ありがとうございます。 インデントの指摘もありがとうございます。 どのようなインデントにすれば見やすいのかなど、まだあやふやなところもあり分かりづらくて申し訳ないです。 ・・あと「このソースコンパイル通ってますか?」 case0: printf("役員\n");はcase 0: printf("役員\n");ですね?(他のcaseも) これに関してはコンパイル自体は成功しているのですが、そこまでたどり着けず機能していないという状況です。
guest

0

問題はいろいろあるかもしれませんが、ひとまずreadのところ。
&recとしていますが、引数でアドレスをもらっているので、readに渡すときに&は不要です。
引数のアドレスを指すことになるので、recの実体に読み込まれていないと思われます。

c

1int search(char *sno, struct syain_k *rec) 2{ 34 while(1) 5 { 6 n = read(Fd,&rec,sizeof(struct syain_k)); 78 n = read(Fd,rec,sizeof(struct syain_k));

投稿2019/04/24 01:04

ttyp03

総合スコア16996

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

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

entio

2019/04/24 04:08

回答ありがとうございます。 その通りでした。無事bの中に値が入りました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問