📄 getdata.cpp
字号:
/*************************************************************************
* Get case descriptions from data file
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "ErrorP.h"
char *FileName = "DF"; /* 默认的数据文件名 */
short ClassNum; /* 分类数目 */
char **ClassName; /* 类名 */
short AttNum; /* 最大属性数目 */
char **AttName; /* 属性名 */
short *AttValNum; /* 每个属性取值的最大个数 */
char ***AttValName; /* 属性值类型或名称 - AttValName[Att][0]中存储离散属性值的最大值 */
char *SpecialStatus; // 特征类型:IGNORE,DISCRETE,CONTINUOUS
short MaxDiscrValNum = 2; // 离散特征(数值类型)和集合特征的最大取值个数
int ItemNum; /* 读取的数据条数目 */
Description *Item; /* 读取的数据条内容 */
char Delimiter; /* 定界符 */
///////////////////////////////////////////////////////////////////////////////////////////////////
// 功能函数
///////////////////////////////////////////////////////////////////////////////////////////////////
char *CopyString( char *x)
{
char *s;
s = (char *) calloc(strlen(x)+1, sizeof(char));
if( s != NULL ) {
//printf( "Allocated Success\n" );
//free( s );
}
else {
printf( "Can't allocate memory\n" );
}
strcpy(s, x);
return s;
}
/////////////////////////////////////////////////////////////////////
// 在 List[First] 到 List[Last] 之间定位 Val 值的位置
/////////////////////////////////////////////////////////////////////
int Which(char *Val, char *List[], short First, short Last)
{
short n=First;
while ( n <= Last && strcmp(Val, List[n]) ) n++;
return ( n <= Last ? n : First-1 );
}
/////////////////////////////////////////////////////////////////////
// Read a name from file f into string s, setting Delimiter.
/////////////////////////////////////////////////////////////////////
#define SkipComment while ( ( c = getc(f) ) != '\n' )
#define Space(s) (s == ' ' || s == '\n' || s == '\t')
Boolean ReadName(FILE *f, char *s)
{
register char *Sp=s;
register int c;
/* 跳过空格和注释 */
while ( ( c = getc(f) ) == '|' || (c == ' ' || c == '\n' || c == '\t') ) {
if ( c == '|' ) {
/* 跳过注释信息 */
SkipComment;
}
}
/* 如果没有属性名返回FALSE, 定界符赋值=EOF(文件结束) */
if ( c == EOF ) { Delimiter = EOF; return FALSE; }
/**************************************************************************
* 读字符直到另一个分界符
* ':' 属性名与属性值之间的分界符
* ',' 属性值与数据条值之间的分界符
* '\n' 行结束
* '|' 注释分界符
* 'EOF' 文件结束分界符
**************************************************************************/
while ( c != ':' && c != ',' && c != '\n' && c != '|' && c != EOF ) {
if ( c == '.' ) {
if ( ( c = getc(f) ) == '|' || (c == ' ' || c == '\n' || c == '\t') ) break;
*Sp++ = '.';
}
if ( c == '\\' ) { c = getc(f); }
*Sp++ = c;
/* 跳过空格 */
if ( c == ' ' ) { while ( ( c = getc(f) ) == ' ' ) ; }
else { c = getc(f); }
}
if ( c == '|' ) SkipComment;
Delimiter = c;
while ( (*(Sp-1) == ' ' || *(Sp-1) == '\n' || *(Sp-1) == '\t') ) Sp--;
*Sp++ = '\0';
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// 读取类、特征的有关信息
///////////////////////////////////////////////////////////////////////////////
void GetNames()
{
FILE *File_Hander;
char Ch_FileName[100];
char Buffer[1000];
short v;
int ClassCeiling=100, AttCeiling=100, ValCeiling;
// 打开数据属性名文件 ///////////////////////////////////////////////////////
strcpy(Ch_FileName, FileName);
strcat(Ch_FileName, ".names");
if ( !(File_Hander=fopen(Ch_FileName, "r")) ) { Error(0, Ch_FileName, ""); }
// 从数据属性名文件获取类名 /////////////////////////////////////////////////////////
ClassName = (char **) calloc(ClassCeiling, sizeof(char *));
if( ClassName != NULL ) {
// printf( "Allocated Success\n" );
// free( ClassName );
}
else {
printf( "Can't allocate memory on ClassName!\n" );
exit(1);
}
ClassNum = -1;
do {
ReadName(File_Hander, Buffer);
if ( ++ClassNum >= ClassCeiling) {
ClassCeiling += 100;
ClassName = (char **) realloc(ClassName, ClassCeiling*sizeof(char *));
if( ClassName != NULL ) {
// printf( "Allocated Success\n" );
// free( ClassName );
}
else {
printf( "Can't allocate memory on ClassName!\n" );
exit(1);
}
}
ClassName[ClassNum] = CopyString(Buffer); // free(ClassName[ClassNum]);
} while ( Delimiter == ',' );
// 从数据属性名文件获取属性名和属性值 ///////////////////////////////////////////////
AttName = (char **) calloc(AttCeiling, sizeof(char *));
if( AttName != NULL ) {
// printf( "Allocated Success\n" );
// free( AttName );
}
else {
printf( "Can't allocate memory on AttName!\n" );
exit(1);
}
AttValNum = (short *) calloc(AttCeiling, sizeof(short));
AttValName = (char ***) calloc(AttCeiling, sizeof(char **));
SpecialStatus = (char *) malloc(AttCeiling);
AttNum = -1;
while ( ReadName(File_Hander, Buffer) ) {
// 每个特征一个循环 //////////////////////////////////////////////////
if ( Delimiter != ':' ) { Error(1, Buffer, ""); } // 格式定义":"
if ( ++AttNum >= AttCeiling ) {
/* 如果分配记录属性名的空间不够,则再分配空间 */
AttCeiling += 100;
AttName = (char **) realloc(AttName, AttCeiling*sizeof(char *));
AttValNum = (short *) realloc(AttValNum, AttCeiling*sizeof(short));
AttValName = (char ***) realloc(AttValName, AttCeiling*sizeof(char **));
SpecialStatus = (char *) realloc(SpecialStatus, AttCeiling);
}
// 获取特征名 ////////////////////////////////
AttName[AttNum] = CopyString(Buffer);
// 获取特征值及判断属性的特点 ////////////////
SpecialStatus[AttNum] = NIL;
AttValNum[AttNum] = 0;
ValCeiling = 100;
AttValName[AttNum] = (char **) calloc(ValCeiling, sizeof(char *));
do {
// 每个特征取值一个循环 ////////////////////////////////////////////////////
if ( ! ( ReadName(File_Hander, Buffer) ) ) Error(2, AttName[AttNum], "");
if ( ++AttValNum[AttNum] >= ValCeiling ) {
ValCeiling += 100;
AttValName[AttNum] = (char **) realloc(AttValName[AttNum], ValCeiling*sizeof(char *));
}
// 获取特征值名称,数组下标 AttValNum[AttNum] 从1开始 /////
AttValName[AttNum][AttValNum[AttNum]] = CopyString(Buffer);
} while ( Delimiter == ',' );
// 根据属性取值个数进行属性类别的处理 ///////////////////////////////////////////
if ( AttValNum[AttNum] == 1 ) {
// 如果属性只有一个取值: continous,discrete和ignore 三种类型 ///////
if ( ! strcmp(Buffer, "continuous") ) {
// "continuous" 类型
// 进行离散处理
SpecialStatus[AttNum] = CONTINUOUS;
}
else if ( ! memcmp(Buffer, "discrete", 8) ) {
// "discrete" 类型的属性处理
SpecialStatus[AttNum] = DISCRETE;
v = atoi(&Buffer[8]);
if ( v < 2 ) {
printf("** %s: illegal number of discrete values\n", AttName[AttNum]);
exit(1);
}
AttValName[AttNum] = (char **) realloc(AttValName[AttNum], (v+2)*sizeof(char *));
// DISCRETE 类型的特征值数组,设置相应离散属性的最大取值 /////////////////////////
AttValName[AttNum][0] = (char *) v;
if ( v > MaxDiscrValNum ) MaxDiscrValNum = v;
}
else {
if ( ! strcmp(Buffer, "ignore") ) {
/* "ignore" 类型的属性处理 */
SpecialStatus[AttNum] = IGNORE;
}
else {
/* 不能识别的属性类型 */
Error(3, AttName[AttNum], "");
}
}
// IGNORE,DISCRETE,CONTINUOUS 特征取值个数设置为 0 ///////////////////
AttValNum[AttNum] = 0;
}
else {
// 集合特征 ///////////////////////////////////////////////////////////
SpecialStatus[AttNum] = SET;
if ( AttValNum[AttNum] > MaxDiscrValNum ) MaxDiscrValNum = AttValNum[AttNum];
}
} /* end while */
fclose(File_Hander);
}
/////////////////////////////////////////////////////////////////////////////////////////
// 读训练数据
/////////////////////////////////////////////////////////////////////////////////////////
#define ITEM2K 2048
Description GetDescription(FILE *File_Hander)
{
short Att;
char name[500], *endname;
int Dv;
float Cv;
Description Dvec;
if ( ReadName(File_Hander, name) ) {
// 分配存储属性值的空间 //////////////////////////////////////////////
Dvec = (Description) calloc(AttNum+2, sizeof(AttValue));
if( Dvec == NULL ) {
printf("Can't allocate memory on sub Item.\n" );
exit(1);
}
// 读取各个特征的取值 ////////////////////////////////////////////////
for (Att = 0; Att <= AttNum; ++Att ) {
if ( SpecialStatus[Att] == IGNORE ) {
DVal(Dvec, Att) = 0;
}
else if ( AttValNum[Att] || SpecialStatus[Att] == DISCRETE ) {
// SET 特征 || DISCRETE 特征 /////////////////////////////////
if ( ! ( strcmp(name, "?") ) ) {
Dv = 0;
}
else {
/* 查找属性取值name在属性取值AttValName[Att]中的位置 */
Dv = Which(name, AttValName[Att], 1, AttValNum[Att]);
if ( ! Dv ) {
// Dv=0 表示属性出现新的取值 //////////////////////////
if ( SpecialStatus[Att] == DISCRETE ) {
// DISCRETE 特征
Dv = ++AttValNum[Att]; /* 离散属性取值个数加1 */
if ( Dv > (int) AttValName[Att][0] ) {
printf("\nToo many values for %s (max %d)\n", AttName[Att], (int) AttValName[Att][0]);
exit(1);
}
AttValName[Att][Dv] = CopyString(name);
}
else {
// SET 的特征不允许出现新的取值
Error(4, AttName[Att], name);
}
}
}
DVal(Dvec, Att) = Dv;
}
else {
// 连续数值处理
if ( ! ( strcmp(name, "?") ) ) {
/* 未知的连续值 */
Cv = Unknown;
}
else {
Cv = (float) strtod(name, &endname);
if ( endname == name || *endname != '\0' ) {
Error(4, AttName[Att], name);
}
}
CVal(Dvec, Att) = Cv;
}
ReadName(File_Hander, name);
} /* for end */
/* 读取类值 */
if ( (Dv = Which(name, ClassName, 0, ClassNum)) < 0 ) {
Error(5, "", name);
Dv = 0;
}
Class(Dvec) = Dv;
return Dvec; /* 读取了一条完整的数据并返回 */
}
else {
return NIL;
}
}
void GetData(char *Extension)
{
FILE *File_Hander;
char ch_FileName[100];
int Item_count, ItemSpace;
// 打开数据文件 ////////////////////////////////////////////////////////////////
strcpy(ch_FileName, FileName);
strcat(ch_FileName, Extension);
if ( ! ( File_Hander = fopen(ch_FileName, "r") ) ) Error(0, ch_FileName, "");
Item_count=0;
ItemSpace=0;
do {
ItemNum = Item_count;
if ( Item_count >= ItemSpace ) {
if ( ItemSpace ) {
ItemSpace += ITEM2K; /* 每次追加2k条空间 */
/* 追加分配空间 */
if( (Item = (Description *) realloc(Item, ItemSpace*sizeof(Description)) ) == NULL ) {
printf( "Can't realloc memory on Item\n" );
exit(1);
}
}
else {
/* 第一次分配空间 */
if( (Item = (Description *) malloc((ItemSpace=ITEM2K)*sizeof(Description)) ) == NULL ) {
printf( "Can't malloc memory on Item\n" );
exit(1);
}
}
}
Item[Item_count] = GetDescription(File_Hander);
} while ( Item[Item_count] != NIL && ++Item_count );
fclose(File_Hander);
ItemNum = Item_count - 1; /* 读取的最大数据条数 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -