|
Hello gurus,
I have a C question this time. An easy one
I wish to write a function that modifies a 2D array of unsigned char .
My array looks like this:
unsigned char map[0x40][0x20];
I call an update function:
UpdateMap(map, nLevel);
and the map should be modified. But I have forgotten hwo to write the header of the UpdateMap function. Can some one remind me please?
its code is simply like that:
<br />
void UpdateMap([I have forgotten how to write the header])<br />
{<br />
int i=0, j=0;<br />
for (i=0; i<0x20; i++)<br />
for (j=0; j<0x20; j++)<br />
map[i][j]=map[i+0x20][j]=g_levelMaps[i+(nLevel*0x20)][j];<br />
}<br />
<br />
Thanks for the help.
Best regards.
Fred.
There is no spoon.
|
|
|
|
|
It's an unsigned char **.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Hi Christian,
That's what I have done, but I have a warning:
"Parsing argument 1 of 'UpdateMap' from incompatible pointer type"
That's why I have posted a new thread
I have declared my array as an unsigned char and also in the header of the function.
fred
There is no spoon.
|
|
|
|
|
I think that when I did it, I declared an unsigned char ** and then called new on it to build the array. But that's what it is, you can't pass an array as such AFAIK.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
ok, my array is not initialized by the new operator. It is decalred like a standard array:
unsigned char map[0x40][0x20]
fred
There is no spoon.
|
|
|
|
|
You can code it as follows:
void UpdateMap(unsigned char map[0x40][0x20])
{
int i=0, j=0;
for (i=0; i<0x20; i++)
for (j=0; j<0x20; j++)
map[i][j]=map[i+0x20][j]=g_levelMaps[i+(nLevel*0x20)][j];
}
void test()
{
unsigned char map[0x40][0x20];
UpdateMap(map);
}
Hope that helps,
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
It works if you specify the array bounds ? Cool.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Christian Graus wrote:
It works if you specify the array bounds ? Cool.
It does work
For an array of n dimensions you need to specify at least (n-1) bounds, because otherwise the compiler has no way to calc the offset for a given element. For example, if you have int matrix[3][5] (3 rows, 5 columns), then the element at matrix[i][j] (row i, column j), can be computed as *(matrix+(i*5)+j) , that is, increment the matrix pointer so as to skip i rows of 5 elements each, then skip j elements, and then dereference the resulting pointer.
As can be seen in the example above, the number of rows isn't strictly needed, though (just like the number of elements isn't actually needed for an array of only one dimension). In fact one could even write a function that received as its argument a matrix of unbounded rows and n columns.
void test(int matrix[][5])
{
matrix[2][3] = 1;
}
void main()
{
int matrix[3][5];
test(matrix);
}
If on the other hand the test function received the matrix as an int** , there'd be no way to know how many elements to skip for each row. The test function would compile, but the main function not, because int[3][5] is not the same as int** , the latter being a pointer to a pointer to an int [1]. In fact if we changed the test function to
void test(int** matrix)
{
matrix[2][3] = 1;
}
The expression matrix[2][3] would compile to something entirely different than before. With matrix defined as int** an expression matrix[i][j] would translate to *((*(map+i))+j) , that is in the example, incrementing the matrix pointer by 2, dereferencing the result, using that value as a pointer, incrementing it by 3 and then dereferencing that! To keep that working as before, we'd need to also alter the main function as follows:
void main()
{
int matrix[3][5];
int* rows[3];
for (int i = 0; i < 3; i++)
rows[i] = &matrix[i][0];
test(rows);
}
There's still one additional correct way of writing the code, which can be used if one doesn't want test to be restricted to a particular number of columns:
void test(int* matrix, int nCols)
{
matrix[2*nCols+3] = 1;
}
void main()
{
int matrix[3][5];
test(matrix[0],5);
}
[1] Depending on how it's used, it can also be seen as a pointer to an array of pointers to int s, or as a pointer to a pointer to an array of int s, or as a pointer to an array of pointers to arrays of int s.
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
Hi,
Thanks for the trick
As my array will be modified by other functions, I simply put the array in global and the functions modify it and it works that way
Thanks.
Fred
There is no spoon.
|
|
|
|
|
u can mention the first argument in the header as unsigned char(*map)[0x20]
(pointer to an array of size 0x20)
|
|
|
|
|
Do not use global variables unless you have no other choice. See my response to a similar question here.
"One must learn from the bite of the fire to leave it alone." - Native American Proverb
|
|
|
|
|
I have an EDIT box and I'd like to silently trap and eat certain characters.
I can catch WM_CHAR, check for the key, and return 0.
I guess I'm asking if this is the right thing to do?
I'd prefer to catch WM_KEYDOWN, and somehow return something that says "don't bother translating this key. Do not translate. Do not send out WM_CHAR ..."
But to no avail.
------
Here is another example. I want to convert every character typed to +2. So, if the user enters "abc" I want to print "cde" to the window. "ejv" == "glx". Following the above approach, if I capture and eat the "a" character in WM_CHAR, and then resend "c" ... naively, I'd capture the "c" and cancel it ... and send "e" ... etc etc. and I've got a crazy endless loop.
Some languages have event handlers that include the character code by reference -- and if you change the character code - whatever you changed it to is what is passed to the underlying window. Is there a low level facility to do that in win32? Can I capture WM_KEYDOWN and change the key so that WM_CHAR is correct.
Or, do I just need to manage some tricky key issues (if user didn't send this key, process it, else, cancel it and resend the new key).
Should I bother with with the TranslateMessage function? I'm just sure this is a common enough idiom that someone else has asked this and has an elegant solution ... any pointers would be great!
----
One more example - I'm implementing vi or emacs ... and I've got a slew of keyboard commands. There are just times when converting keys to WM_CHAR is a waste of CPU. If I'm in vi's navigation mode - I really don't need to send any characters to the window. I guess I can keep canceling them in WM_CHAR -- but it seems there should be a more elegant way to do so ...
I'm not a big fan of global hooks - but maybe they are warranted in this case?
Thanks in advance for any suggestions,
-Luther
|
|
|
|
|
You didn't say if you are using MFC or not. If you are using MFC (and possibly WTL ) you can do this quite easily by overriding your CEdit derived class's PreTranslateMessage function and handling the WM_KEYDOWN message there.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|
|
|
|
|
Ahh ... nice suggestion!
I am not using WTL per se, but my own OO framework. I mimic several parts of the WTL including THUNKING the wndproc - but I've not worried about the PreTranslateMessage mechanism ... till now.
So, conceptually, I don't want to translate WM_KEYDOWN to the WM_CHAR if it is a tab character ... I will read up - but I am guessing that PreTranslateMessage leads to TranslateMessage unless you return 0 or something like that ...
I wonder if I can also change the keydown here as well ...
At any rate, I think your point is ... I need to intercept the message before calling TranslateMessage - and the WTL lib provides an easy way to do this on a per HWND basis. Seems like alot of overhead ... does the MFC or WTL message loop call PreTranslateMessage for EVERY window class object?
Thanks,
-Luther
|
|
|
|
|
This is EXACTLY what I was looking for
Thanks PJ!
BOOL DialogName::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if(pMsg->message==WM_KEYDOWN)
{
if(pMsg->wParam==VK_RETURN || pMsg->wParam==VK_ESCAPE)
pMsg->wParam=NULL ;
}
return CDialog::PreTranslateMessage(pMsg);
}
|
|
|
|
|
I have a Class called CDriver which is as follows:
class CDriver {
public:
// Constructor
CDriver();
CDriver(CDriver &driver); // Copy constructor
CDriver operator =(const CDriver d);// Assign one to another
~CDriver();
// Varables
CString csFirstName;
CString csMI;
CString csLastName;
CString csBirthDate;
CString csASSN;
CString csStreetAddr;
CString csCity;
CString csState;
CString csZip;
CString csHomePhoneNum;
CString csHireDate;
CString csTruckAssigned;
};
Now I made a vector: "vector<<cdriver>> vecDriver"; Also a CString vector: "vector<<cstring>> myCStringvec"; and an iterator "vector<<cstring>>::iterator myIT";
None of these work properly! I can get the "myCStringvec.push_back(temCString)"; to accept one and only one CString. I NULLed temCString before reloading it with data then again used: "myCStringvec.push_back(temCString)"; to no avail. WHY?
vecDriver doesn't work at all nor does myIT. Please ignore the "<< and >>" it would not show what I wanted to show without using two each!
C++ is my favorite programming language
|
|
|
|
|
The "Do not treat <'s as HTML tags" checkbox helps considerably when posting code.
Your assignment operator should probably take a reference (const CDriver& d )
What do you mean when you say that it doesn't work? What does it do/not do?
Larry Mills wrote:
I NULLed temCString before reloading it with data
If you did something like this:
temCString.Empty();
temCString = _T("Some New Data");
then that should be fine. If you did something more interesting, then there might be potential for error - please elaborate.
|
|
|
|
|
I did this: temCString = ""; Then I would reload this (worker CString) with the CDriver data that I extracted from the instance of CDriver that was loaded --> ADDING THE FILE DELIMITERS in this "temCString". The idea of the vector was it was supposed to hold the FILE DELIMITED CSTRINGS that comprised the CDriver data. Then I was going to send the vector CStrings to my DataBase file. But the vector will only load the FIRST sending of the temCString; after I temCString = ""; I reload that CString with the next FILE DELIMITED CSTRINGS from CDriver and attempt to send it to the vector. In debug mode the CString is correctly loaded and as I enter the vector using push_back() method it goes through the motions of receiving the data CString but when I check it the second attempt to load it fails --> it's not in the vector!
Any ideas?
Larry A Mills Sr
(Thanks about the tip regarding Do not treat <'s as HTML tags" checkbox.)
C++ is my favorite programming language
|
|
|
|
|
Looks to me like you're passing in the same string over and over, assuming that's what you mean by 'I NULLed temCString before reloading it with data'.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
What I mean is that I clear out (NULL) the string ALWAYS, before I send the next data. (I load this class varable with all the data from CDriver WITH THE FILE DELIMITERS in this string. Then I would extract each string and send it to a file. I never got that far because I noticed that the CString was not being ADDED TO THE VECTOR after the first one was in the vector. I used the push_back() method with both CStrings.
Any ideas?
Larry A Mills Sr
VC++ 6.0 version
C++ is my favorite programming language
|
|
|
|
|
Hello
I want to use namespace in a com atl project in VC6. I don't know how i have to do this. I want to use this dll in C# and it will be nice to have namespace.
Tahnks,
Mihai
|
|
|
|
|
Anyone know if boost provides a way of escaping\unescaping regular expression metacharacters?
In Italy for thirty years under the Borgias they had warfare, terror, murder, bloodshed - but they produced Michelangelo, Leonardo da Vinci and the Renaissance. In Switzerland they had brotherly love, five hundred years of democracy and what did that produce - the cuckoo clock!
-- Harry Lime
|
|
|
|
|
Hi Friends,
I am looking for some very good book explaining SNMPv2 and MIB-II development in C++ (Object oriented approach). Please refer me any such book which i can buy form internet.
YOur help will be highly appreciated.
Best regards
Mukhan
|
|
|
|
|
I would like to do project "Thumb Rcognition and Authentication" using VC++ .
if any one has some idea plz send some suggestion.
Regarding the interface of the Scanner and the database.
And device drivers also
hello every body
|
|
|
|
|
??? talking about fingerprint recognition ?
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|