Retrieve item value from DWORD_PTR in combobox? - combobox

I want to Retrieve the item value(string) s
where is s is
DWORD_PTR s = m_laybox.GetItemData(idx);
Basically, s is selected item and I am saving in config
now how can I get item value(string) from s

Well, there are multiple strategies. One thing you must know is that the data must exist (more or less) for the lifetime of the combobox. You don't have to put strings in the combobox. You can, but you can also put object pointers into the combobox (as the item data).
One way I like to do things is to have an array of items and then store an index into the combo box.
But, consider that you put "strings" into the combo box....
You do something like:
say pString is a TCHAR* (or char* or wchar_t*)
// for all the items you need to add ....
int idx = m_combo.AddString(pString); // or something different
m_combo.SetItemDataPtr(idx, pString);
Afterword, in response to a CBN_SELENDOK or CBN_SELCHANGE, you want to get the data...
You will be given an idx ....
TCHAR* pRetrieved = reinterpret_cast<TCHAR*>(m_combo.GetItemDataPtr(idx);
CComboBox::GetItemDataPtr() returns an LPVOID. You need to cast that to the type you want.
For a diff example, consider this record...
struct ClientInfo
{
CString m_Name;
int m_CliendID;
CString m_Address;
};
Consider that maybe you have an array of these records:
CArray<ClientInfo> m_arrayClientInfo;
Somewhere later you initialize it. Then you want to fill the combo box during a dialog. You do something like:
for (int i = 0; i < m_arrayClientInfo.GetCount(); ++i)
{
int idx = m_combo.AddString(m_arrayClientInfo[i].m_Name);
m_combo.SetItemDataPtr(idx, i); // store index, not pointer, but you could store pointer
}
Sometime later in the program when you want to get the data ...
int nArrayIndex = reinterpret_cast<int>(m_combo.GetItemDataPtr(idx));
const ClientInfo& clientInfo = m_arrayClientInfo[nArrayIndex];
Those are the basics...don't guarantee anything compiles or works...but it's close

Related

C: Additional chars in char array when using scanf to put "string" in char array,

I am experiencing an issue regarding the comparison of strings (arrays of chars).
The code below is not my program but rather a simulation of what I am doing.
I have a struct, which stores an item's name.
I later have a user search for items using an input name,
which matches a struct Item's instance name (like Xenon) with that user input.
However, the input string contains gibberish, which I will show.
I have added '\0' to the end of my char, so this should not be an issue,
unless I am doing that incorrectly.
To be more clear,
A user enters, "Xenon", so we find the instance of struct Item that
has "Xenon" as its name value.
// Section #A
// I store structs in this dynamically allocated array.
// Later, users can access item instances, if needed.
struct Item *struct_arr = malloc( sizeof(struct Item)*SIZE );
struct Item
{
char name[16];
float price;
int quantity;
int id_num;
};
struct Item item1;
strcpy(item1.name, "Xenon"); // i explicitly set this instance
item1.price = 125;
item1.quantity = 2;
item1.id_num = 1;
struct_arr[0] = item1;
// Section #B
char name[16]; // also tried 17
name[16] = '\0'; // or 17, tried 17
scanf("%s", name); // assume I enter, "Xenon"
// res outputs 2
int res = strcmp(item1.name, name); // They are not the same, though when printed, "Xenon" and "Xenon"
// THE ISSUE IS BELOW : THE SOLUTION IS SET strcmp == 0
for (int i=0; i < SIZE; i++) {
if (strcmp(struct_arr[i].name, name)) { // strcmp(struct_arr[i].name, name) == 0
int res = strcmp(struct_arr[i].name, name); * #A
break;
}
}
// i then proceeded to gdb to see what was going on. Read on
In gdb, I step to the point in my program where
I am using the user's input (stored in char array "name")
to select the correct struct Item instance.
Gdb gives results like the following:
print name
"Xenon\000\000\000\372วง\367\377\177\000"
print item1.name
"Xenon\000\000\000\000\000\000\000\000\000\000"
This may be cumbersome, but I will include a printf result from C.
This result simultaneously looks at parallel chars; that is,
from i=0 to i<16, it looks at item1.name[i] and name[i].
// Output is i, item1.name[i], name[i]
each: i is 0,X,X
each: i is 1,e,e
each: i is 2,n,n
each: i is 3,o,o
each: i is 4,n,n
each: i is 5,,
each: i is 6,,
each: i is 7,,
each: i is 8,,โ–’
each: i is 9,,G
each: i is 10,,โ–’
each: i is 11,,โ–’
each: i is 12,,A
each: i is 13,
each: i is 14,,
each: i is 15,,
Clearly these two strings are not the same.
The string from user input has some gibberish inside of it,
while item1.name's string looks fairly "clean".
I am not sure of what the issue is.
My logic is that, although name[16] is not in the memory that I reserved,
if we place '\0' following name[15], then if we do hit '\0' when iterating over name
we will still run into that memory location, for 15 and 16 are adjacent in memory.
I do not think this is the issue.
Furthermore, when I set the attribute "name" of item1, it implicitly adds '\0' to my knowledge,
for we are assigning a string "", not a char '', to the array char name[16]. C abstracts this.
With that said, once again, I am not completely sure what the issue is.
It seems that I overlooked the fact that I left out " == 0" when performing the comparison with "strcmp(a,b)". Sleep is important. That is all this post teaches. Thanks to all who looked for an issue that I did NOT state in the first edition. Apologies.

Cloning a struct?

I have some structs like the below:
typedef struct {
GLubyte red, green, blue;
} pixel;
typedef struct {
pixel *pixelData;
int w, h;
} imagen;
It's for an image loader and image processor (applies filters to a loaded image).
I'm initializing two imagen:
imagen work, original;
work is something that I want to display after having some filters applied, and original is something I can reset to.
void loadImage() {
//load data into (imagen)original
}
work = original;
After loading the image, I copy it to work so I can maintain a copy of the original should I want to reset later (reset being work = original again). The problem I'm facing is that the reset doesn't work: anything I apply to work is also applied to original, so I'm effectively resetting to what I'm resetting.
I think the problem is my work = original; I'm fairly new to C, but I'm assuming I'm only pointing work at original, so any logic I do on work is also applied to original?
original.w = 40;
work = original;
work.w = 50;
work = original;
Is work.w 40 or 50 in this case? If it is indeed pointing to original, how do I instead clone original onto work, so I can safely work on work without consequence of original?
You have a pixelData pointer in your struct:
typedef struct {
pixel *pixelData;
int w, h;
} imagen;
In order to create a completely independent copy, you need to copy the data pixelData is pointing to:
work.w = original.w;
work.h = original.h;
size_t size = sizeof(pixel) * work.w * work.h;
work.pixelData = (pixel*)malloc(size);
memcpy(original.pixelData, work.pixelData, size);
Also note that when you no longer need it you have to release the allocated memory:
free(work.pixelData);
I think the problem is in the pointer to pixeldata. When you assign it, you are copying the address of the value stored in original, and once you modify it with, the original is modified too. Try allocating a new pixelData pointer and then copy the original content in its value, instead of copying the pointed address itself.

Changing a structs string

I'm using lex to implement a scanner. I want to build a symbol table while parsing. I have two structs, SymbolEntry and SymbolTable (below). Most of the time, when I call my function for inserting a symbol (registerID, also below) I have all the information for the entry. However, when I have a constant I also want to get it's value, but that is not immediately available when I first create the entry. When I try to change the entries value later in the code, I'm invalidating the whole memory block used by that entry and the name and value are printing garbage.
Here are the two structs:
typedef struct{
char* type;
char* name;
char* value;
} SymbolEntry;
typedef struct{
SymbolEntry *entries;
size_t size;
size_t capacity;
} SymbolTable;
This is the registerID function, called when an {id} is matched. yytext contains the ID.
int registerID(char* type){
//create a new symbol entry with the specified type and name and a default value
SymbolEntry e;
e.type = type;
e.name = (char *)calloc(yyleng+1, sizeof(char));
strcpy(e.name, yytext);
e.value = "";
prevSym = insertSymbol(&table, e);
return prevSym;
}
This is the relevant code for insertSymbol(SymbolTable* st, SymbolEntry entry). pos is always the last element in the array when inserting (otherwise the entry isn't unique and pos is just returned).
st->entries[pos].name = (char *)calloc(strlen(entry.name)+1, sizeof(char));
st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
st->entries[pos].value = (char *)calloc(strlen(entry.value)+1, sizeof(char));
strcpy(st->entries[pos].name, entry.name);
strcpy(st->entries[pos].type, entry.type);
strcpy(st->entries[pos].value, entry.value);
Later, after the lex framework has matched the value immediately following a CONSTANTs name, this code is performed (directly in the rule for <CONSTANT_VAL>{number})
table.entries[prevSym].value = (char *)calloc(yyleng+1, sizeof(char));
strcpy(table.entries[prevSym].value, yytext);
Why does this invalidate the the SymbolEntry at this position in the array, and how can I safely change the contents of value?
EDIT:
It doesn't only happen with constants. The first two SymbolEntrys are always garbage. I'm assuming that probably means they ALL are, but the others just haven't been overwritten.
Also, it seems like subsequent calls to registerID is causing the data to get corrupted. With just 9 symbols, only the first two are garbage, with 34, it's the first 7. Adding more text to parse without variables did not cause any issues.
SOLVED
Well it turns out that I just accidentally deleted a line somewhere along the way and that's what introduced the bug. I accidentally erased my call to initSymbolTable. Thanks to chux for asking me how I initialized the table. Sorry about that.
2 potential problems.
1 - Compare
// Fields set with non-malloc'ed memory
e.type = type;
e.value = "";
// Fields set with malloc'ed memory
st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
st->entries[pos].value = (char *)calloc(strlen(entry.value)+1, sizeof(char));
strcpy(st->entries[pos].type, entry.type);
strcpy(st->entries[pos].value, entry.value);
Both of these set the fields to valid memory and in the second case, dynamically fill the memory. The concern is subsequent use. How does OP know to free() or realloc() the second kind and not the first. Further concern: With registerID(char* type), how do we know the value passed to type is still valid way later when that pointer is used via field type. Suggest:
e.type = strdup(type); // or the usual strlen()+1, malloc() and copy
e.value = strdup("");
2 - The type and setting of yyleng are not shown. Maybe it is not big enough as compared to strlen(e.name), etc.?
[Edit] after review, I real think e.type = type; is the problem. e.type needs its own copy of type.
Minor: Consider
// st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
// strcpy(st->entries[pos].type, entry.type);
size_t Length = strlen(entry.type) + 1;
st->entries[pos].type = malloc(Length);
memcpy(st->entries[pos].type, entry.type, Length);

how do i delete arrays of typedef structs?

I am trying to delete an array of initialized structs e.g. reset the array
My struct:
struct entry{
char name[NAME_SIZE];
int mark;
};
typedef struct entry Acct;
Acct dism2A03[MAX_ENTRY];
Acct clear[0]; << temp struct to set original struct to null
My attempt:
entry_total keeps track of how many structs in the struct array dism2A03[x] have values set in them.
I tried to create an empty array of the same struct clear[0]. Looped through initialized arrays in dism2A03[x] and set them to clear[0]
for(m=0;m<entry_total;m++){
dism2A03[m]=clear[0];
}
break;
However, it is setting them to 0, i want them to become uninitialized e.g. no values in them
You cannot have memory with no value in it. It's physically impossible. It's due to the laws of physics of our universe :-)
Also, this:
Acct clear[0];
is wrong. You cannot have an array with zero elements. Some compilers will allow this as an extension, but it's not valid C. And for the compilers that allow this, it doesn't do what you think it does.
It would seem to me that what you want instead is to resize the array. To do that, you would need to copy the elements you want to keep into a new array, and then free() the old one. To do that, you need to create dism2A03 using dynamic memory:
Acct *dism2A03 = malloc(sizeof(Acct) * MAX_ENTRY);
if (dism2A03 == NULL) {
// Error: We're out of memory.
}
(malloc() returns NULL if there's no more free memory, and the code checks that. Usually all you can do if this happens is terminate the program.)
When you want a new array with some elements removed, then you should back up the starting address of the current one:
Acct* oldArray = dism2A03;
then create a new one with the new size you want:
dism2A03 = malloc(sizeof(Acct) * NEW_SIZE);
if (dism2A03 == NULL) {
// Error: We're out of memory.
}
copy the elements you want from the old array (oldArray) to the new one (dism2A03) - which is up to you, I don't know which ones you want to keep - and after than you must free the old array:
free(oldArray);
As a final note, you might actually not want to create a new array at all. Instead, you could keep having your original, statically allocated array ("statically allocated" means you're not using malloc()):
Acct dism2A03[MAX_ENTRY];
and have a index variable where you keep track of how many useful elements are actually in that array. At first, there are 0:
size_t dism2A03_size = 0;
As you add elements to that array, you do that at the position given by dism2A03_size:
dism2A03[dism2A03_size] = <something>
++dism2A03_size; // Now there's one more in there, so remember that.
While doing so, you need to make sure that dism2A03_size does not grow larger than the maximum capacity of the array, which is MAX_ENTRY in your case. So the above would become:
if (dism2A03_size < MAX_SIZE) {
dism2A03[dism2A03_size] = <something>
++dism2A03_size; // Now there's one more in there, so remember that.
} else {
// Error: the array is full.
}
As you can see, adding something to the end of the array is rather easy. Removing something from the end of the array is just as easy; you just decrement dism2A03_size by one. However, "removing" something from the middle of the array means copying all following elements by one position to the left:
for (size_t i = elem_to_remove + 1; i < dism2A03_size; ++i) {
dism2A03[i - 1] = dism2A03[i];
}
--dism2A03_size; // Remember the new size, since we removed one.
Note that you should not attempt to remove an element if the array is empty (meaning when dism2A03_size == 0.)
There's also the case of adding a new elements in the middle of the array rather than at the end. But I hope that now you can figure that out on your own, since it basically a reversed version of the element removal case.
Also note that instead of copying elements manually one by one in a for loop, you can use the memcpy() function instead, which will do the copying faster. But I went with the loop here so that the logic of it all is more obvious (hopefully.)
when you declare an array in this way Acct dism2A03[MAX_ENTRY]; the array is allocated in the stack, therefore it will be removed when the function will perform the return statement.
What you can do is to allocate the structure in the heap via malloc/calloc, and then you can free that memory area via the free function.
For example :
typedef struct entry Acct;
Acct * dism2A03 = calloc(MAX_ENTRY, sizeof( struct entry));
// ....
free(dism2A03);

Keeping only a few changes from the data structure

I was not sure, about the title of the question, but here's the problem.
I have an array of structures, now I pass it by reference to a function, where in, I have a priority queue, of the same structures.
Now, I process my array, by making use of the priority queue, and in the end of the process, I will have two of the attributes(say A and B) of my structure, in array changed, while I want only one of the change(A) to be reflected outside the function, and I want the other(B) change to be restored, the way it was before passing the array. I have to do it, because for the second time when I have to process the same array, but with different parameters, I want the changes of A to remain, but B to not.
What I do right now is that, after the process, once I am out of the function, I process the entire array, and where ever I have the value changed for attribute B I revert it back to the initial value. Now this is obviously a O(n2) operation which is no good for me.
Can I do something to make it more efficient.
I am working with C.
If your B is of type bool for example, you can create a bool array in the function. Use the indices of the input array (integers) in the priority queue instead of structures. Use the bool array to access the Bs of the input array:
void func(Type *Input, size_t n)
{
bool B[n];
queue<size_t> pqueue;
for (size_t i = 0; i < n; i++)
B[i] = Input[i].B;
size_t index;
while (index = pqueue.front()) {
// do something with Input[index]
// B[index] = false;
// rest of the function
}
}

Resources