C++ LPTSTR to int (but memory overwrite problem using atoi) - c++

I have the following code, m_edit is a MFC CEdit (I know I would never use MFC but project demanded it).
It's a simple loop, that gets the text from a text edit, converts it to integer after getting the first line, then stores it in m_y vector.
LPTSTR szTemp;
vector<int> m_y;
for(int i = 0; i < m_edit->GetLineCount(); i++){
szTemp = s_y.GetBuffer(0);
m_edit->GetLine(i, szTemp); // get line text store in szTemp
y = atoi(szTemp);
m_y.push_back(y);
szTemp = "";
y = 0;
}
IMPORTANT EXAMPLE: So let's say the CEdit has 6 numbers:
0
5
2
5
18
6
If you use Visual Studio's debugger you will notice an anomaly!!
Here's what it shows:
y = 0
y = 5
y = 2
y = 5
y = 18
y = 68
Do you see that? szTemp when inserted into atoi, it returns the number 6, but concatenates the 2nd digit of the last number!!! This is why I did szTemp = "";, but the problem persists. Also, let's say the last number was 17 (not 18), then this time debugger would say y = 67, so it is definitely this problem.
However, Visual Studio debugger, when you hover over szTemp during this iteration, it says '6' <--- not '68' inside szTemp. So somehow atoi is ruining it.
Am I suppose to concatenate a \0 into szTemp before putting it into atoi? How do I solve this easily?

From the MFC CEdit::GetLine documentation:
Remarks:
The copied line does not contain a null-termination character.
So you need to pay attention to GetLine's return value to determine how many bytes were copied into the buffer and then add your own NUL-terminator.
Also, I would recommend that you pass in the buffer size to make sure you don't have a potential buffer overflow.

I think you should specify a buffer size for GetBuffer
e.g.
szTemp = s_y.GetBuffer(MY_MAX_STRLEN);
having GetBuffer(0) allocates a 0 sized buffer since CString is (presumably) empty.

Related

How can I read from a .txt file to determine the size of a 2-D array?

