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

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

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

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

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Q&A

解決済

2回答

1155閲覧

fgetsとmemcpyのやり方

kekennnn

総合スコア1

C

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

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

0グッド

0クリップ

投稿2022/07/23 23:04

編集2022/08/02 01:09

fgets関数を用いて、ファイル(class.dat)を1行ずつ読み込み、memcpyで切り取りをし、生徒の成績を作りたいと考えています。
ファイル(class.dat)の内容は左から、クラス(全角2桁)、氏名(全角20桁)、性別(全角MまたはFの1桁)、国語の点数(半角3桁)、数学の点数(半角3桁)、英語の点数(半角3桁)となっています。また、性別は男・女と表示したいと考えてます。

現在、ファイルの読み込みはできたのですが、memcpyの部分が上手く出来ないです。
C言語初心者なので、考え方が浮かばないので、教えていただけますと幸いです。

txt

1JM田中 なおき M026052036 2JM渡辺よしひこ M056011023 3JM吉田 なおみ F078002014 4JM高橋 啓介 M095100033 5JM武田 謙信 M020025003 6RM大阪 ヒロキ M069078056 7RM太田 信彦 M033069074 8RM吉田 さおり F025085012 9KM守屋 かおり F036075074 10KM佐藤 かよ F014026085 11KM川崎 たかや M025047091 12KM野原 ひろし M098036062

表示したい結果============================
クラス  氏名     性別  国語  数学  英語  合計 
JM    田中 なおき 男   026  052  036   114
・・・・・省略・・・・・

===================================

C

1#define _CRT_SECURE_NO_WARNINGS 2#include <stdio.h> 3#include <stdlib.h> 4 5int main() { 6 7 FILE* fp; 8 char str[256]; 9 char class[4]; 10 char name[64]; 11 char gen[2]; 12 char Tensu[16]; 13 int tensu; 14 int jap; 15 nt math; 16 int eng; 17 18 printf("クラス\t氏名\t\t性別\t国語\t数学\t英語\t合計\t\n"); 19 printf("------------------------------------------------------------\n"); 20 21 22 fp = fopen("class.dat", "r"); 23 24 25 if (fp == NULL) { 26 printf("ファイルオープン失敗\n"); 27 return -1; 28 } 29 30 while (!feof(fp)) { 31 if (fgets(str, 256, fp) == NULL) { 32 break; 33 } 34 35 memcpy(&class, str, 2); 36 memcpy(&name, str[2], 20); 37 memcpy(&gen, str[22], 1); 38 memcpy(&Tensu, str[23], 9); 39 tensu = atoi(Tensu); 40 memcpy(&jap, Tensu[3], 3); 41 memcpy(&math, Tensu[6], 3); 42 memcpy(&eng, Tensu[9],3); 43 44 printf("%s\t %s\t\t %s\t %s\n ", 45 &class, 46 &name, 47 &gen, 48 &jap, 49 &math 50 &eng 51 &jap + &math + &eng 52 ); 53 } 54 fclose(fp); 55 56 return 0; 57} 58

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

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

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

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

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

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

y_waiwai

2022/07/23 23:06

うまくいかない、とはどういう動作となるんでしょうか。詳しく説明しよう また、実際にはどういう表示になるのかってのも提示しよう
kekennnn

2022/07/23 23:13

printf("クラス\t氏名\t\t性別\t国語\t数学\t英語\t合計\t\n"); printf("------------------------------------------------------------\n"); この部分の表示はできています。 また、memcpy(&gen, str[22], 1);の部分で『0x00007FF900241416 (vcruntime140d.dll) で例外がスローされました (test.exe 内): 0xC0000005: 場所 0x00000000FFFFFFE7 の読み取り中にアクセス違反が発生しました』という表示が出てきており、調べたのですが、よくわかりませんでした、
archiver

2022/07/24 00:03

