📄 data_lgr.cpp
字号:
}
//-------------------------------------------------------------------------------------
// Destructor: ~CDataLogger
// This destructor closes the data file (which forces writing to the disk from
// the operating system's file buffer on PC's and such) and frees up memory.
CDataLogger::~CDataLogger (void)
{
if (FileHandle != NULL)
{
Flush (); // This writes data that's been taken to a file
fclose (FileHandle); // This line flushes the data file to disk
}
delete ErrorString;
delete Separator;
delete TitleString;
// Delete all the array objects which are held in the list of log arrays
for (CLogArray* pCur = (CLogArray*)GetHead (); pCur != NULL;
pCur = (CLogArray*)GetNext ())
delete (pCur);
this->CBasicList::~CBasicList (); // Call the basic list object destructor
}
//-------------------------------------------------------------------------------------
// Function: DefineData
// The user program calls this function to define the data items which go into
// the data columns in the list of data to be saved by the logger.
void CDataLogger::DefineData (int NumColumns, ...)
{
va_list Parameters; // List of the function's parameters
int Index; // Index number counts through the columns
LogDataType ColumnType; // Type of data to be stored in each column
// Use va_arg macros to get each column's data type; then create column arrays
va_start (Parameters, NumColumns);
for (Index = 0; Index < NumColumns; Index++)
{
// Get the column type out of the argument list
ColumnType = va_arg (Parameters, LogDataType);
// Call constructor to create the new log array object for this column
CLogArray *pNewArray = new CLogArray (ColumnType, ArrayType, ArraySize);
// Now call the Insert() method this object inherited from CListObj. Insert()
// will place this column at the end of the list of columns.
CBasicList::Insert ((void*)pNewArray);
}
va_end (Parameters);
}
//-------------------------------------------------------------------------------------
// Friend function: DefineLoggerData
// This is a version of DefineData() which is implemented as a friend function
// instead of a member function so that it can be called with a C style call
// rather than requiring the user to use a C++ style member function call.
void DefineLoggerData (CDataLogger* apLogger, int NumColumns, ...)
{
va_list Parameters; // List of the function's parameters
int Index; // Index number counts through the columns
LogDataType ColumnType; // Type of data to be stored in each column
// Use va_arg macros to get each column's data type; then create column arrays
va_start (Parameters, NumColumns);
for (Index = 0; Index < NumColumns; Index++)
{
// Get the column type out of the argument list
ColumnType = va_arg (Parameters, LogDataType);
// Call constructor to create the new log array object for this column
CLogArray *pNewArray = new CLogArray (ColumnType, apLogger->ArrayType,
apLogger->ArraySize);
// Now call the Insert() method this object inherited from CListObj. Insert()
// will place this column at the end of the list of columns.
apLogger->CBasicList::Insert ((void*)pNewArray);
}
va_end (Parameters);
}
//-------------------------------------------------------------------------------------
// Function: AddTitle
// This function creates a title for the log which will be written at the top of
// the output file.
void CDataLogger::AddTitle (char *aString)
{
*TitleString << aString; // Add text to the title string
}
//-------------------------------------------------------------------------------------
// Function: AddLineNumbers
// If the user calls this function, line numbers will be turned on - this means
// that when the data is printed to a file, integer line numbers will be printed
// in the leftmost column.
void CDataLogger::AddLineNumbers (void)
{
WriteLineNumbers = TRUE;
}
//-------------------------------------------------------------------------------------
// Function: SetSeparator
// This function allows the user to change the text which comes between the
// columns - the default is a comma for a comma-separated-variable file.
void CDataLogger::SetSeparator (char *aString)
{
*Separator = aString;
}
//-------------------------------------------------------------------------------------
// Function: DiscardData
// This function resets the arrays so that they are in the empty state. The
// effect is to throw away any data which we've
void CDataLogger::DiscardData (void)
{
CLogArray *pCol; // Pointer to data column in list
// The data has been retreived, so set pointers to first line to start over
for (pCol = (CLogArray *)GetHead (); pCol != NULL; pCol = (CLogArray *)GetNext ())
pCol->Flush ();
LinesSaved = 0;
}
//-------------------------------------------------------------------------------------
// Function: Flush
// This function writes the data in the arrays to the data file.
void CDataLogger::Flush (void)
{
unsigned LineCounter; // Counts lines in arrays
CLogArray *pCol; // Pointer to data column in list
// Write stuff to file only if there's a file associated with this logger
if (FileHandle != NULL)
{
// If titles have been turned on, write the file title on the first line.
// Then clear the title so it doesn't get written again
TitleString->WriteToFile (FileHandle);
*TitleString = "";
fprintf (FileHandle, "\n");
// If there are any errors, write them next, then a linefeed
ErrorString->WriteToFile (FileHandle);
fprintf (FileHandle, "\n");
// Check the columns for errors (such as wrong type of data) and reset them
pCol = (CLogArray *)GetHead ();
while (pCol != NULL)
{
fprintf (FileHandle, "%s", pCol->GetErrorString ());
pCol->ResetRead ();
pCol = (CLogArray *) GetNext ();
}
// If column headers have been activated, write the headers on the next line.
// If line number column is turned on, its header will be "Line"
if (WriteHeaders == TRUE)
{
if (WriteLineNumbers == TRUE) // Write line number header
{ // above the first column
fprintf (FileHandle, "Line");
Separator->WriteToFile (FileHandle);
}
for (pCol = (CLogArray *)GetHead (); pCol != NULL;
pCol = (CLogArray *)GetNext ())
{
pCol->WriteHeader (FileHandle); // Write each header string,
Separator->WriteToFile (FileHandle); // then write separator text,
}
fprintf (FileHandle, "\n"); // Go down to first data line
WriteHeaders = FALSE; // Only write headers once.
}
// For each line in the arrays, get the data and write it to the file
for (LineCounter = 0; LineCounter < LinesSaved; LineCounter++)
{
// If we're supposed to write line numbers, put them first on this line
if (WriteLineNumbers == TRUE)
{
fprintf (FileHandle, "%u", LineCounter);
Separator->WriteToFile (FileHandle);
}
// Now step through all the columns, writing the data from each
pCol = (CLogArray *) GetHead ();
while (pCol != NULL)
{
fprintf (FileHandle, "%s", pCol->GetData ());
Separator->WriteToFile (FileHandle);
pCol = (CLogArray *) GetNext ();
}
fprintf (FileHandle, "\n");
}
} // End of the file-writing "if"
// Call function to empty out the data arrays
DiscardData ();
}
//-------------------------------------------------------------------------------------
// Function: Rewind
// This function resets the pointers in the data arrays so that the data which
// has already been taken can be read all over again.
void CDataLogger::Rewind (void)
{
CLogArray *pCol; // Pointer to data column in list
// The data has been retreived, so set pointers to first line to start over
for (pCol = (CLogArray *)GetHead (); pCol != NULL; pCol = (CLogArray *)GetNext ())
{
pCol->Rewind ();
}
// Set the number of lines saved back to the maximum number available
LinesSaved = MaxLinesSaved;
}
//-------------------------------------------------------------------------------------
// Function: GetNumLines
// This function returns the number of lines of data which can be read from the
// buffer.
unsigned CDataLogger::GetNumLines (void)
{
return (LinesSaved);
}
//-------------------------------------------------------------------------------------
// Function: LogDataLine
// This is the standard function for saving data to the logger. The user calls
// LogDataLine (pLogger, data1, data2, ...) where the 'dataX' parameters are the
// data to be saved. The number of data items in the function call MUST equal
// the number of columns the logger stores. This function returns the number of
// data items saved or a negative number if there were problems saving the data.
int SaveLoggerData (CDataLogger* pLogger, ...)
{
va_list Parameters; // Parameters given to this function
CLogArray* pCol; // Pointer to a log column object
va_start (Parameters, pLogger); // Begin variable-argument processing
// For each column to which a point is saved, get the data from an argument in
// the argument list and then move to the next argument
pCol = (CLogArray*)(pLogger->GetHead ());
while (pCol != NULL)
{
// A different call of va_arg is required for each type of parameter
switch (pCol->GetDataType ())
{
case LOG_INT:
*pCol << va_arg (Parameters, int);
break;
case LOG_LONG:
*pCol << va_arg (Parameters, long);
break;
// Floats get promoted to doubles when they're passed as parameters, so
// we have to convert them back to floats before saving
case LOG_FLOAT:
*pCol << (float)(va_arg (Parameters, double));
break;
case LOG_DOUBLE:
*pCol << va_arg (Parameters, double);
break;
case LOG_POINTER:
*pCol << va_arg (Parameters, void*);
break;
default:
va_end (Parameters);
return (-1);
}
pCol = (CLogArray*)(pLogger->GetNext ());
}
// Increment the number of items saved, unless we've filled the whole buffer
if ((pLogger->ArrayType == LOG_FINITE) || (pLogger->ArrayType == LOG_CIRCULAR))
{
if (pLogger->LinesSaved < pLogger->ArraySize)
{
pLogger->LinesSaved++;
pLogger->MaxLinesSaved++;
}
}
else if (pLogger->ArrayType == LOG_EXPANDING)
{
pLogger->LinesSaved++;
pLogger->MaxLinesSaved++;
}
// If everything worked OK, close the parameter processor and return
va_end (Parameters);
return (pLogger->HowMany ());
}
//-------------------------------------------------------------------------------------
// Function: GetDataLine
// This is the standard function for retreiving data from the logger. The user
// calls GetDataLine (pLogger, &data1, &data2, ...) where the '&dataX' parameters
// are *pointers* to places to which the retreived data goes. The number of data
// items in the function call MUST equal the number of columns the logger stores.
// This function returns the number of data items retreived or a negative number
// if there were problems getting the data out.
int GetLoggerData (CDataLogger* pLogger, ...)
{
va_list Parameters; // Parameters given to this function
CLogArray* pCol; // Pointer to a log column object
void* pData; // Data pointer from argument list
va_start (Parameters, pLogger); // Begin variable-argument processing
// For each column, get the location from an argument in the argument list
pCol = (CLogArray*)(pLogger->GetHead ());
while (pCol != NULL)
{
// Get a pointer to the data from the command line
pData = va_arg (Parameters, void*);
// A different call of va_arg is required for each type of parameter
LogDataType aType = pCol->GetDataType ();
if (aType == LOG_INT)
*pCol >> (int*)pData;
else if (aType == LOG_LONG)
*pCol >> (long*)pData;
else if (aType == LOG_FLOAT)
*pCol >> (float*)pData;
else if (aType == LOG_DOUBLE)
*pCol >> (double*)pData;
else if (aType == LOG_POINTER)
*pCol >> (void**)pData;
else
{
va_end (Parameters);
return (-1);
}
pCol = (CLogArray*)(pLogger->GetNext ());
}
// If everything worked OK, close the parameter processor and return
va_end (Parameters);
pLogger->LinesSaved--;
return (pLogger->HowMany ());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -