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

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

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

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

Q&A

解決済

2回答

3559閲覧

C言語 指定バイト数の切り出し(固定長ファイルの読み込み)

watan

総合スコア13

C

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

0グッド

0クリップ

投稿2018/07/30 07:56

C言語で固定長ファイルを構造体に読み込む処理にて、指定バイト数の切り出しがうまく組めません。

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

typedef struct{
char sStr1[3] ;
char sNum[3] ;
char sDate[6] ;
}stTest ;

const char sLine[3][20] = { "xABCxx123xx180730xx","xXYZxx456xx180731xx","xEFGxx789xx180801xx" };
void main(){
stTest kTest[3] ;
int iLp;

for( iLp = 0; iLp < 3 ; iLp ++ ){ //2Bytes目から3バイト文字列を構造体に格納する。 strncpy( kTest[iLp].sStr1, &sLine[iLp][1], 3 ) ; //7Bytes目から3バイト文字列を構造体に格納する。 strncpy( kTest[iLp].sNum, &sLine[iLp][6], 3 ); //12Bytes目から6バイト文字列を構造体に格納する。 strncpy( kTest[iLp].sDate, &sLine[iLp][11], 6 ) ; printf( "sTr1[%s] sNum[%s] sDate[%s]\n", kTest[iLp].sStr1, kTest[iLp].sNum, kTest[iLp].sDate);

}
return ;
}


sTr1[ABC] sNum[123] sDate[180730]
sTr1[XYZ] sNum[456] sDate[180731]
sTr1[EFG] sNum[789] sDate[180801]

としたいのですが、上記を実行すると以下のような結果となります。
sTr1[ABC123180730@] sNum[123180730@] sDate[180730@] sTr1[XYZ456180731@] sNum[456180731@] sDate[180731@]
sTr1[EFG78918081x╗] sNum[78918081x╗] sDate[18081x╗]

どの部分が問題なのか、ご指導お願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

固定長のファイルを読み込む場合、たいていの場合は読み込まない部分も構造体のメンバとして定義しておいて、丸ごと読み込みます。

c

1typedef struct{ 2 char sDummy1[1] ; 3 char sStr1[3] ; 4 char sDummy2[2] ; 5 char sNum[3] ; 6 char sDummy3[2] ; 7 char sDate[6] ; 8 char sDummy4[2] ; 9}stTest ; 10 11stTest work; 12fread(&work, sizeof(work), 1, fp);

これを今回のコードに当てはめるとこんな感じでしょうか。

c

1typedef struct{ 2 char sDummy1[1] ; 3 char sStr1[3] ; 4 char sDummy2[2] ; 5 char sNum[3] ; 6 char sDummy3[2] ; 7 char sDate[6] ; 8 char sDummy4[2] ; 9}stTest ; 10 11const char sLine[3][20] = { "xABCxx123xx180730xx","xXYZxx456xx180731xx","xEFGxx789xx180801xx" }; 12void main(){ 13 stTest kTest[3] ; 14 int iLp; 15 16 for( iLp = 0; iLp < 3 ; iLp ++ ){ 17 memcpy(&kTest[iLp], &sLine(iLp), sizeof(stTest)); 18 printf( "sTr1[%.3s] sNum[%.3s] sDate[%.6s]\n", kTest[iLp].sStr1, kTest[iLp].sNum, kTest[iLp].sDate); 19 } 20 return ; 21}

ちなみに今ある構造体の定義のままでも上記のprintfを使えば期待通りになると思います。
要はNULL終端ではない文字列を出力しようとしているだけの問題です。

NULL終端文字列として取り込みたいのであれば、構造体の各メンバの領域を増やす必要があります。

c

1typedef struct{ 2 char sStr1[4] ; // 1バイト拡張 3 char sNum[4] ; // 1バイト拡張 4 char sDate[7] ; // 1バイト拡張 5}stTest ; 6 7const char sLine[3][20] = { "xABCxx123xx180730xx","xXYZxx456xx180731xx","xEFGxx789xx180801xx" }; 8void main(){ 9 stTest kTest[3] ; 10 int iLp; 11 12 // 領域全体を初期化しておく 13 memset(&kTest, 0x00, sizeof(kTest)); 14 15 for( iLp = 0; iLp < 3 ; iLp ++ ){ 16 //2Bytes目から3バイト文字列を構造体に格納する。 17 strncpy( kTest[iLp].sStr1, &sLine[iLp][1], 3 ) ; 18 19 //7Bytes目から3バイト文字列を構造体に格納する。 20 strncpy( kTest[iLp].sNum, &sLine[iLp][6], 3 ); 21 22 //12Bytes目から6バイト文字列を構造体に格納する。 23 strncpy( kTest[iLp].sDate, &sLine[iLp][11], 6 ) ; 24 25 printf( "sTr1[%s] sNum[%s] sDate[%s]\n", kTest[iLp].sStr1, kTest[iLp].sNum, kTest[iLp].sDate); 26 } 27 return ; 28} 29

投稿2018/07/30 08:37

ttyp03

総合スコア16996

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

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

watan

2018/07/30 10:29

大変わかりやすく解説いただきまして、ありがとうございました。 構造体にそのまま読み込むことが出来るのですね。サンプルまでご提示いただきとても助かりました。
guest

0

文字列とは終端に'\0'が必要です
ですんで、3バイトの文字列には、最低4バイト分の領域が必要となります
そこらへん修正してやり直してみてください

投稿2018/07/30 08:00

y_waiwai

総合スコア87719

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

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

watan

2018/07/30 10:26

ありがとうございました! 基本的な知識が不足しておりました。大変参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問