氏名データですが、「渡辺よしひこ」だけ姓と名の間にスペースが無く、他はスペースがありますが、姓と名の間にスペースを入れる入れないは何かルールはありますか? またデータに全角文字(マルチバイト文字)を使用していますが、文字コードは何を想定していますか?文字コードによっては全角文字(マルチバイト文字)を表すバイト数が変わりますので、今の単に「文字数」指定のmemcpyでは期待通りのコピーにならないと思います。
kekennnn

2022/07/24 00:14

氏名データですが、「渡辺よしひこ」ですが、ファイルを渡された時点でこの状態であったので、特にルールはないと思います。 文字コードについても指示がない状況です。
archiver

2022/07/24 00:48

これって委託業務か何かですか?データファイルについては仕様を確認された方がいいです。 1レコード(1行)のデータに可変長データ(氏名)と固定長データ(氏名以外)が混在しています。今の形式では氏名データ(以降)を抜き出すのがかなり困難になります。
kekennnn

2022/07/24 01:55

学校の課題です。  クラス(全角2桁)、氏名(空白全角20桁)、性別(全角MまたはFの1桁)、国語の点数(半角3桁)、数学の点数(半角3桁)、英語の点数(半角3桁)で固定長と言われました。
kazuma-s

2022/07/24 02:08

質問の class.dat の内容を ```text と ``` で挟んでください。 ソースコードも main の中身だけを ``` と ``` で挟むのではなく、 #define ... から } までの全部を ```C と ``` で挟んでください。 質問は編集できます。
kazuma-s

2022/07/24 02:14

> クラス(全角2桁)、氏名(空白全角20桁)、性別(全角MまたはFの1桁)、 質問の class.dat の内容では、クラスも性別も半角になっていますが、違うんですか?
guest

回答2

0

ベストアンサー

C

1#define _CRT_SECURE_NO_WARNINGS 2#include <stdio.h> 3 4int main(void) 5{ 6 FILE *fp; 7 char str[256], class[4], name[64], name2[64], gen[2]; 8 int jap, math, eng; 9 10 printf("クラス\t氏名\t\t性別\t国語\t数学\t英語\t合計\t\n"); 11 printf("------------------------------------------------------------\n"); 12 fp = fopen("class.dat", "r"); 13 if (fp == NULL) { 14 printf("ファイルオープン失敗\n"); 15 return -1; 16 } 17 static const char *s[] = { "男", "女" }; 18 while (fgets(str, 256, fp) != NULL) 19 if (sscanf(str, "%2s%s%s%1s%3d%3d%3d", 20 class, name, name2, gen, &jap, &math, &eng) == 7) 21 printf(" %s\t %s %s\t %s\t %03d\t %03d\t %03d\t %03d\n", 22 class, name, name2, s[*gen=='F'], jap, math, eng, jap + math + eng); 23 else if (sscanf(str, "%2s%s%1s%3d%3d%3d", 24 class, name, gen, &jap, &math, &eng) == 6) 25 printf(" %s\t %s\t %s\t %03d\t %03d\t %03d\t %03d\n", 26 class, name, s[*gen=='F'], jap, math, eng, jap + math + eng); 27 else printf("wrong data"); 28 fclose(fp); 29}

性別を M F ではなく、男女に修正しました。

追記
質問のコードに #define _CRT_SECURE_NO_WARNINGS があることから、
OS が Windows で、コンパイラが Visual C++ だとすると、
文字コードは Shift-JIS でしょう。
それだと全角文字は 2バイトになります。
memcpy はバイト数を指定してバイト列をコピーするものです。

C

