Here's my assignment:
Write a program that takes a filename as its only command line argument and prints the results to
std::out
formatted as follows:
- The first line of the output should be whether or not the checksum passed ("Checksum passed", "Checksum failed")
- If the checksum passed, the rest of the file will contain the parsed data. Print label value pairs separated by a colon for each field, one per line (all numbers should be represented as decimals).
An expected output file is provided for the first binary file to demonstrate format.
File structure (Little Endian):
size: 4 bytes entry count: 2 bytes --- entry --- first name length: 4 bytes first name: first name length bytes last name length: 4 bytes last name: last name length bytes flags: 1 byte * age: 1 byte * height: 1 byte ------------- zero padding: x bytes checksum: 4 bytes * = optional
Field descriptions:
size: Total number of bytes in the file
entry count: Number of entries in the file
entry
first name length: Number of characters in the following first name string since it is not NULL terminated
first name: Non-null terminated string
last name length: Number of characters in the following last name string since it is not NULL terminated
last name: Non-null terminated string
flags: Bit mask which indicates presence of either age or height fields.
- age field present
- height field present
age: Age in years. Optional field.
height: Height in inches. Optional field.
zero padding - The file is zero padded to ensure 4 byte alignment.
checksum: This value is calculated by summing every four bytes of the data (not including the actual checksum value)
FileParser.cpp
// FileParser.cpp : Defines the entry point for the console application.
//
#include<iostream>
#include <string>
#include <fstream>
#include <sstream>
void ParseFile(char* dataBuffer);
int main(int argc, char *argv[])
{
std::string inputFileName = argv[1];
std::ifstream inputFile(inputFileName, std::ios::binary | std::ios::ate);
if (inputFile.good())
{
//get File size
std::streamoff size = inputFile.tellg();
char *data = new char[size];
inputFile.seekg(0, std::ios::beg);
inputFile.read(data, size);
inputFile.close();
int checkSum = 0;
for (int i = 4; i <= size - 4; i = i + 4)
{
checkSum += (data[i - 1] << 24) |
(data[i - 2] << 16) |
(data[i - 3] << 8) |
(data[i - 4]);
}
int checksumfromFile = 0;
memcpy(&checksumfromFile, &data[size - 4], sizeof(int));
if (checkSum == checksumfromFile)
{
std::cout << "Checksum passed" << std::endl;
ParseFile(data);
}
else
std::cout << "Checksum Failed" << std::endl;
}
return 0;
}
void ParseFile(char* data)
{
unsigned char sizeinBytes = 4;
unsigned char count = 2;
unsigned char firstNameLength = 4;
unsigned char lastNameLength = 4;
unsigned char flags = 1;
unsigned char age_byte = 1;
unsigned char height_byte = 1;
unsigned char checksum = 4;
int offset = 0;
// size
int size;
memcpy(&size, &data[offset], sizeof(int));
std::cout << "size:" << size << std::endl;
offset += sizeinBytes;
//count of entries
short entryCount;
memcpy(&entryCount, &data[offset], sizeof(short));
std::cout << "entry count::" << entryCount << std::endl;
offset += count;
for (int i = 0; i < entryCount; i++)
{
//firstNameLength
int lengthofFirstName;
memcpy(&lengthofFirstName, &data[offset], sizeof(int));
std::cout << "first name length:" << lengthofFirstName << std::endl;
offset += firstNameLength;
//firstName
char* firstName = new char[lengthofFirstName];
memcpy(firstName, &data[offset], lengthofFirstName);
firstName[lengthofFirstName] = '\0';
std::cout << "first name:" << firstName << std::endl;
offset += lengthofFirstName;
// 4 bytes
int lengthofLastName;
memcpy(&lengthofLastName, &data[offset], sizeof(int));
std::cout << "last name length:" << lengthofLastName << std::endl;
offset += lastNameLength;
char* lastName = new char[lengthofLastName];
memcpy(lastName, &data[offset], lengthofLastName);
lastName[lengthofLastName] = '\0';
std::cout << "last name:" << lastName << std::endl;
offset += lengthofLastName;
char flag = data[offset];
std::cout << "flags:" << (int)flag << std::endl;
offset += flags;
char age;
char height;
if (flag == 3)
{
age = data[offset];
height = data[offset + 1];
offset += age_byte + height_byte;
std::cout << "age:" << (int)age << std::endl;
std::cout << "height:" << (int)height << std::endl;
}
else if (flag == 2)
{
height = data[offset];
offset += height_byte;
std::cout << "height:" << (int)height << std::endl;
}
else if (flag == 1)
{
age = data[offset];
offset += age_byte;
std::cout << "age:" << (int)age << std::endl;
}
}
int checkSum;
memcpy(&checkSum, &data[size - 4], sizeof(int));
std::cout << "checksum:" << checkSum << std::endl;
}
tested it on a simple file and it works fine
glad to hear, having 2nd thoughts readinginputFile(…)…streamoff size = inputFile.tellg() … new char[size]
(ate
was beyond the right margin of CR's code peephole…). \$\endgroup\$