I am working on a flood-fill recursion assignment where I have to read an ASCII art text file and fill it in. The assignment can be found here: https://faculty.utrgv.edu/robert.schweller/CS2380/homework/hw10.pdf
Recursion() //construcor
{
column = -1;
row = -1;
grid = new char*[size of art row];
for(int i = 0; i < size of art; i++)
{
board[row] = new char[size of art column]
}
}
I'm not sure if determining the size of the array should be in the constructor or not. I need to know the size of the array in order to know where the user wants to fill the art file in. Also, here is all of the code for a better context. https://pastebin.com/TSYH26Ci
I would handle your file as binary. I do not know which OS,API you are using so I will answer just in generic way...
get file size siz
usually seeking to 0 bytes from end of file will give you the file size.
allocate 1D array dat to store your entire file
dat = new BYTE[siz];
load your file into memory (1D array)
do not forget to use binary access as some ASCII arts could use control codes (ASCII below 32) which could be corrupted by text file access.
scan for end of line
so scan your array from 0 and stop when you find ASCII codes 13 or 10. Its position will give you the x resolution of your ASCII art
int xs;
for (xs=0;xs<siz;xs++)
if ((dat[xs]==10)||(dat[xs]==13))
break;
now xs should be holding your x resolution.
compute y resolution ys
the safest way is to count the number of end of lines (13 or 10). In such case you can even store the line start addresses to some pointer array BYTE **pixel=new (BYTE*)[ys]; which will enable you simple 2D access pixel[y][x]. If your ASCII art is aligned and have constant size per each line than you can compute ys from size..
ys = siz/(xs+eol_size)
where eol_size is 1 or 2 depending on the used line ending: ((10),(13),(13,10) or (10,13)) so:
eol_size=1;
if (xs<siz)
if ((dat[xs+1]==10)||(dat[xs+1]==13))
eol_size=2;
As we do not have access to any input file we can only guess... If you need to generate one see:
C++ Image to ASCII art conversion
Here example of binary file access in VCL (bullets #1,#2,#3):
Convert the Linux open, read, write, close functions to work on Windows

How exactly does a reference to an array work?

I am looking at a unique example here and am trying to understand why his snippet behaves the way it does
// uninitialized mem
char test[99999];
//
test[0] = 'a';
test[1] = 'b';
test[2] = 'c';
test[3] = 'd';
test[4] = 'e';
test[5] = 'f';
test[6] = 'g';
for (int i = 0; i < 99999; i++) {
cout << (&test[i])[i] << endl;
}
In particular, what is happening in memory for the output to skip a character?
output:
a
c
e
g
..
This is what is happening:
An array is just a contiguous chunk of memory.
&test
Is getting the address of that index of the starting point of array. Not the value.
When you add [some number], it counts up the number times the size of the data type, in this case each char is a byte.
So when you do
&test[i]
that means the starting address + i bytes.
when you do
(&test[i])[i]
You are doing i bytes from the starting address, and then treat that as the starting address and go up i more bytes.
So in your iterations:
(&test[0])[0] // index 0 + 0 = 0
(&test[1])[1] // index 1 + 1 = 2
(&test[2])[2] // index 2 + 2 = 4
(&test[3])[3] // index 3 + 3 = 6
It should become a bit more obvious when you consider what the array indexing is actually doing.
Given an array test, you usually access the nth element of test with test[n]. However, this is actually the equivalent of *(test+n). This is because addition on pointers automatically multiplies the amount you add with the size of the type being pointed to. This means the pointer will then be pointing at the second item in the array if you add one to the pointer, the third item if you add two, and so on.
The code you provide then references that value, so you end up with &(*(test+n)). The reference (&) and the dereference (*) operations then cancel each other out, which means you end up with just test+n.
The code then does another array index on that value, so you end up with (test+n)[n], which again may be written as *((test+n)+n). If you simplify that, you get *(test+n+n), which may be rewritten as *(test+2*n).
Clearly then, if you convert that back to array indexing notation, you end up with test[2*n], which indicates in simple form that you'll be querying every other element of the array.

Two 2D Arrays, Two Matrices, One File

I am trying to figure out how to read two matrices from one file and then assign them to two different 2D arrays. The matrices are separated by a new line in the text file. I managed to get the first one to read successfully but now I cant figure out how to read the second one. The way I see it, the the line that separates the two matrices must be considered and checked for. How do I get the program to read and assign the second matrix to an array?
Both matrices and arrays are 4x4.
This is what the text file looks like:
3 4 5 7
5 16 7 12
11 12 3 9
9 8 1 12
15 4 3 6
1 12 3 12
7 8 19 9
11 12 8 5
Here is my code for the first array which works fine.
for (int y = 0; y < 4; ++y )
{
for (int x = 0; x < 4; ++x )
{
infile >> array1[x][y];
}
}
And here is my code for the array I can't figure out.
for (int y = 0; y < 4; ++y )
{
for (int x = 0; x < 4; ++x )
{
if(x == '\n' && y == '\n') //My attempt.
{
infile >> array2[x][y];
}
}
}
Here is the output:
This will check to make sure numbers in file are written to the first array.
3 4 5 7
5 16 7 12
11 12 3 9
9 8 1 12
This will check to make sure numbers in file are written to the second array.
9.21742e-314 1.0572e-307 7.29112e-304 3.87184e-306
1.06498e-307 1.65425e-317 6.79039e-313 4.22748e+266
5.92879e-323 1.06196e-307 6.95089e-308 9.88799e-315
1.79648e-313 8.48798e-314 6.95224e-308 1.06193e-307
Press any key to continue . . .
Any help is appreciated!
When you are reading your file using the "formatted input" operator >>, the kind and amount whitespace (spaces, tabs, newlines) between the items (numbers in your case) is insignificant. This means you do not get to see the empty line at all. If you need to parse a file based on its lines, consider using getline instead and parsing the single lines using a istringstream.
If on the other hand you know the size of both arrays, you can simply read the second array just as you read the first array. The extra empty line just gets ignored.
The reason your code for reading the second array does not work is that you compare the index variables to '\n', which happens to be 10 on most systems. As your index ranges from 0 to 3, the if condition is never true, so nothing gets read at all, so you are seeing a dump of uninitialized memory.
You can read the second array exactly as you read the first. The reason is that, when you start reading from a stream, at first it discards whitespaces till it encounters something that is not whitespace. Then it gets the numbers/character one by one till it encounters whitespace again. So, there is no problem with the newline and you can read the remaining array without problems.

Multidimensional array with different sizes using Arduino

I would like to have a multidimensional array that allows for different sizes.
Example:
int x[][][] = {{{1,2},{2,3}},{{1,2}},{{4,5},{2,7},{1,1}}};
The values will be known at compile time and will not change.
I would like to be able to access the values like val = x[2][0][1];
What is the best way to go about this? I'm used to java/php where doing something like this is trivial.
Thanks
I suppose you could do this "the old fashioned (uphill both ways) way":
#include <stdio.h>
int main(void){
int *x[3][3];
int y[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
x[0][0] = &y[0];
x[0][1] = &y[2];
x[1][0] = &y[4];
x[2][0] = &y[6];
x[2][1] = &y[8];
x[2][2] = &y[10];
// testing:
printf("x[0][0][0] = %d\n", x[0][0][0]);
printf("x[0][0][1] = %d\n", x[0][0][1]);
printf("x[0][1][0] = %d\n", x[0][1][0]);
printf("x[0][1][1] = %d\n", x[0][1][1]);
printf("x[1][0][0] = %d\n", x[1][0][0]);
printf("x[1][0][1] = %d\n", x[1][0][1]);
printf("x[2][0][0] = %d\n", x[2][0][0]);
printf("x[2][0][1] = %d\n", x[2][0][1]);
printf("x[2][1][0] = %d\n", x[2][1][0]);
printf("x[2][1][1] = %d\n", x[2][1][1]);
printf("x[2][2][1] = %d\n", x[2][2][0]);
printf("x[2][2][1] = %d\n", x[2][2][1]);
return 0;
}
Basically, the array x is a little bit too big (3x3) and it points to the "right place" in the array y that contains your data (I am using the digits 1…12 because it's easier to see it is doing the right thing). For a small example like this, you end up with an array of 9 pointers in x (72 bytes), plus the 12 integers in y (48 bytes).
If you filled an int array with zeros where you didn't need values (or -1 if you wanted to indicate "invalid") you would end up with 18x4 = 72 bytes. So the above method is less efficient - because this array is not "very sparse". As you change the degree of raggedness, this gets better. If you really wanted to be efficient you would have an array of pointers-of-pointers, followed by n arrays of pointers - but this gets very messy very quickly.
Very often the right approach is a tradeoff between speed and memory size (which is always at a premium on the Arduino).
By the way - the above code does indeed produce the output
x[0][0][0] = 1
x[0][0][1] = 2
x[0][1][0] = 3
x[0][1][1] = 4
x[1][0][0] = 5
x[1][0][1] = 6
x[2][0][0] = 7
x[2][0][1] = 8
x[2][1][0] = 9
x[2][1][1] = 10
x[2][2][1] = 11
x[2][2][1] = 12
Of course it doesn't stop you from accessing an invalid array element - and doing so will generate a seg fault (since the unused elements in x are probably invalid pointers).
Thanks Floris.
I've decided to just load all values into a single array, like
{1,2,2,3,1,2,4,5,2,7,1,1}
and have a second array which stores the length of each first dimension, like
{2,1,3}
The third dimension always has a length of 2, so I will just multiply the number by 2. I'm going to make a helper class so I can just do something like getX(2,0) which would return 4, and have another function like getLength(0) which would return 2.

sorting through a file/returning info

Just need general project help.
Basically I need to do this for 8 players. The numbers come from a file im supposed to call in. The first 5 numbers for for the first 5 games, the next for rebounds, and then for blocks. Im assuming I need to call in a loop to read the first name, last name, points, rebounds and blocks, process that info and then output the information.Any tips/ suggestions?
ex from the text file:
Thomas Robinson 17 28 10 16 10 11 12 13 8 9 1 1 1 0 1
ex from what I'm supposed to return that information to
Game Log
-----------------------------------------------------------------------------
Player Name : Thomas Robinson
-----------------------------------------------------------------------------
Game # Points Rebounds Blocks
-----------------------------------------------------------------------------
1 17 11 1
2 28 12 1
3 10 13 1
4 16 8 0
5 10 9 1
-----------------------------------------------------------------------------
I think this is homework, but since I don't know which functions can be used, and which functions can't, my answers may be can't fit the request.
At a first look, I got three ideas.
1) using ifstream::get()
ifstream in_file;
in_file.open("your_file_name.txt");
char ch;
string str = "";
while(in_file.get() != '\n')
{
str = "";
while((ch = in_file.get()) != ' ')
{
// add ch to str.
str += string(&ch, 1);
}
// push str into an array, vector, stack, etc.
/*...*/
}
in_file.close();
2) read the line into a string, and then use a split function, you can find how to implement a split function everywhere.
3) use the ifstream::getline() function, it provides a delemiter parameter.
you can find the usage of ifstream::get() and ifstream::getline() here and here
The code I provide in 1) is probably not a good practice, you should check the 'EOF' stream error, in_file.open()'s exceptions etc.
btw, the code I first wrote was an error code, you can't use str += string(ch), you should either write str += string(&ch, 1) or str += string(1, ch) or str += ch you can find string's constructors here. Sorry for the error code again.
You can parse the file with the ">>" operator pretty nicely if everything is separated by spaces and newlines. Which is how the ">>" operator works. So, yes, you need a loop. Basically you want the loop to work like this:
(I never knew you could do this in Comp Sci 1. It would've saved me so much trouble...I used to do things like what the other answer is doing.)
(I'm also assuming you know how to open a txt file as an ifstream. If not, see http://www.cplusplus.com/reference/iostream/ifstream/open/.)
int temp;
int n = 0;
int x = 1;
while(textfile >> temp) // Each time through the loop, this will make temp
// the next value in the file. It will stop when
// there's nothing more to read.
{
/* Now it's going to go from left to right through the file, so you
need some logic to put it in the right place. you know that every
five numbers start a new column, so:*/
array[x][n] = temp; //Start x at 1 because you're skipping the first column
n++;
if (n == 5) {
n = 0;
x++; //Every five values, move on to the next column
}
Now your array will have the stuff where it needs to be. Just output it according to plan.