1#include <stdio.h> // printf 2#include <stdlib.h> // atoi 3#include <string.h> // memcpy 4 5int main(void) 6{ 7 // 01234567890123456789012345678901234 8 char str1[] = "JM田中 なおき M026052036\n"; 9 // 12全全1全全全12345678901.123456789 10 char str2[] = "JM田中 なおき    M026052036\n"; 11 // 全全全全全全全全全全全全全123456789 12 // 1 2 1 2 3 4 5 6 7 8 9 10 13 char class[5] = "", name[23] = "", gen[3] = "", num[4] = ""; 14 int jap, math, eng; 15 16 memcpy(class, str1, 2); 17 memcpy(name, &str1[2], 22); 18 memcpy(gen, &str1[24], 1); 19 memcpy(num, &str1[25], 3); 20 jap = atoi(num); 21 memcpy(num, &str1[28], 3); 22 math = atoi(num); 23 memcpy(num, &str1[31], 3); 24 eng = atoi(num); 25 printf("[%s] [%s] [%s] [%d] [%d] [%d]\n", 26 class, name, gen, jap, math, eng); 27 28 memcpy(class, str2, 4); 29 memcpy(name, &str2[4], 20); 30 name[20] = '\0'; 31 memcpy(gen, &str2[24], 2); 32 memcpy(num, &str2[26], 3); 33 jap = atoi(num); 34 memcpy(num, &str2[29], 3); 35 math = atoi(num); 36 memcpy(num, &str2[32], 3); 37 eng = atoi(num); 38 printf("[%s] [%s] [%s] [%d] [%d] [%d]\n", 39 class, name, gen, jap, math, eng); 40}

char配列は = "" で初期さすると、全バイトが '\0' で初期化されます。

実行結果

text

1[JM] [田中 なおき ] [M] [26] [52] [36] 2[JM] [田中 なおき     ] [M] [26] [52] [36]

投稿2022/07/24 01:47

編集2022/07/24 15:52
kazuma-s

総合スコア8224

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

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

kekennnn

2022/08/01 01:29

お返事遅くなりすいません。 こちら参考にさせて頂いたところ、上手く動作しました。 ありがとうございます。
kazuma-s

2022/08/01 16:09

クラス名は全角なんですか、半角なんですか? はっきりしてください。
guest

0

memcpy(&name, str[2], 20);

第二引数はアドレスですが、ここではcharとなってしまっています。

memcpy(&name, &str[2], 20);
あるいは
memcpy(&name, str+2, 20);
としましょう
#他も同様

投稿2022/07/23 23:41

y_waiwai

総合スコア87719

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

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

kekennnn

2022/07/24 02:00

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main() { FILE* fp; char str[256]; char class[4]; char name[64]; char gen[2]; char Tensu = 0; int tensu; int jap = 0; int math = 0; int eng = 0; int sum = jap + math + eng; printf("クラス\t氏名\t\t性別\t国語\t数学\t英語\t合計\t\n"); printf("------------------------------------------------------------\n"); fp = fopen("class.dat", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (!feof(fp)) { if (fgets(str, 256, fp) == NULL) { break; } memcpy(&class, &str, 2); memcpy(&name, &str[2], 20); memcpy(&gen, &str[22], 1); memcpy(&Tensu, &str[23], 9); tensu = atoi(&Tensu); memcpy(jap, &Tensu, 3); memcpy(math, &Tensu, 3); memcpy(eng, &Tensu,3); printf("%s\t %s\t\t %s\t %d\t %d\t %d\n ", &class, &name, &gen, math, eng, sum ); } fclose(fp); return 0; } ================================================ 修正したのですが、memcpy(math, &Tensu, 3);の部分で同様に『アクセス違反が発生』となってしまいました。
y_waiwai

2022/07/24 03:42

memcpy の第一引数もアドレスです。(それ、intぢゃん) memcpyという関数は何をするものか、ってのを調べてみよう おそらく課題か何かだと思いますが、まだまだ、ここらへんのメモリ操作に関することについて学習の必要があるかと
kazuma-s

2022/07/24 03:57

int jap = 0; int math = 0; int eng = 0; int sum = jap + math + eng; このような宣言をしておけば、あとで jap などの値が変わった時、sum の値も変わると思っているのですか?
kekennnn

2022/07/24 05:46

その認識でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問