I'm trying to encode a relatively complex message into a union structure so that I can generate an array of uint8_t that I can feed into a serial communications protocol.
However, when looking at the array generated when my union is filled with data, an extra uint8_t element appears after my command type element. Please see the Union structure below:
union myint16_t{
uint16_t ui16;
int16_t i16;
uint8_t data[2];
};
union {
struct {
uint8_t commandtype;
myint16_t UpperLimits[4];
myint16_t LowerLimits[4];
myint16_t JointZeros[4];
int8_t JointPolarity[4];
myint16_t P[4];
myint16_t I[4];
myint16_t D[4];
};
uint8_t data[53];
};
as you can see there are the second anonymous union references the union myint16_t.
So if I fill all the values of the anonymous union and then print out the underlying data[53] array, my second value (data[1]) is 0 and not part of the first element of UpperLimits[4]. Please see the code where I fill the union and then print out the elements.
char q = 'c';
hmmv4_configmsg msg;
msg.commandtype =(uint8_t) q;
msg.UpperLimits[0].ui16 = 784;
msg.UpperLimits[1].ui16 = 784;
msg.UpperLimits[2].ui16 = 784;
msg.UpperLimits[3].ui16 = 784;
msg.LowerLimits[0].ui16 = 223;
msg.LowerLimits[1].ui16 = 223;
msg.LowerLimits[2].ui16 = 223;
msg.LowerLimits[3].ui16 = 223;
msg.JointZeros[0].ui16 = 512;
msg.JointZeros[1].ui16 = 512;
msg.JointZeros[2].ui16 = 512;
msg.JointZeros[3].ui16 = 512;
msg.JointPolarity[0] = -1;
msg.JointPolarity[1] =-1;
msg.JointPolarity[2] =-1;
msg.JointPolarity[3] =-1;
msg.P[0].i16=4000;
msg.P[1].i16=4000;
msg.P[2].i16=4000;
msg.P[3].i16=4000;
msg.I[0].i16=1;
msg.I[1].i16=1;
msg.I[2].i16=1;
msg.I[3].i16=1;
msg.D[0].i16=24;
msg.D[1].i16=24;
msg.D[2].i16=24;
msg.D[3].i16=24;
//msg.change_endian();
while(1)
{
for(int i =0; i<54; i++)
{
writebuf[i]=msg.data[i];
printf("D: %d, %d \n", i, msg.data[i]);
}
printf("L0: %d, %d, %d", msg.P[0].i16, msg.P[0].data[0], msg.P[0].data[1]);
int r =jointencoder.xfer1(writebuf, readbuf, 54);
}
the output of the printf is (the offending element is D:1 -- it shouldn't be there):
D: 0, 99
D: 1, 0
D: 2, 16
D: 3, 3
D: 4, 16
D: 5, 3
D: 6, 16
D: 7, 3
D: 8, 16
D: 9, 3
D: 10, 223
D: 11, 0
D: 12, 223
D: 13, 0
D: 14, 223
D: 15, 0
D: 16, 223
D: 17, 0
D: 18, 0
D: 19, 2
D: 20, 0
D: 21, 2
D: 22, 0
D: 23, 2
D: 24, 0
D: 25, 2
D: 26, 255
D: 27, 255
D: 28, 255
D: 29, 255
D: 30, 160
D: 31, 15
D: 32, 160
D: 33, 15
D: 34, 160
D: 35, 15
D: 36, 160
D: 37, 15
D: 38, 1
D: 39, 0
D: 40, 1
D: 41, 0
D: 42, 1
D: 43, 0
D: 44, 1
D: 45, 0
D: 46, 24
D: 47, 0
D: 48, 24
D: 49, 0
D: 50, 24
D: 51, 0
D: 52, 24
D: 53, 0
L0: 4000, 160, 15joint encoder transferred
My question is why is D:1 there? My understanding of unions and structures is that because command type is uint8_t, then it should only occupy one data space, and therefore UpperLimits[0] should start on D:1, but it seems that command_type is acting as a uint16_t and posting another bit. Why is this so?
Note: you may see that the index goes up to count data[53] which should be out of bounds, but I need to read this and send it so as to be able to deconstruct the data at the other end.
There is almost certainly a padding byte between commandtype and UpperLimits; the 2-byte myint16_t data type is aligned on an even byte boundary.
struct {
uint8_t commandtype;
myint16_t UpperLimits[4];
...
If you could print the size of the anonymous structure and union, you're likely to find that it is at least 54 bytes (where you think it should be 53). One of the disadvantages of untagged structure types embedded as anonymous members of a union is that there is no easy way to print the size of the structure. Give the structure a tag (struct tag { uint8_t commandtype; ...) so that you can print its size out.
There isn't an easy fix for that using the current framework.
You need to tell the compiler how to align the elements in your union or struct. Simply add #pragma pack(push,1) before your definitions to instruct the compiler to align adjacent elements on one-byte boundaries, and then use #pragma pack(pop) to revert to the compiler's default alignment. For performance reasons, you would not want to use one-byte alignment for all structs/unions/classes, so it's a good idea to wrap your union definition in the pragma pair.
Example:
#pragma pack(push,1)
union
{
uint_8 first;
uint_8 second;
} two_bytes;
#pragma pack(pop)
assert(sizeof two_bytes == 2);
Related
I took over a program, which use 1d array to construct cv::Mat. I'm confuse about it, and I make a demo:
int main()
{
short data[] = {
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
43, 42, 43, 44
};
cv::Mat m{ 4, 4, CV_8U, data};
cv::imwrite("test.png", m);
return 0;
}
I expect the output is
11 12 13 14
21 22 23 24
31 32 33 34
43 42 43 44
But I open the img in MATLAB:
11 0 12 0
13 0 14 0
21 0 22 0
23 0 24 0
The 3rd parameter in the constructor you used for cv::Mat (CV_8U) specifies the format of the data buffer.
Your data is an array of short, i.e. each entry is 2 bytes. When you use values small values like you did, it means one of the bytes for each short will be 0.
When you use this buffer to initialized a cv::Mat of type CV_8U you tell opencv to treat the buffer as containing unsigned chars (1 byte elements). So each short is interpreted as 2 unsigned char bytes.
This is why you get the zeroes in the output.
Eaither change the type of the data buffer to unsigned char [], or change the cv::Mat data type to e.g. CV_16S. The 2 should usually match.
You can do it e.g. like this:
unsigned char data[] = {
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
43, 42, 43, 44
};
cv::Mat m{ 4, 4, CV_8U, data };
You can see the list of opencv data types here (in the Data types section):
https://docs.opencv.org/3.4/d1/d1b/group__core__hal__interface.html
Im trying to use the GlobalPlatform library from Karsten Ohme (kaoh) in Delphi. Thanks to the help of some people here on stackoverflow i got it parially working and i am able to setup a connection to the cardreader. Now i am trying to select an AID, and therefore i need to pass the AID as array of Bytes to the function.
I use the GPShell (the commandline tool that uses the same library) source code as a reference to help me translate the functions. There i found the convertStringToByteArray function, which takes a string and converts it to a array of Bytes.
The original C++ function:
static int convertStringToByteArray(TCHAR *src, int destLength, BYTE *dest)
{
TCHAR *dummy;
unsigned int temp, i = 0;
dummy = malloc(destLength*2*sizeof(TCHAR) + sizeof(TCHAR));
_tcsncpy(dummy, src, destLength*2+1);
dummy[destLength*2] = _T('\0');
while (_stscanf(&(dummy[i*2]), _T("%02x"), &temp) > 0)
{
dest[i] = (BYTE)temp;
i++;
}
free(dummy);
return i;
}
and i tried to write a similar procedure in Delphi, i tried to convert the string in two ways - the first (Literally) converts every character (treated as HEX) to integer. The second way uses Move:
procedure StrToByteArray(Input: AnsiString; var Bytes: array of Byte; Literally: Boolean = false);
var
I, B : Integer;
begin
if Literally then
begin
for I := 0 to Length(Input) -1 do
if TryStrToInt('$' + Input[I +1], B) then
Bytes[I] := Byte(B)
else
Bytes[I] := Byte(0);
end else
Move(Input[1], Bytes[0], Length(Input));
end;
But i keep getting a
(6A82: The application to be selected could not be found.)
error, when i try to select AID
A000000003000000
I know i am trying to select the right AID, because when i use this same AID with GPShell - i get a successful response. So i am not sure if the problem is in my String to Byte array procedure, or maybe somewhere else.
When i use breakpoints, and i try to convert the string to bytes literally i get
(10, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0)
in the debugger. But when i try with Move (or ORD) i get
(65, 48, 48, 48, 48, 48, 48, 48, 48, 51, 48, 48, 48, 48, 48, 48)
I also tried to convert the string to bytes online with various websites, and these give me another result
(41, 30, 30, 30, 30, 30, 30, 30, 30, 33, 30, 30, 30, 30, 30, 30)
So i am a bit lost in trying to find out what im doing wrong, is the problem in my string to bytes conversion - or do i need to look somewhere else?
The original C++ code parses pairs of hex digits into bytes:
A000000003000000 -> A0 00 00 00 03 00 00 00
But your Delphi code is parsing individual hex digits into bytes instead:
A000000003000000 -> A 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0
Try this instead:
procedure StrToByteArray(Input: AnsiString; var Bytes: TBytes; Literally: Boolean = false);
var
I, B : Integer;
begin
if Literally then
begin
SetLength(Bytes, Length(Input) div 2);
for I := 0 to Length(Bytes)-1 do
begin
if not TryStrToInt('$' + Copy(Input, (I*2)+1, 2), B) then
B := 0;
Bytes[I] := Byte(B);
end;
end else
begin
SetLength(Bytes, Length(Input));
Move(Input[1], Bytes[0], Length(Input));
end:
end;
That being said, Delphi has its own HexToBin() functions for parsing hex strings into byte arrays. You don't need to write your own parser, eg:
procedure StrToByteArray(Input: AnsiString; var Bytes: TBytes; Literally: Boolean = false);
begin
if Literally then
begin
SetLength(Bytes, Length(Input) div 2);
HexToBin(PAnsiChar(Input), PByte(Bytes), Length(Bytes));
end else
begin
SetLength(Bytes, Length(Input));
Move(Input[1], Bytes[0], Length(Input));
end:
end;
I have an array of 16 cells and I know location 0 (a) and location 15 (b).
I want to increase linearly the RGB value between point a to b.
This is my function so far which gets a hex and converts it to RGB but I am unsure how I can extend it to do the above.
void rgb(int hexValue)
{
unsigned r = (hexValue & 0xF800) >> 11;
unsigned g = (hexValue & 0x07E0) >> 5;
unsigned b = hexValue & 0x001F;
r = (r * 255) / 31;
g = (g * 255) / 63;
b = (b * 255) / 31;
printf("r: %d, g: %d, b: %d\n", r, g, b);
}
Many thanks in advance.
Edit:
Per my comment bellow this is an example code of trying to solve this..
int ra = 0;
int ga = 0;
int ba = 0;
int rb = 255;
int gb = 255;
int bb = 255;
int r = 0;
int g = 0;
int b = 0;
for(int i = 0; i < W; i++)
{
r = (ra*((W-1)-i) + rb*i)/(W-1);
g = (ga*((W-1)-i) + gb*i)/(W-1);
b = (ga*((W-1)-i) + bb*i)/(W-1);
printf("loop is: %d -- r: %d, g: %d, b: %d\n", i, r, g, b);
}
Is this logic correct? If so, I would then need to get ra,ga,ba and convert them back to hex.
My output is:
loop is: 0 -- r: 0, g: 0, b: 0
loop is: 1 -- r: 17, g: 17, b: 17
loop is: 2 -- r: 34, g: 34, b: 34
loop is: 3 -- r: 51, g: 51, b: 51
loop is: 4 -- r: 68, g: 68, b: 68
loop is: 5 -- r: 85, g: 85, b: 85
loop is: 6 -- r: 102, g: 102, b: 102
loop is: 7 -- r: 119, g: 119, b: 119
loop is: 8 -- r: 136, g: 136, b: 136
loop is: 9 -- r: 153, g: 153, b: 153
loop is: 10 -- r: 170, g: 170, b: 170
loop is: 11 -- r: 187, g: 187, b: 187
loop is: 12 -- r: 204, g: 204, b: 204
loop is: 13 -- r: 221, g: 221, b: 221
loop is: 14 -- r: 238, g: 238, b: 238
loop is: 15 -- r: 255, g: 255, b: 255
Here's a solution:
void rgb(int rgbA, int rgbB) {
int ra = (rgbA&0xf800)>>11;
int ga = (rgbA&0x7e0)>>5;
int ba = rgbA&0x1f;
int rb = (rgbB&0xf800)>>11;
int gb = (rgbB&0x7e0)>>5;
int bb = rgbB&0x1f;
for (int i=0; i<16; i++) {
int r = (ra*(15-i) + rb*i + 7)/15; // + 7 is there to apply rounding
int g = (ga*(15-i) + gb*i + 7)/15;
int b = (ba*(15-i) + bb*i + 7)/15;
int result = r<<11|g<<5|b;
printf("%04x\n", result);
}
}
I have three integer variables, that can take only the values 0, 1 and 2. I want to distinguish what combination of all three numbers I have, ordering doesn't count. Let's say the variables are called x, y and z. Then x=1, y=0, z=0 and x=0, y=1, z=0 and x=0, y=0, z=1 are all the same number in this case, I will refer to this combination as 001.
Now there are a hundred ways how to do this, but I am asking for an elegant solution, be it only for educational purposes.
I thought about bitwise shifting 001 by the amount of the value:
001 << 0 = 1
001 << 1 = 2
001 << 2 = 4
But then the numbers 002 and 111 would both give 6.
The shift idea is good, but you need 2 bits to count to 3. So try shifting by twice the number of bits:
1 << (2*0) = 1
1 << (2*1) = 4
1 << (2*2) = 16
Add these for all 3 numbers, and the first 2 bits will count how many 0 you have, the second 2 bits will count how many 1 and the third 2 bits will count how many 2.
Edit although the result is 6 bit long (2 bits per number option 0,1,2), you only need the lowest 4 bits for a unique identifier - as if you know how many 0 and 1 you have, then the number of 2 is determined also.
So instead of doing
res = 1<<(2*x);
res+= 1<<(2*y);
res+= 1<<(2*z);
you can do
res = x*x;
res+= y*y;
res+= z*z;
because then
0*0 = 0 // doesn't change result. We don't count 0
1*1 = 1 // we count the number of 1 in the 2 lower bits
2*2 = 4 // we count the number of 2 in the 2 higher bits
hence using only 4 bits instead of 6.
When the number of distinct possibilities is small, using a lookup table could be used.
First, number all possible combinations of three digits, like this:
Combinations N Indexes
------------- - ------
000 0 0
001, 010, 100 1 1, 3, 9
002, 020, 200 2 2, 6, 18
011, 101, 110 3 4, 10, 12
012, 021, 102, 120, 201, 210 4 5, 7, 11, 15, 19, 21
022, 202, 220 5 8, 20, 24
111 6 13
112, 121, 211 7 14, 16, 22
122, 212, 221 8 17, 23, 25
222 9 26
The first column shows identical combinations; the second column shows the number of the combination (I assigned them arbitrarily); the third column shows the indexes of each combination, computed as 9*<first digit> + 3*<second digit> + <third digit>.
Next, build a look-up table for each of these ten combinations, using this expression as an index:
9*a + 3*b + c
where a, b, and c are the three numbers that you have. The table would look like this:
int lookup[] = {
0, 1, 2, 1, 3, 4, 2, 4, 5, 1
, 3, 4, 3, 6, 7, 4, 7, 8, 2, 4
, 5, 4, 7, 8, 5, 8, 9
};
This is a rewrite of the first table, with values at the indexes corresponding to the value in the column N. For example, combination number 1 is founds at indexes 1, 3, and 9; combination 2 is at indexes 2, 6, and 18, and so on.
To obtain the number of the combination, simply check
int combNumber = lookup[9*a + 3*b + c];
For such small numbers, it would be easiest to just check them individually, instead of trying to be fancy, eg:
bool hasZero = false;
bool hasOne = false;
bool hasTwo = false;
// given: char* number or char[] number...
for(int i = 0; i < 3; ++i)
{
switch (number[i])
{
case '0': hasZero = true; break;
case '1': hasOne = true; break;
case '2': hasTwo = true; break;
default: /* error! */ break;
}
}
If I understand you correctly, you have some sequence of numbers that can either be 1, 2, or 3, where the permutation of them doesn't matter (just the different combinations).
That being the case:
std::vector<int> v{1, 2, 3};
std::sort(v.begin(), v.end());
That will keep all of the different combinations properly aligned, and you could easily write a loop to test for equality.
Alternatively, you could use a std::array<int, N> (where N is the number of possible values - in this case 3).
std::array<int, 3> a;
Where you would set a[0] equal to the number of 1s you have, a[1] equal to the number of '2's, etc.
// if your string is 111
a[0] = 3;
// if your string is 110 or 011
a[0] = 2;
// if your string is 100 or 010 or 001
a[0] = 1;
// if your string is 120
a[0] = 1;
a[1] = 1;
// if your string is 123
a[0] = 1;
a[1] = 1;
a[2] = 1;
If you are looking to store it in a single 32-bit integer:
unsigned long x = 1; // number of 1's in your string
unsigned long y = 1; // number of 2's in your string
unsigned long z = 1; // number of 3's in your string
unsigned long result = x | y << 8 | z << 16;
To retrieve the number of each, you would do
unsigned long x = result & 0x000000FF;
unsigned long y = (result >> 8) & 0x000000FF;
unsigned long z = (result >> 16) & 0x000000FF;
This is very similar to what happens in the RBG macros.
int n[3]={0,0,0};
++n[x];
++n[y];
++n[z];
Now, in the n array, you have a unique ordered combination of values for each unique unordered combination of x,y,z.
For example, both x=1,y=0,z=0 and x=0,y=0,z=1 will give you n={2,1,0}
I am trying to find a way to import stat data into a game in progress Via spread sheets? Here's what I am working with:
Right now for example.. The spells, in order to name them, set stats, ect and be able to call them via Number I Have something like this going on in the actual code:
void spell(int & eMoney, int eSpell[10])
{
using namespace std;
char spellname[10][25] = {"Minor Heal", "Fire Shard", "Lightening Shard", "Ice Shard", "Magic Barrier", "Essence Of Life",
"Earth Shard", "Wind Shard", "Insigma", "Weaken"};
int spellcost[10] = {50, 80, 80, 80, 100, 100, 80, 80, 120, 80};
Which is all fine and dandy, it works... But it's an issue now and later.. I want to be able to use a spread sheet, like a CSV file, so I can have a spread sheet for like just spells, just swords, just clubs... I plan to have a very large selection, it's more ideal to be able to edit a single file in columns and rows and have the actual game pull the information from an external file when it's needed... But I am not able to figure out how to go about this? I am open to any ideas..
Here is an example of how I call on a spell's info now:
case 2:
do
{
cout << "Which spell would you like to cast?\n\n";
for(x=0;x<10;x++)
cout << x+1 << ". " << spellname[x] << ": " << eSpell[x] << " left" << endl;
cout << "11. Leave\n\n>> ";
cin >> decision;
system("cls");
}
while((decision<1)&&(decision>11)||(eSpell[decision-1]==0));
switch(decision)
and here is an example of the spread sheet I have in mind basically? Starting at A1:
Type sName mDmg sPrice
Spell 1 Minor Heal 10 100
Spell 2 Fire Shard 12 100
Spell 3 Lightening Shard 12 200
Spell 4 Ice Shard 12 150
Spell 5 Magic Barrier 10 130
Spell 6 Essence Of Life 15 10
Spell 7 Earth Shard 12 120
Spell 8 Wind Shard 12 230
Spell 9 Insigma 12 90
Spell 10 Weaken 12 100
Another Example:
Current Code:
char monsters[16][25] = {"Wolf", "Bear", "Bandit", "Traveler", "Gargoyle", "Knight", "Warlock", "Mammoth", "Cyclops", "Unicorn", "Dragon", "Your Mother", "Demon", "Jesus", "Satan", "God"};
//monster strengths
int monsterdamagemax[16] = {32, 42, 53, 53, 65, 65, 75, 75, 85, 85, 90, 90, 95, 95, 110, 110};
int monsterdamagemin[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int monsterdefensemax[16] = {2, 7, 13, 13, 20, 20, 25, 25, 35, 35, 40, 40, 45, 45, 55, 55};
int monsterdefensemin[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int monsterhealth[16] = {32, 52, 73, 73, 95, 95, 118, 118, 142, 142, 167, 167, 193, 193, 220, 220};
int monsterspeed[16] = {7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15};
int monstergold[16] = {20, 30, 41, 41, 53, 53, 66, 66, 80, 80, 95, 95, 110, 110, 125, 125};
Ideally, I want to be able to get all that from a CSV file like:
mID mName mDmgMax mDmgMin mDefMax mDefMin mHp mSpeed mGold
1 Wolf 32 0 2 0 32 7 20
2 Bear 42 0 7 0 52 8 30
3 Bandit 53 0 13 0 73 9 41
4 Traveler 53 0 13 0 73 9 41
5 Gargoyle 65 0 20 0 95 10 53
6 Knight 65 0 20 0 95 10 53
7 Warlock 75 0 25 0 118 11 66
8 Mammoth 75 0 25 0 118 11 66
9 Cyclops 85 0 35 0 142 12 80
10 Unicorn 85 0 35 0 142 12 80
11 Dragon 90 0 40 0 167 13 95
12 Your Mother 90 0 40 0 167 13 95
13 Demon 95 0 45 0 193 14 110
14 Jesus 95 0 45 0 193 14 110
15 Statan 110 0 55 0 220 15 125
16 God 110 0 55 0 220 15 125
How about writing a small command based application that creates records for you, and in your "main" program that is game, you just have to read these records.
A sample structure -
struct monster
{
int mID;
char mName[25]; //from your code
int mDmgMax;
//and these as well mDmgMin mDefMax mDefMin mHp mSpeed mGold
};
in this "helper" program read each data item (like the mName) in a record one by one, and insert in this structure. Write the structure to monsters.dat file
std::ofstream fout;
fout.open("monsters.dat", std::ios::app | std::ios::binary);
fout.write( (char*) &monsterInstance, sizeof(monsterInstance) );
fout.close();
This will simply append records. (I have skipped error checking and reading data.)
For greater ease, this program should be able to show current monsters, add monster, delete monster (by entering mID).
Reading such records in your main program should be a easy task.
If you're going to have a lot of table-based data to keep around, you might look into using SQLite. It has some interesting costs and benefits.
On the down side (maybe), it's SQL. It can be a bit more complex and depending on your searching algorithm, could be slower. It also can't be edited by hand, you need something to open the database (there are free tools available).
On the up side, you get all the sorting and filtering power of a database (anything you'll need, like spell='fireball' AND damage < 5), and SQLite is fast (easily enough to store game data in, and very possibly faster than your own code). You can store all your data in a single file for easy deployment or modding, with unique tables for each type (weapons, spells, characters, etc), and no server involved (SQLite is a single DLL).
Relational databases excel at working with consistently-formed tables of data, which is exactly what you have in a game environment (each object type has a few fields, not much variation, maybe some blanks, with various data types). SQLite, despite being the smallest database, can handle thousands of rows with excellent time, so you won't have to worry about your game data becoming unwieldy (which happens very quickly with pure text table files, like NWN(2)'s 2DA format).
There is a learning curve to it, but you do gain some simplicity in the future (adding a new object type is a new table and queries, not a whole lot of code) and a very stable data format and load/save library. Depending on your needs, it may be worth a shot.
As pointed in question comments, you should go for <fstream> if you really want to deal with CSV files. Using that approach, getline should be enough for what you need.
This thread in C++.com and this question should point you some directions on how to handle CSV.
I use Boost to parse the CSV files I work with. Here's a simple example.
I agree with peachykeen though, SQLite may suit you better, but maybe this will help you get started.
#include <iostream>
#include <fstream>
#include <vector>
#include <boost/tokenizer.hpp>
#include <boost/token_functions.hpp>
typedef std::vector<std::string> csvLine;
typedef std::vector<csvLine> csvLines;
typedef boost::tokenizer<boost::escaped_list_separator<char> > csvTokenizer;
csvLines ReadCSVFile(const std::string& fileName)
{
csvLines retVec;
std::ifstream inFile(fileName.c_str());
if(inFile)
{
std::string fileLine;
while(std::getline(inFile, fileLine))
{
csvTokenizer lineTokens(fileLine);
retVec.push_back(csvLine(lineTokens.begin(), lineTokens.end()));
}
inFile.close();
}
return retVec;
}
int main(int argc, char** argv)
{
csvLines lines(ReadCSVFile(argv[1]));
for(csvLines::iterator lineIt = lines.begin(); lineIt != lines.end(); ++lineIt)
{
for(csvLine::iterator tokenIt = (*lineIt).begin(); tokenIt != (*lineIt).end(); ++tokenIt)
{
std::cout << *tokenIt << " ";
}
std::cout << std::endl;
}
return 0;
}