問題庫(QAS)用外部的配置文件保存,每次運行前先載入庫中已經建立的問題。然後再進入操作選擇。
完整代碼如下:
/*
1. 暫時不考慮漢字;
2. 可以用鏈表優化;
3. 將每壹種操作封裝成壹個函數;
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
//////////////////////////////////////////////////////////////////////////
// 字符串最大長度
#define MAX_STR_LEN 2048
// 題庫上限
#define MAX_QAS_LEN 1024
// 配置文件路徑
#define QAS_FILE_PATH "d:\\qasconfig.txt"
//////////////////////////////////////////////////////////////////////////
// 問題結點
typedef struct tagQASNode
{
char Question[MAX_STR_LEN];
char Answer[MAX_STR_LEN];
double Score;
bool IsAnswered;
}QASNode;
// 問題庫
QASNode *g_QASLib[MAX_QAS_LEN];
int g_QASIndex = 0;
//////////////////////////////////////////////////////////////////////////
// 添加
bool InsertToLib(char *pQuestion, char *pAnswer, double score)
{
if (pQuestion == NULL || strcmp(pQuestion, "") == 0 || pAnswer == NULL)
return false;
QASNode *pNewNode = (QASNode*)malloc(sizeof(QASNode));
memset(pNewNode, 0L, sizeof(QASNode));
strcpy_s(pNewNode->Question, pQuestion);
strcpy_s(pNewNode->Answer, pAnswer);
pNewNode->Score = score;
g_QASLib[g_QASIndex++] = pNewNode;
return true;
}
// 隨機壹個不重復的序號
int GetQuestionIndex()
{
int retVal = -1;
int tryCnt = 0;
while (tryCnt++ < g_QASIndex)
{
int randVal = rand() % (g_QASIndex+1);
if ( !g_QASLib[randVal]->IsAnswered )
{
retVal = randVal;
break;
}
}
return retVal;
}
//////////////////////////////////////////////////////////////////////////
int main()
{
// 打開配置文件
FILE *pStream = NULL;
if( fopen_s(&pStream, QAS_FILE_PATH, "a+") != 0 )
{
printf_s("Open the config file failed.\n");
return -1;
}
// 加載已有的QAS
fseek(pStream, 0L, SEEK_END);
int fileSize = ftell(pStream);
fseek(pStream, 0L, SEEK_SET);
while ( !feof(pStream) && fileSize )
{
if (g_QASIndex < MAX_QAS_LEN)
{
char tempQ[MAX_STR_LEN] = {0}, tempA[MAX_STR_LEN] = {0};
double tempS = 0.0;
fscanf_s(pStream, "%s", tempQ, MAX_STR_LEN);
fscanf_s(pStream, "%s", tempA, MAX_STR_LEN);
fscanf_s(pStream, "%lf", &tempS);
InsertToLib(tempQ, tempA, tempS);
}
}
// 累計得分
double totalSocore = 0.0;
int currentIndex = -1;
// 獲取操作類型
int opType = -1;
printf_s("請選擇操作類型:\n 1. 回答問題;\n 2. 查看分數;\n 3. 添加新問題;\n 4. 查看問題庫裏的問題和答案;\n 0. 退出系統;\n\n");
while (opType != 0)
{
printf_s("請選擇操作類型: ");
scanf_s("%d", &opType);
switch (opType)
{
case 0:
if (pStream)
{
fclose(pStream);
}
break;
case 1:
{
if (g_QASIndex == 0)
{
printf("問題庫為空, 請試著添加壹個問題吧!\n");
break;
}
srand((unsigned)time(NULL));
currentIndex = GetQuestionIndex();
if (currentIndex != -1)
{
printf_s("Question: %s\n", g_QASLib[currentIndex]->Question);
printf_s("Input answer:");
char tempA[MAX_STR_LEN] = {0};
fflush(stdin);gets_s(tempA, MAX_STR_LEN);
if (strcmp(tempA, g_QASLib[currentIndex]->Answer) == 0)
{
printf("Right!\n");
totalSocore += g_QASLib[currentIndex]->Score;
g_QASLib[currentIndex]->IsAnswered = true;
}
else
{
printf("Wrong!\n");
}
}
else
{
printf("妳已經答對了所有的問題!\n");
}
}
break;
case 2:
{
if (currentIndex != -1)
{
printf("Quest: %s\nScore = %.2f\n", g_QASLib[currentIndex]->Question, g_QASLib[currentIndex]->Score);
}
else
{
printf("請先選擇\"回答問題\"!\n");
}
}
break;
case 3:
{
// 壹次只添加壹個問題
if (g_QASIndex < MAX_QAS_LEN)
{
char tempQ[MAX_STR_LEN] = {0}, tempA[MAX_STR_LEN] = {0};
double tempS = 0.0;
printf_s("請輸入新問題:\n");
fflush(stdin);gets_s(tempQ, MAX_STR_LEN);
printf_s("請輸入對應的答案:\n");
fflush(stdin);gets_s(tempA, MAX_STR_LEN);
printf_s("請輸入對應的分值:\n");
fflush(stdin);scanf_s("%lf", &tempS);
InsertToLib(tempQ, tempA, tempS);
// 添加到題庫
fprintf_s(pStream, "%s %s %f\n", tempQ, tempA, tempS);
}
}
break;
case 4:
{
if (g_QASIndex == 0)
{
printf("問題庫為空, 請試著添加壹個問題吧!\n");
break;
}
for (int i=0; i<g_QASIndex; ++i)
{
printf("第%d個:\nQ:%s\nA:%s\nS:%.2f\n", i+1, g_QASLib[i]->Question, g_QASLib[i]->Answer, g_QASLib[i]->Score);
}
}
break;
default:
break;
}
}
printf("\n");
return 0;
}
運行起來後先建立問題庫!