#include <iostream>
using namespace std;
#define StructArrarySize 5 // 老師數量
#define StudentNum 3 // 每位老師的學生的數量
#define FileName "f:/1.txt" // 文件路徑和名稱
#define LineMaxLen 1024 // 每行最大長讀
#define KeyMaxLen 20 // key的最大長度
typedef struct _AdvTeacher
{
char *name;
char *tile;
int age;
char *addr;
char **student;
}AdvTeacher;
int CreateStructArray(AdvTeacher **, int, int); //客戶端初始化結構體數組
int FreeStructArray(AdvTeacher **, int, int); //客戶端釋放結構體數組內存
int StructWriteFile(const char *, const AdvTeacher *, int, int); //結構體寫入文件
int StructFileRead(char *pFileName, char *pKey, char *pValue, int *pValueLen); //讀取結構體文件
void ReadFileMenu(void); //讀取文件菜單
int main(void)
{
int rv = 0;
AdvTeacher * t = NULL;
rv = CreateStructArray(&t, StructArrarySize, StudentNum); //被調函數分配內存
if (rv != 0)
{
printf("func: CreateStructArray() _%d_error_\n ", rv);
goto End;
}
for (int i = 0; i < StructArrarySize; ++i) // 客戶端初始化賦值
{
printf("請輸入第%d位老師的姓名: ", i+1);
scanf("%s", t[i].name);
printf("請輸入第%d位老師的年齡: ", i+1);
scanf("%d", &(t[i].age));
printf("請輸入第%d位老師的職務: ", i+1);
scanf("%s", t[i].tile);
printf("請輸入第%d位老師的地址: ", i+1);
scanf("%s", t[i].addr);
for (int j = 0; j < StudentNum; ++j)
{
printf("請輸入第%d位老師的第%d位學生的姓名: ", i+1, j+1);
scanf("%s", t[i].student[j]);
}
}
char * fileName = FileName;
rv = StructWriteFile(fileName, t, StructArrarySize, StudentNum); // 結構體寫入文件
if (rv != 0)
{
printf("func: StructWriteFile() _%d_error_\n ", rv);
goto End;
}
ReadFileMenu(); //讀取結構體文件
End:
rv = FreeStructArray(&t, StructArrarySize, StudentNum);
if (rv != 0)
{
printf("致命錯誤: FreeStructArray()執行失敗!\n _%d_error_\n", rv);
}
system("pause");
return rv;
}
// 創建結構體數組
int CreateStructArray(AdvTeacher **t, int structArrarySize, int studentNum)
{
int rv = 0;
if (NULL == t)
{
rv = -1;
return rv;
}
AdvTeacher * temp = NULL;
temp = (AdvTeacher *)malloc(structArrarySize * sizeof(AdvTeacher));
if (NULL == temp)
{
rv = -2;
return rv;
}
for (int i = 0; i < structArrarySize; ++i)
{
temp[i].name = (char *)malloc(256 * sizeof(char));
temp[i].addr = (char *)malloc(256 * sizeof(char));
temp[i].tile = (char *)malloc(256 * sizeof(char));
if (NULL == temp[i].name || NULL ==temp[i].addr || NULL == temp[i].tile)
{
rv = -3;
return rv;
}
temp[i].student = (char **)malloc(studentNum * sizeof(char *));
if (NULL == temp[i].student)
{
rv = -4;
return rv;
}
for (int j = 0; j < studentNum; ++j) //創建學生內存塊
{
(temp[i].student)[j] = (char *)malloc(256 * sizeof(char));
if (NULL == (temp->student)[j])
{
rv = -5;
return rv;
}
}
}
*t = temp;
return rv;
}
// 銷毀結構體數組
int FreeStructArray(AdvTeacher **t, int structArrarySize, int studentNum)
{
int rv = 0;
AdvTeacher *temp = *t;
for (int i = 0; i < structArrarySize; ++i)
{
for (int j = 0; j < studentNum; ++j) // 銷毀學生內存塊
{
if (NULL != temp[i].student[j])
{
free(temp[i].student[j]);
}
}
if (NULL != temp[i].addr && NULL != temp[i].name && NULL != temp[i].tile && NULL != temp[i].student)
{
free(temp[i].addr);
free(temp[i].name);
free(temp[i].tile);
free(temp[i].student);
}
}
if (NULL != temp)
{
free(temp);
*t = NULL; //間接賦值 通過*(實參的地址), 去間接修改實參的值 為null
}
return rv;
}
// 結構體文件寫入
int StructWriteFile(const char *fileName, const AdvTeacher *t, int structArrarySize, int studentNum)
{
int rv = 0;
if (NULL == fileName || NULL == t)
{
rv = -1;
return rv;
}
FILE *fp = NULL;
fp = fopen(fileName, "w+");
if (NULL == fp)
{
printf("func: StructWriteFile() _文件打開失敗_\n");
goto End;
}
char buf[1024];
for (int i = 0; i < structArrarySize; ++i)
{
sprintf(buf, "name%d = %s\n", i + 1, t[i].name);
fputs(buf, fp);
sprintf(buf, "age%d = %d\n", i + 1, t[i].age);
fputs(buf, fp);
sprintf(buf, "tile%d = %s\n", i + 1, t[i].tile);
fputs(buf, fp);
sprintf(buf, "addr%d = %s\n", i + 1, t[i].addr);
fputs(buf, fp);
for (int j = 0; j < studentNum; ++j)
{
sprintf(buf, "%dstudentname%d = %s\n",i+1, j +1, t[i].student[j]); //第幾個老師的第幾個學生
fputs(buf, fp);
}
}
End:
if (NULL != fp)
{
fclose(fp);
}
return rv;
}
// 結構體文件讀出
int StructFileRead(char *pFileName, char *pKey, char *pValue, int *pValueLen)
{
int rv = 0;
FILE *fp = NULL;
char lineBuf[LineMaxLen];
char *pTmp = NULL, *pBegin = NULL, *pEnd = NULL;
if (pFileName==NULL || pKey==NULL || pValue==NULL || pValueLen==NULL)
{
rv = -1;
printf("StructFileRead() err. param err \n");
goto End;
}
fp = fopen(pFileName, "r");
if (fp == NULL)
{
rv = -2;
printf("fopen() err. \n");
goto End;
}
while (!feof(fp))
{
//讀每一行
memset(lineBuf, 0, sizeof(lineBuf));
pTmp = fgets(lineBuf, LineMaxLen, fp);
if (pTmp == NULL)
{
break;
}
//不含=, 非配置項
pTmp = strchr(lineBuf, '=');
if (pTmp == NULL)
{
continue;
}
//key是否在本行
pTmp = strstr(lineBuf, pKey);
if (pTmp == NULL)
{
continue;
}
//調整到=右邊,取value准備
pTmp = strchr(lineBuf, '=');
if (pTmp == NULL)
{
continue;
}
pTmp = pTmp + 1;
//獲取value 起點
while (true)
{
if (*pTmp == ' ')
{
pTmp ++ ;
}
else
{
pBegin = pTmp;
if (*pBegin == '\n')
{
//沒有配置value
printf("配置項:%s 沒有配置value \n", pKey);
goto End;
}
break;
}
}
//獲取valude結束點
while (true)
{
if ((*pTmp == ' ' || *pTmp == '\n'))
{
break;
}
else
{
pTmp ++;
}
}
pEnd = pTmp;
//賦值
*pValueLen = pEnd-pBegin;
memcpy(pValue, pBegin, pEnd-pBegin);
pValue[pEnd - pBegin] = '\0';
break;
}
End:
if (fp != NULL)
{
fclose(fp);
}
return rv;
}
// 文件讀出菜單
void ReadFileMenu(void)
{
char pKey[256];
char pValue[1024];
int pValueLen = 0;
int rv = 0;
while (true)
{
strcpy(pValue, "不存在匹配項");
system("cls");
printf("\t********************讀取文件菜單************************\n");
printf("\t格式:如第一個老師的姓名: name1\n");
printf("\t格式:如第一個老師的第二個學生的姓名: 1studentname2\n");
printf("\t退出請輸入: quit \n\n");
printf("\t********************讀取文件菜單************************\n");
printf("\t\n");
printf("\t請輸入需要讀取數據: ");
scanf("%s", pKey);
if (strlen(pKey) < 4)
{
printf("\t非法輸入!請重新輸入\n");
system("pause");
continue;
}
if (0 == strcmp("quit", pKey))
{
break;
}
rv = StructFileRead(FileName, pKey, pValue, &pValueLen);
if (0 != rv)
{
rv = -1;
printf("func: StructFileRead() _%d_error_\n", rv);
return;
}
printf("\n\t%s = %s\n\n", pKey, pValue);
printf("\t請按任意鍵繼續!\n");
strcpy(pValue, "不存在匹配項"); //覆蓋上一次pValue的值,這樣就可以避免下次如果沒有找到pValue,這次的值不會殘留到下一個pValue
system("pause");
}
return;
}