これは私のa.txt
ファイルで、合計3行です。余分なスペースや印刷できない文字は含まれません。
David Joans
018976
David12
これはC
このファイルを読み取るために使用するコードです。このコードを読むためにその中に構造を作成しました。パスワード::
#include<stdio.h>
#include<stdlib.h>
#pragma pack(1)
typedef struct info {
char name[15];
int num;
char pass[15];
}info;
int main(int argc, char const* argv[])
{
FILE* fp = NULL;
if (fp = fopen("a.txt", "r")) {
info var;
fread(&var, 1, sizeof(var), fp);
printf("%s\n%d\n%s\n", var.name, var.num, var.pass);
}
else {
perror("File can not be opened!!\n");
exit(EXIT_FAILURE);
}
return 0;
}
出力は次のとおりです。
David Joans
018976
David12
171325241
David12
プログラムの実際の問題は何ですか?私が理解するのを手伝ってください。
答え1
ファイルのバイナリ表現は構造体の実際のバイナリ表現と一致する必要はありませんinfo
。コンパイラは、構造体フィールド間にパディングスペースを自由に使用できます。したがって、目的の操作を実行する唯一の信頼できる方法は、ファイル内の各フィールドを個別に読み取り、構造内の対応するフィールドに割り当てることです。このような:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma pack(1)
typedef struct info {
char name[15];
int num;
char pass[15];
}info;
int main(int argc, char const* argv[])
{
FILE* fp = NULL;
if (fp = fopen("a.txt", "r")) {
info var;
char num_str[15];
char *endl_ptr;
fgets (var.name, sizeof (var.name), fp);
fgets (num_str, sizeof (num_str), fp);
fgets (var.pass, sizeof (var.pass), fp);
/* parse num_str into an integer */
var.num = strtol(num_str, NULL, 10);
/* replace the trailing endline character by a NULL */
if ((endl_ptr = strchr (var.name, '\n')))
*endl_ptr = '\0';
if ((endl_ptr = strchr (var.pass, '\n')))
*endl_ptr = '\0';
printf("%s\n%d\n%s\n", var.name, var.num, var.pass);
}
else {
perror("File can not be opened!!\n");
exit(EXIT_FAILURE);
}
return 0;
}
あるいは、実際のバイナリ表現が構造のバイナリ表現と一致するファイルがある場合もあります。たとえば、info
すでに構造化されたプログラムでファイルが生成されている場合、単純な構造ファイルはトリックをwrite
実行します。ただし、これは他のシステムに移植することはできません。
答え2
ファイルからfread
27バイトを読みます。これはすべてで、sizeof(var)がint + 4と2のパディングの場合は2 x 15より大きいためです。fread
読み込んだバイト数を返します。通常、この数を確認してください。
fread
void *ptr
それが何を意味するのか分からない。改行struct info
を削除せずに\0
NUL文字で文字列を終了せず、数値文字列をint
。占有されたメモリ空間の構造について。
string
関数を使用して直接バイトチャンクを解析する必要がありますstrtol
(両方のマニュアルページがあります)。したがって、中間配列を読む必要がありますchar buf [80];
。
出力の最初の3行はフル入力です。幸いなことに、誤ってNUL文字に遭遇してもプログラムは中断されません。
4行目はおそらくintからアクセスされるバイト「976D」ですinfo.num
。 CPUがリトルエンディアンなので、バイト順が逆です。
5行目は再アクセスでinfo.pass
、ここで入力の最後の行が終わります。
fread(&var, 1, sizeof(var), fp);
ファイルから36バイトのデータをインポートし、&var
ポインタが指定した場所に連続して保存します。 &varがどのような構造を指しているのか、受信領域がどれだけ大きいのかわかりません(または気にしません)。var
はいただメモリアドレス - サイズまたはタイプが添付されていません。また、テキストファイルがsizeof(var)
。
渡すまた訪れるprintf("%s\n%d\n%s\n", var.name, var.num, var.pass);
、一部のデータを複数回出力するという意味です。printf
構造体の各部分のアドレスを知らせますが、それでも構造体メンバーの種類や長さはわかりません。終了していない文字列をvar.name
取得します。みんな入力データ。その後、var.num
入力データの16バイト目から始めて、4バイトのテキストを使用し、それを意味のある整数と誤って考えます。その後、var.pass
入力のバイト20から再開し、終了していない別の文字列を出力します。