|
Thanks for pointing that out. It turns out that I need to get a pointer to the DevMode using GlobalUnlock before I modify the DevMode.
Here is the code I have and it works:
void CustomPrintDlg::OnLandscapeChecked()
{
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalLock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
GlobalUnlock(pDevMode)
}
Un
|
|
|
|
|
I just cant get this, how would you, for example, return, lets say, a (database) table from a function?
In C (no c++ stuff). For example, we got a table like:
row one
row two
2 rows with 2 columns, 2x2:
wchar_t *array[2][2]
{
{L"row", L"one"},
{L"row", L"two"}
};
But how to create things dynamically? And we dont know how many rows are there, nor how many columns.
How to allocate mem for this, and then do something like: (thats wrong and lame an i know it is pathetic)
array = malloc(initial size/* which is: 1 row and 1 column */)
getting_a_row, ok, it has 2 columns, allocating mem for 1 row and 2 columns
proceeding... we got next row! so now we got 2 rows and 2 columns, allocating mem for next row with 2 columns
and then something even more lame:
wcscpy(rows[0][0], L"row"); wcscpy(rows[0][1], L"one");
wcscpy(rows[1][0], L"row"); wcscpy(rows[1][1], L"two");
thanks
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
If the structure is know, then you can simply make an array of structures.
typedef struct {
wchar_t szCol1[4];
whcar_t szCol2[4];
} DatabaseRow;
DatabaseRow drTable[2] = {
{ L"row", L"one" },
{ L"row", L"two" }
};
Most databases will have a pre-allocated string, with a maximum length (generally not including the NULL terminating character), you would make the size of the char array the length of the field it represents +1. If there is no maximum length, then you will need to use a string pointer with dynamically allocated memory by using malloc
If the structure is unknown you could use something like
typedef struct {
DWORD nFieldLen;
BYTE pFieldData[];
} DatabaseField;
Your table row will then need to contain a pointer to 1 of these structures for each column
typedef struct {
DWORD nColumns;
DatabaseField *pColumns[];
} DatabaseRow;
int nColumns = 3;
DatabaseRow *pRow = (DatabaseRow *)malloc(sizeof(DatabaseRow) + sizeof(DatabaseField) * nColumns);
The same principal can be used for allocating each field and the entire table, all you need is the number of rows, columns and the size of each column.
You will then need to cast the data in the column to the correct type.
Note that as far as I know all SQL implementations return everything as text, it is then up to you to interpret these as a number, date, binary data (from hex), ...
|
|
|
|
|
Alright! Thanks very much. I have totally forgot about good old structures and pointers to them. Will play with it for a little bit.
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
OK, here is how we do it: (once again, Andrew, you rock!)
typedef struct _DatabaseField
{
DWORD nFieldLen;
wchar_t pFieldData[];
} DatabaseField;
typedef struct _DatabaseRowEx
{
DWORD nColumns;
DatabaseField *pColumns[];
} DatabaseRowEx;
int nColumns = 3, x = 0, rowz = 1;
wchar_t *row1elems[] = {L"aaa", L"bbb", L"ccc"};
wchar_t *row2elems[] = {L"111", L"222", L"333"};
DatabaseRowEx *pRow = (DatabaseRowEx *)malloc(sizeof(DatabaseRowEx) +
sizeof(DatabaseField) * nColumns * rowz);
wprintf(L"Row 1: ");
for(x = 0; x < nColumns; x++)
{
pRow[0].pColumns[x] = (DatabaseField *)malloc(sizeof(wchar_t *) *
wcslen(row1elems[x]) + 1);
wcscpy((wchar_t *)pRow[0].pColumns[x], row1elems[x]);
wprintf(L" [ %s ] ", pRow[0].pColumns[x]);
}
wprintf(L"\r\n");
rowz++;
pRow = (DatabaseRowEx *)realloc(pRow, sizeof(DatabaseRowEx) +
sizeof(DatabaseField) * nColumns * rowz);
wprintf(L"Row 2: ");
for(x = 0; x < nColumns; x++)
{
pRow[1].pColumns[x] = (DatabaseField *)malloc(sizeof(wchar_t *) *
wcslen(row2elems[x]) + 1);
wcscpy((wchar_t *)pRow[1].pColumns[x], row2elems[x]);
wprintf(L" [ %s ] ", pRow[1].pColumns[x]);
}
wprintf(L"\r\n");
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
An abrupt way of doing this is creating a
std::vector<std::vector<std::string> > and create some functions to properly arrange its sizing taking two parameters (rows and cols).
something like:
#include <vector>
#include <string>
class text_table:
public std::vector<std::vector<std::wstring > >
{
typedef std::vector<std::vector<std::wstring > > super;
public:
typedef std::wstring string_t;
void resize(size_t rows, size_t colums)
{
super::resize(rows);
for(size_t i=0; i<rows; ++i)
super::at(i).resize(cols);
}
const string_t& at(size_t rew, size_t col) const
{ return super::at(row).at(col); }
string_t& at(size_t rew, size_t col)
{ return super::at(row).at(col); }
};
If you need to return it from a function, probably a std::auto_ptr may avoid the copy-on return of a relatively huge structure.
Something like:
#include <memory>
#include "texttable.h"
std::auto_ptr<text_table> create_table( ... )
{
std::auto_ptr<text_table> p(new text_table);
p->resize(...);
.... ....
return p;
}
If you want better isolation, you can elaborate by encapsulating (rather then inheriting) the
std::vector<std::vector<std::wstring> > as a private member
and write a brand new interface for all the tex_table operation you may suppose to need.
In that case you can also avoid the use of auto_ptr if you store a pointer (rather than the structure itself) and manage copy and assignment by handling a reference count, and create an effective copy of the data only if the data are shared and needed to be modified.
There are lot of improvements possible!
2 bugs found.
> recompile ...
65534 bugs found.
modified on Tuesday, February 1, 2011 2:58 AM
|
|
|
|
|
Ok, thanks. Although thats not actually what i needed here, but gives some insight too.
Well, i need to return this from function from C dll to c/c++/c# apps, so good old C is the only way :X
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
Hey all, hope everyone had a great weekend.
I have some code where I am passing a string array and some numbers and want to reconcile the two as far as a lookup table. When I want to compare a value in an array to a value passed to the function it wants arg1 to be boolean, but I am not sure the proper syntax. can anyone give me an idea of what I am doing wrong? Also, I am not sure the code will work as written anyway, but this is the only error popping up so far.
double __stdcall HEI_F2(string &arg1, int &arg2)
{
int tp;
int bg;
int counter, typ, bwg, b;
string vl_reg1[16] = {"70-30 Cu-Ni", "90-10 Cu-Ni", "Admiralty Metal", "Aluminum Brass", "Aluminum Bronze", "Arsenical Copper", "Cold-Rolled Low Carbon Steel", "Copper Iron 194 (Olin 194)", "Titanium Grades 1 & 2", "304 SS", "316/317 SS", "N08367 (AL6XN)", "S43035 (TP439)", "S44660 (Sea-Cure)", "S44735 (AL29-4C)"};
string a;
int vl_reg2[10] = {12, 14, 16, 18, 20, 22, 23, 24, 25};
double vl_reg12[16] = {0.71, 0.8, 0.93, 0.92, 0.89, 0.98, 0.81, 1, 0.64, 0.54, 0.53, 0.48, 0.63, 0.58, 0.58};
double vl_reg14[16] = {0.78, 0.85, 0.96, 0.95, 0.93, 1, 0.86, 1.01, 0.71, 0.62, 0.61, 0.56, 0.71, 0.66, 0.66};
double vl_reg16[16] = {0.83, 0.89, 0.98, 0.97, 0.96, 1.01, 0.9, 1.02, 0.77, 0.69, 0.67, 0.63, 0.77, 0.72, 0.72};
double vl_reg18[16] = {0.88, 0.93, 1, 0.99, 0.98, 1.02, 0.94, 1.03, 0.83, 0.75, 0.74, 0.7, 0.82, 0.79, 0.79};
double vl_reg20[16] = {0.92, 0.96, 1.01, 1.01, 1, 1.03, 0.97, 1.03, 0.89, 0.82, 0.81, 0.78, 0.88, 0.85, 0.85};
double vl_reg22[16] = {0.95, 0.98, 1.02, 1.02, 1.01, 1.03, 0.98, 1.04, 0.91, 0.86, 0.85, 0.82, 0.91, 0.89, 0.89};
double vl_reg23[16] = {0.96, 0.99, 1.02, 1.02, 1.01, 1.04, 0.99, 1.04, 0.93, 0.88, 0.87, 0.84, 0.92, 0.9, 0.9};
double vl_reg24[16] = {0.97, 0.99, 1.03, 1.02, 1.02, 1.04, 1, 1.04, 0.94, 0.9, 0.89, 0.86, 0.94, 0.92, 0.92};
double vl_reg25[16] = {0.97, 1, 1.03, 1.03, 1.02, 1.04, 1, 1.04, 0.95, 0.91, 0.9, 0.88, 0.95, 0.93, 0.93};
string vl_reg3[16] = {"vl_reg12", "vl_reg14", "vl_reg16", "vl_reg18", "vl_reg20", "vl_reg22", "vl_reg23", "vl_reg24", "vl_reg25"};
counter = 0;
do{
a = vl_reg1[counter];
if (arg1 = a)
{
tp = counter;
}
counter = counter + 1;
}while (counter <= 16);
counter = 0;
do{
b = vl_reg2[counter];
if (tp = b)
{
bg = counter;
}
counter = counter + 1;
}while (counter <= 10);
return vl_reg3[bg][tp];
}
|
|
|
|
|
jharn wrote: ...but this is the only error popping up so far.
What error?
jharn wrote: if (arg1 = a)
Do not confuse == with = .
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
Sorry, I wasn't clear....
in the part where I compare if (arg1 = a) it tells me expression must have a bool type.
|
|
|
|
|
jharn wrote: in the part where I compare if (arg1 = a) it tells me expression must have a bool type.
Right, you are confusing == with = .
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
Hi, I tried arg1==a, now it says that no operator "==" matches these operands.
|
|
|
|
|
I think you need to use the 'compare' method. It returns 0 if they're equal, a positive int the string is greater, or a negative int if the string is less. Therefore:
if (arg1.compare(a) == 0)
|
|
|
|
|
Is that not an AND function? ==
I guess I am confused.....
|
|
|
|
|
jharn wrote: Is that not an AND function? ==
Uh, no. That is the equality operator.
The two AND operators are bitwise (& ) and logical (&& ).
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
hahahaha......you are SO right, my apologies
|
|
|
|
|
Hi, I tried arg1==a, now it says that no operator "==" matches these operands.
|
|
|
|
|
You are trying to compare two strings. The == operator just compares simple scalar values, not arrays. I'm not a C++ / C# programmer, but if it was C, I'd suggest using the strcmp function - there must be a C++ / C# equivalent. If it was Java, you'd use the equals() method.
|
|
|
|
|
jsc42 wrote: You are trying to compare two strings. The == operator just compares simple scalar values, not arrays.
Neither arg1 nor a is an array. They are both string objects, which has this.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
I apologise! I had forgotten that C++ allows operator overloading.
|
|
|
|
|
You declare your arrays to have 16 elements, but only initialize 15, then access the 17:th element.
string vl_reg1[16] = { };
do{
a = vl_reg1[counter];
counter = counter + 1;
} while (counter <= 16)
It's a mess.
|
|
|
|
|
OK, I see, sorry to bother, I know it usually is not much fun helping a newbie, but I really do appreciate your guidance.
|
|
|
|
|
First off, your code looks like it is supposed to be C++, I'm not an expert on this language. I'm going to assume it is something else because I don't see how this would compile.
I agree with the assessment that the code is a mess no matter what language.
The reason why you aren't blowing up with string vl_reg1[16] = {...} is because the variable is first defined with 16 values in an array and then the {} acts like you said
vl_reg1 = new string[15]
, followed by a loop that fills in 15 values into the new array. Like I said, I'm not an expert. That's what it looks like it is doing. As far as I know C++ doesn't have string as a field. The "new" is probably a mistake on my part because that works great in C#, but entails a huge amount of memory management headaches with C++. (Unless the .Net version of C++ fixes that problem as well.) Anyway in C# you can dynamically change the size of an array if you wish. In C# I would probably say string[] vl_reg1 = {...}
I'm assuming your language supports ubounds(). From your error messages, maybe your language doesn't support "=="?
Change your first while to
}while (counter <= vl_reg1.ubounds(0));
In fact, change your whole do loop to:
do{
a = vl_reg1[counter];
tp = counter++;
}while (counter <= vl_reg1.ubounds(0) && arg1 != a);
You don't have any error checking. Immediately after that execute
if (arg1 != a) return -1.;
You have return vl_reg3[bg][tp];
I don't understand how that would even compile. I know what you are trying to do, but this WON'T do it! (At least in any of the languages I know.) vl_reg3 is a string type single array. You are returning a double value from the routine. You can't change types. All of a sudden you are returning a double array setup from a single array string type. No, it won't automagically determine the string field vl_reg3[bg] needs to be converted to a double type array field and pass back that array's number from the tp location. (Which makes no sense either, but that's what it looks like you are trying to do.
Forget the second loop it is total nonsense. vl_reg2 should be a pointer to the array values you want to use, so keep the numbering scheme you've put into it. These numbers should be a 1 to 1 correllation to the positions of the first argument found in vl_reg1.
Set up a new double array. (call it, say "ret_vals")
Instead of the second array, do some more error checking
if (arg2 < 0) return -2.;// This could be the first line of the code if you want.
if (tp > vl_reg1.ubounds(0)) return -3.;
// You passed a valid array value in the first argument but the second isn't defined yet.
b = vl_reg1[tp];
// There isn't a do loop that will do this, write a line for each array you want to use.
if (b == 12) ret_vals = vl_reg12;
// reassigns the ret_vals array to point to the array of values you want to use.
if (ret_vals == null) return -4.;
// you just screwed up the if tests you were supposed to write
if (arg2 > ret_vals.ubounds(0)) return -5.;
// you just passed too big an argument for the return location in the array values you want to use.
return ret_vals[arg2];
|
|
|
|
|
All, thank you very much for your help and your constructive criticism. I do realize I am a complete newbie and I hope I can improve my programming skills. I do know that the last line of the code would not work (vl_reg3[bg][tp]).....it was written ion visual basic and I was in the process of converting it to C++.
I have since found out that the function in C++ is not receiving the text string I am trying to send form a VBA Declare function, so I guess I need to figure that out first.
All, I know I am not a good programmer, but I ma very persistent so I will keep trying to learn and I hope all of you are not offended by my less than intelligent coding and questions.
|
|
|
|
|
This is the VBA code I was trying to translate from, it is a bit cleaner since I am a bit more familiar with it. Just posting so you can see what I was trying to do.
Function HEI_F2(ByVal typ As Variant, bwg As Integer) As Double 'saturation pressure inHg from Temp
Dim vl_reg1 As Variant, vl_reg2 As Variant, vl_reg3 As Variant, vl_reg12 As Variant
Dim vl_reg14 As Variant, vl_reg16 As Variant, vl_reg18 As Variant, vl_reg20 As Variant
Dim vl_reg22 As Variant, vl_reg23 As Variant, vl_reg24 As Variant, vl_reg25 As Variant
Dim tp As Integer
vl_reg1 = Array("70-30 Cu-Ni", "90-10 Cu-Ni", "Admiralty Metal", "Aluminum Brass", "Aluminum Bronze", _
"Arsenical Copper", "Cold-Rolled Low Carbon Steel", "Copper Iron 194 (Olin 194)", _
"Titanium Grades 1 & 2", "304 SS", "316/317 SS", _
"N08367 (AL6XN)", "S43035 (TP439)", "S44660 (Sea-Cure)", "S44735 (AL29-4C)")
vl_reg2 = Array(12, 14, 16, 18, 20, 22, 23, 24, 25)
vl_reg12 = Array(0.71, 0.8, 0.93, 0.92, 0.89, 0.98, 0.81, 1#, 0.64, 0.54, 0.53, 0.48, 0.63, 0.58, 0.58)
vl_reg14 = Array(0.78, 0.85, 0.96, 0.95, 0.93, 1#, 0.86, 1.01, 0.71, 0.62, 0.61, 0.56, 0.71, 0.66, 0.66)
vl_reg16 = Array(0.83, 0.89, 0.98, 0.97, 0.96, 1.01, 0.9, 1.02, 0.77, 0.69, 0.67, 0.63, 0.77, 0.72, 0.72)
vl_reg18 = Array(0.88, 0.93, 1#, 0.99, 0.98, 1.02, 0.94, 1.03, 0.83, 0.75, 0.74, 0.7, 0.82, 0.79, 0.79)
vl_reg20 = Array(0.92, 0.96, 1.01, 1.01, 1#, 1.03, 0.97, 1.03, 0.89, 0.82, 0.81, 0.78, 0.88, 0.85, 0.85)
vl_reg22 = Array(0.95, 0.98, 1.02, 1.02, 1.01, 1.03, 0.98, 1.04, 0.91, 0.86, 0.85, 0.82, 0.91, 0.89, 0.89)
vl_reg23 = Array(0.96, 0.99, 1.02, 1.02, 1.01, 1.04, 0.99, 1.04, 0.93, 0.88, 0.87, 0.84, 0.92, 0.9, 0.9)
vl_reg24 = Array(0.97, 0.99, 1.03, 1.02, 1.02, 1.04, 1#, 1.04, 0.94, 0.9, 0.89, 0.86, 0.94, 0.92, 0.92)
vl_reg25 = Array(0.97, 1#, 1.03, 1.03, 1.02, 1.04, 1#, 1.04, 0.95, 0.91, 0.9, 0.88, 0.95, 0.93, 0.93)
vl_reg3 = Array(vl_reg12, vl_reg14, vl_reg16, vl_reg18, vl_reg20, vl_reg22, vl_reg23, vl_reg24, vl_reg25)
counter = 0
Do While counter <= UBound(vl_reg1)
If typ = vl_reg1(counter) Then
tp = counter
Exit Do
End If
counter = counter + 1
Loop
counter = 0
Do While counter <= UBound(vl_reg2)
If bwg = vl_reg2(counter) Then
bg = counter
Exit Do
End If
counter = counter + 1
Loop
HEI_F2 = (vl_reg3(bg)(tp))
End Function
|
|
|
|
|