この問題の見方について、いくつかの断片を紹介できます。
まずclass
、多くのオブジェクト指向プログラミング言語 (C++ を含む) では名前はキーワードであり、変数の名前にすることはできないため、変数に名前を使用することは避けます。
構造体 DBrecord
typedef を使用することをお勧めします。次に、「struct DBrecord」を使用せずに、「DBrecord」だけで構造体変数を宣言できます。しかし、それはオプションです。これはどのように見えるかです:
typedef struct {
int DBrecordID; // ID for each entry
char *lastName;
char *firstName;
char studentID[8];
...
} DBrecord;
ファイルからの読み込み
この宿題では、ファイルの先頭にレコードの数があるため、「余分な」注意を払う必要はありません。ロードするだけです。
ファイルが次のようになっているとします。
2
Doe John 12345678 senior 3.14159 2015
Carl Boss 32315484 junior 2.71 2013
したがって、ファイルに対して最初に行うことは、ファイルを開くことです。
ファイルを操作するポータブルな方法は、FILE ポインターを使用することです。それを見せてください(stdio.h
含める必要があります):
FILE *filePtr; // Define pointer to file
if((filePtr = fopen("records.txt", "r")) == NULL) // If couldn't open the file
{
printf("Error: Couldn't open records.txt file.\n"); // Printf error message
exit(1); // Exit the program
}
次に、 fgets() を使用して行単位で読み取るか、 fgetc() を使用して文字単位で読み取ることにより、ファイルから行単位で読み取ることができます。これは、レコード数を読み取る方法です (最初の行にあり、ファイルを開いたばかりであることを思い出してください。ファイルの先頭にいます)。
char buffer[100]; // Define the buffer
fgets(buffer, 100 /* size of buffer */, filePtr);
現在、バッファには最初の行 (\n 文字なし) - レコード数が含まれています。num の文字を整数に変換し続けます (ここstdlib.h
にも含める必要があります)。
int numOfRecords = atoi(buffer);
十分な DB レコードの割り当て
レコードの数がわかったので、それらに十分なスペースを割り当てることができます。ポインターの配列を使用します。
DBrecord **recs;
recs = (DBrecord **) malloc(sizeof(DBrecord *) * numOfRecords);
ポインターの配列を作成したので、個々のポインターをすべて DBrecord として割り当てる必要があります。使用サイクル:
int i;
for(i = 0; i < numOfRecords; i++)
{
recs[i] = (DBRecord *) malloc(sizeof(DBrecord));
}
これで、次のように配列要素 (= 個々のレコード) にアクセスできます。
recs[0]->lastname /* two possibilities */
*(recs[0]).lastname
など。
ファイルからの値で配列を埋める
これで、宿題を終わらせるためのすべてがわかりました。このようにして配列を埋めます:
int i;
for(i = 0; i < numOfRecords; i++)
{
// Content of cycle reads one line of a file and parses the values into recs[i]->type...
/* I give you small advice - you can use fgetc(filePtr); to obtain character by character from the file. As a 'deliminer' character you use space, when you hit newline, then the for cycle continues.
You know the order of stored values in the file, so it shouldn't be hard for you.
If you don't get it, let me now in comments */
}
なんとなく分かりやすくなりましたか?
編集: main の引数としてのファイル名
通常、引数 (値) をプログラムに「渡す」方法は 2 つあります。彼らです:
./program < records.txt // Here the file's name is passed to program on stdin
./program records.txt // Here the file's name is passed as value in `argv`.
もし選べるなら、2番目を強くお勧めします。したがって、main を次のように定義する必要があります。
int main(int argc, char *argv[]) // this is important!
{
// code
return 0;
}
argc
プログラムに渡された引数の数を示す整数です。argv
それらを格納する配列です。最初の引数がプログラムの名前であることを思い出してください。したがって、確認する必要がある場合は、次のようにします。
if(argc != 2)
{
printf("Number of arguments is invalid\n");
exit(1); // exit program
}
次に、文字列「records.txt」の代わりに関数にargv[1]
入れるだけです。fopen
編集 2: stdin からファイルの名前を読み取る
レコード ファイルの名前が 経由./program < records.txt
でプログラムに渡される場合、別の方法を実行する必要があります。つまり、"records.txt" (引用符なし) がプログラムの標準入力に渡されます (リダイレクトされます)。
したがって、これを処理するには、次のようにします。
char filename[50]; // buffer for file's name
scanf("%s", &filename); // reads standard input into 'filename' string until white character appears (new line, blank, tabulator).
次に、目的のファイルの名前をfilename
文字列で取得します。