|
Message Closed
modified 15-May-23 19:07pm.
|
|
|
|
|
If you pass a list of random types (numbers, strings, objects), then your function needs some method of determining what each reference is. That is why printf (and its derivatives) requires a format string to identify the type of each parameter.
|
|
|
|
|
Message Closed
modified 15-May-23 19:07pm.
|
|
|
|
|
I'm not sure exactly where you're stuck. But lets start with the example you gave in your original post:
void PrintFloats (int n, ...)
{
int i;
double val;
printf ("Printing floats:");
va_list vl;
va_start(vl,n);
for (i=0;i
Assuming that you're stuck here, then you might complete this something like
for(i = 0; i < n; ++i) {
val = va_arg(vl, float);
printf("%f ", val);
}
va_end(vl);
putchar('\n');
In this case I'm assuming that the int n parameter tells the function how many float values to expect. Other options to tell a variadic function how many arguments to expect are to use some sort of format string, like printf() does, or you can use some sort of sentinel value for your function e.g.
PrintFloats(1.1, 2.2, -15.2, nan("")); In this case we have assumed that a NaN won't be part of the input string, so is a fair choice for a sentinel.
Keep Calm and Carry On
|
|
|
|
|
Message Closed
modified 15-May-23 19:07pm.
|
|
|
|
|
It's pretty straight forward, really. When you use the va_arg macro, the second argument is the received objects type. So, to receive a pointer to a type, you use va_arg(args, Obj*) where Obj is some object type - e.g. class, int, double, struct, etc. Here's a short working example:
#include <cstdarg>
#include <iostream>
struct S {
int data;
S(int d) : data(d) {}
};
void f(size_t n, ...)
{
va_list args;
va_start(args, n);
for(size_t i = 0; i < n; ++i) {
S* ptr = va_arg(args, S*);
std::cout << ptr->data << '\n';
}
}
int main()
{
S item1(1);
S item2(2);
S item3(3);
f(3, &item1, &item2, &item3);
}
Keep Calm and Carry On
|
|
|
|
|
As I said, you need some control to identify hoe many parameters are being passed, and what type they are. There is no other way of knowing when you get to the end of the list.
|
|
|
|
|
I wrote this linked list code. Could someone confirm I`m doing it the way I`m supposed to.
class SomeNode
{
public:
int data;
SomeNode * next;
};
SomeNode * BuildList()
{
SomeNode * Tail;
Tail = (SomeNode*)malloc(sizeof(SomeNode));
Tail->next = NULL;
Tail->data = 100;
SomeNode * Temp;
bool firstrun = true;
for(int i =0; i < 5; i++)
{
if(firstrun)
{
Temp = AddTo(&Tail,i);
firstrun = false;
}
else
{
Temp = AddTo(&Temp,i);
}
}
return Temp;
}
SomeNode * AddTo(SomeNode ** Source, int somedata)
{
SomeNode * NewSN;
NewSN = (SomeNode*)malloc(sizeof(SomeNode));
NewSN->data = somedata;
NewSN->next = (*Source);
return NewSN;
}
|
|
|
|
|
- Since your code is C++ then why do you use malloc rather than new?
- How and where do you free your allocated in heap memory?
|
|
|
|
|
Thanks for your feedback Victor.
Since these are your only observations I take it that overall my code is within 'allowed' range.
malloc: Using it doesn`t seem to break anything so why not.
free: the code is just a display of how things would work in principle.
modified 18-Mar-22 7:20am.
|
|
|
|
|
One thing it is not good using malloc in C++ apps is because the class ctor is not called.
I see you are trying then to "solve" this problem using this code:
<pre lang="C++"> SomeNode * Tail;
Tail = (SomeNode*)malloc(sizeof(SomeNode));
Tail->next = NULL;
Tail->data = 100;
But you wiil need to do it in every place you will create the class instance and, moreover, after some updates in the class members you will have to look for all the occurrences of such a malloc and update the class member initializations accordingly!
|
|
|
|
|
Quote: One thing it is not good using malloc in C++ apps is because the class ctor is not called.
well I`m not really chasing the perfect solution, to be honest I haven`t even got to use the feature that much until now, my projects were simple enough to go about without using new/malloc
Again huge thanks for helping me sort this out.
modified 18-Mar-22 16:36pm.
|
|
|
|
|
I have an update. This is a function for inserting nodes in the middle of the list. Is this a good approach? I did a quick test and it looks like it`s doing what it should.
void InsertTo(SomeNode ** FrontTip, int NewNodeData, int InsertInFrontOfNodeCount, int TotalNodeCount)
{
SomeNode * Temp;
SomeNode * NewNode;
SomeNode * Previous;
NewNode = (SomeNode*)malloc(sizeof(SomeNode));
NewNode->data = NewNodeData;
bool firstrun = true;
for(int i =0; i < TotalNodeCount;i++)
{
if(i == InsertInFrontOfNodeCount)
{
NewNode->next = Temp;
Previous->next = NewNode;
}
else
{
if(firstrun)
{
Temp = (*FrontTip)->next;
firstrun = false;
}
else
{
Previous = Temp;
Temp = Temp->next;
}
}
}
}
|
|
|
|
|
Just a few more things on top of what Victor said:
1. Typically the chaining structure comes before the payload (the data part). That allows you to have different sizes of objects in your list without having to modify the list management code.
2. Again in the typical case, the function that creates or extends the list (BuildList function in your example) receives a structure containing the list head and tail. That way you can easily add new elements at either end and this is the most common operation.
3. In general you should be very, very, very sure that you need to use a linked list. Linked lists perform poorly because they don't make good use of cache. For a longer discussion about this see Bjarne Stroustrup: Why you should avoid Linked Lists - YouTube[^] and also Are lists evil? -- Bjarne Stroustrup : Standard C++[^].
Mircea
|
|
|
|
|
CalinNegru wrote: Could someone confirm I`m doing it the way I`m supposed to. Maybe you meant to phrase it differently, but what is the "supposed to" way to which you refer? There are multiple ways to code a linked list, and only you know what goal(s) you are trying to meet.
"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
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
It`s just a first time linked list implementation experience, I want to know if I`m not doing foolish things.
Quote: There are multiple ways to code
I knew there is more than one approach when writing a linked list, but is there `that` many ways to do it?
|
|
|
|
|
hi
Below is the code I have for Drawing a Pie give a percentage thing is it looks nice and I traced a percent of 10.000 however calculation of x & y are negative and it ends up (the pie) being on the left side of the circle
Wondering if I am doing anything wrong after getting to 2 CPoints and I do a CDC:Pie
CPie::CPie(double percentage, PieWnd *pieptr)
{
piecalc(pieptr->currpercent, &piepointstart, pieptr);
piecalc(percentage, &piepointend, pieptr);
pieptr->currpercent = percentage;
}
CPoint *CPie::piecalc(double percent, CPoint *firstpt, PieWnd *pieptr)
{
double PI = 3.1415926535897931;
double angle = percent / 100;
angle = angle * 360;
CRect pierect;
double radius = pieptr->ellipserect.Height() / 2;
double offx = (radius * sin(angle));
double offy = (radius * cos(angle));
double origx = (pieptr->ellipserect.right + pieptr->ellipserect.left) / 2;
double origy = (pieptr->ellipserect.top + pieptr->ellipserect.bottom) / 2;
firstpt->x = origx + offx;
firstpt->y = origy + offx;
return firstp
|
|
|
|
|
Try this:
angle = percent / 50 * PI
Mircea
|
|
|
|
|
or I think I can divide the radius rect.right - rect.lef2 / 2 thank it worked
|
|
|
|
|
How to compress IPv6 address using VC++
|
|
|
|
|
|
Hi
I have few questions about the above two items first for the EDITWORDBREAKPROCA if my edit control is part of CRicheditCtrl does the callback proc have to be a member of the Cricheditctrl
or can it be like my STEAMIN function
if the callback is a class member how would you code the sendmessage when I code CrichEditctrl->Sendmessage(EM_SETWORDBREAKPROC,0,(LPARAM) &CStroage::editworbreak) I get complier messages saying invalid type conversion
Next do I need a message map entry for EM_EDITWORDPBREAKPROC such as ON_MESSAGE(EM_EDITWORDBREAKPROC,&CStroage::editwordbreak) if so there is a problem with this because the ON_MESSAGE takes a LRESULT MEMBERX (wparam, lparam) not the paraamter of the call back
in the Call back if I want to line break 0n 0x0a0d
then the code would be the following the doc is not that stright forward thanks in advance for anyone who helps me clarify
switch (code)
{
case WB_ISDELIMITER:
if (lpszEditText[ichCurrent] == 0x0a0d)
return TRUE;
else
return FALSE;
break;
|
|
|
|
|
This "header" to you're lengthy on-going (no sarcasm here ... I too use MS VS) battle with AFX/MFC uses Rich Edit 2.0? And that is why there's no EditWordBreakProcEx and you're usg EditWordBreakProc "in support of passing UNICODE" (from the docs)?
|
|
|
|
|
quite honestly dont know what you are saying
|
|
|
|
|
"from the docs" ... the help files. See the Main Menu help button? F1 (on an unknown method/function/etc has always been my friend when it came to the docs).
modified 10-Mar-22 16:01pm.
|
|
|
|