Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Null Pointer
May 20, 2004

Oh no!

volatile bowels posted:

The expression (!((3-5%2) < 5 && (6/4 > 3 ))) is supposed to be a true statement. What does the ! mean in the beginning?

Logical negation.

Adbot
ADBOT LOVES YOU

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Null Pointer posted:

Logical negation.
Or more colloquially, "not".

Screeb
Dec 28, 2004

status: jiggled

rjmccall posted:

It's not in GCC yet. I'm not sure it's anywhere yet, actually; I have a bug sitting on me to implement it in Clang, so I'm naturally curious, but it might be awhile. :)

Ah, ok, cool. I should try out Clang one day. Would be interesting to see how the performance is compared to VS. Hell, I haven't even tried compiling this with anything other than VS.

rjmccall posted:

Interesting. I'm really surprised that you see any significant time difference from having one per-object vs. having one on the stack; if you're serious about this, you might want to check the assembly to see what exactly is going on.

Well, turns out that when the array is per-object, the function gets inlined and seemingly optimised a bit more (though I don't know enough assembly to be able to tell exactly what it's doing in that respect). I can't tell why the heap version is even faster though.

Thanks for all the help man.

HFX
Nov 29, 2004
Anyone have a recommendation for an embedded HTTP server that does not use FD_SET?

My application uses a large number of non TCP connections. Unfortunately, the embedded HTTP server we use for control and status monitoring use select() and FD_SET and this is leading to a crash under Linux.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

I have a question about STL containers. If I have a function that generates N objects containing random discrete values, and I want to count how many of the same objects I generate, what kind of container should I use? For example, I generate an object with some variables A and B inside. After I'm finished the random generation, I want to count how many times I generated an object with A and B.

So far I've been using a vector< pair<int, myclass*> > but I'm having some trouble with the implementation. I guess I'm interested in knowing if this is a good way to go or if there is already a better container I should be using.

Thanks for any help.

A MIRACLE fucked around with this message at 23:29 on Mar 31, 2011

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Probably at least worth looking at std::multimap or std::multiset, though it's hard to tell from your description.

UraniumAnchor
May 21, 2006

Not a walrus.

A MIRACLE posted:

I have a question about STL containers. If I have a function that generates N objects containing random discrete values, and I want to count how many of the same objects I generate, what kind of container should I use? For example, I generate an object with some variables A and B inside. After I'm finished the random generation, I want to count how many times I generated an object with A and B.

So far I've been using a vector< pair<int, myclass*> > but I'm having some trouble with the implementation. I guess I'm interested in knowing if this is a good way to go or if there is already a better container I should be using.

Thanks for any help.

If you simply care about a count of a particular configuration and not attaching anything to a particular object, you could use a map<myclass, int>, but you'd have to make a comparison function in your object. Specifically, operator <, since that's how map decides where to put things. Alternately, if A and B are already types that can be compared, you could use a map<pair<A,B>,int>.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

roomforthetuna posted:

Probably at least worth looking at std::multimap or std::multiset, though it's hard to tell from your description.

To be more specific I have a vector of cities (my class) and I want to generate "packages" with random origins and destinations. After I'm done I need to print out the top routes, the top origins and the top destinations. So I have 2 vector< pair<int, city*> > origin and destination, and a vector< pair<int, package*> > which holds the packages and their count. The implementation is getting hairy and I was looking for alternatives.

Nomikos
Dec 31, 2003

I'm writing a C++0x program that needs to accept a bunch of command-line options in the standard way, you know, --long_options, -s short options, with and without arguments, multiple file names, "--" to stop scanning, etc.

Normally I would use Boost.ProgramOptions but I'm trying to give up Boost and stick to the shiny new C++0x standard library from now on. I don't need any really hairy features from ProgramOptions, just parsing boolean, string, and integer options and filenames from the command line. What's my best, easiest, nicest-looking option?
  • Use getopt(3) directly?
  • Write a much smaller ProgramOptions-like wrapper around getopt(3)?
  • Roll my own smaller ProgramOptions-like thing, making use of shiny new C++0x features to make it easier?
  • Say 'gently caress it' and bring in Boost, pissing off anyone who tries to compile my program, including myself?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

A MIRACLE posted:

To be more specific I have a vector of cities (my class) and I want to generate "packages" with random origins and destinations. After I'm done I need to print out the top routes, the top origins and the top destinations. So I have 2 vector< pair<int, city*> > origin and destination, and a vector< pair<int, package*> > which holds the packages and their count. The implementation is getting hairy and I was looking for alternatives.
Probably least effort would be to keep your cities and packages the same, and change the vector< pair<int, package*> > into a map< package*,int,PackagePointerCompare >
code:
class PackagePointerCompare {
public:
  bool operator()(const package* a,const package* b) {return *a<*b;}
}
(This will require the package class to have a less-than operator - you might also consider making the map of packages instead of package-pointers, which would be simpler.)

Then adding packages and updating their count would be simply
code:
std::map<package*,int,PackagePointerCompare> Packages;
Packages[currentpackage]+=1; //creates the entry if it doesn't exist, increments if it does

That Turkey Story
Mar 30, 2003

Nomikos posted:

  • Say 'gently caress it' and bring in Boost, pissing off anyone who tries to compile my program, including myself?

I highly recommend just using Boost.Program_Options. Unless you have a really solid reason not to, it's probably not worth the time of developing and debugging your own solution, and anyone familiar with Boost.Program_Options will be able to understand your code immediately if you go the Boost route (and if they aren't, there's already documentation written for them to reference).

Hughlander
May 11, 2005

A MIRACLE posted:

To be more specific I have a vector of cities (my class) and I want to generate "packages" with random origins and destinations. After I'm done I need to print out the top routes, the top origins and the top destinations. So I have 2 vector< pair<int, city*> > origin and destination, and a vector< pair<int, package*> > which holds the packages and their count. The implementation is getting hairy and I was looking for alternatives.
One option would be:
code:
struct PackageCounts
{
    PackageCounts()
        : m_pPackage(NULL)
        , m_nCount(0)
        { }

    PackageCounts(package* pInPackage, int nInCount)
        : m_pPackage(pInPackage)
        , m_nCount(nCount)
        { }

    bool operator<(const PackageCounts& rhs)
    {
        return this->m_nCount < rhs.m_nCount;
    }

    package* m_pPackage;
    int m_nCount;
};
typedef std::vector<PackageCounts> PackageCountsVector;
PackageCountsVector vecPackageCounts;

vecPackageCounts.push_back();
std::sort(vecPackageCounts.begin(), vecPackageCounts.end());
for( PackageCountsVector::iterator it = vecPackageCounts.begin() ; it != vecPackageCounts.end() ; ++it )
{
    print(*it);
}
Repeat for city.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

roomforthetuna posted:

Probably least effort would be to keep your cities and packages the same, and change the vector< pair<int, package*> > into a map< package*,int,PackagePointerCompare >
code:
class PackagePointerCompare {
public:
  bool operator()(const package* a,const package* b) {return *a<*b;}
}
(This will require the package class to have a less-than operator - you might also consider making the map of packages instead of package-pointers, which would be simpler.)

Then adding packages and updating their count would be simply
code:
std::map<package*,int,PackagePointerCompare> Packages;
Packages[currentpackage]+=1; //creates the entry if it doesn't exist, increments if it does

Thanks! Can I sort or otherwise get the packages in order of the int? That's what I really need.

wellwhoopdedooo
Nov 23, 2007

Pound Trooper!

Nomikos posted:

I'm writing a C++0x program that needs to accept a bunch of command-line options in the standard way, you know, --long_options, -s short options, with and without arguments, multiple file names, "--" to stop scanning, etc.

Normally I would use Boost.ProgramOptions but I'm trying to give up Boost and stick to the shiny new C++0x standard library from now on. I don't need any really hairy features from ProgramOptions, just parsing boolean, string, and integer options and filenames from the command line. What's my best, easiest, nicest-looking option?
  • Use getopt(3) directly?
  • Write a much smaller ProgramOptions-like wrapper around getopt(3)?
  • Roll my own smaller ProgramOptions-like thing, making use of shiny new C++0x features to make it easier?
  • Say 'gently caress it' and bring in Boost, pissing off anyone who tries to compile my program, including myself?

I'd recommend against trying to write your own OO wrapper around the system-provided getOpt--I did it a few years ago and it was a loving nightmare. Its insistence on modifying the array you send it will drive you up a wall trying to make a const .process(), and the various subtle differences on different environments make practically everything you would normally do to make life easy, impossible. This is before you start trying to code around the really lovely (and common) implementations of it.

gently caress getOpt forever. You're only going to process your options once in a given program, and pretending there's any sort of OS-level standard is like you and your friends getting together and pretending you're all cool--sure, everybody you ask agrees, but it's untrue and the first time you try to capitalize on it or ask someone outside your group of friends you'll find out just how much. In short, use whatever method is fastest and easiest at the moment (in my experience, usually just parsing it myself, unless the framework/standard library/whatever provides an easy-to-use implementation) and get on to writing the useful stuff.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

A MIRACLE posted:

Thanks! Can I sort or otherwise get the packages in order of the int? That's what I really need.
I guess you could do it fairly lazily by making a std::multimap<int,package*> and interating through the other list cross-copying the contents, which would give you a sorted-by-int structure once the copy is done. But it's starting to look less like a map is the structure you want when you're needing it sorted both ways like this - maybe a vector is better because you can sort it on demand, but then the 'find' aspect is uglier while adding entries. Not sure.

nielsm
Jun 1, 2009



I'd say initially use a map for counting:

std::map<package*,int> packagemap;
for each city { packagemap[city.package] += 1; }

Something like that, I'm honestly not sure if I've understood the problem completely. (Using the fact that the default construction of an int yields a zero.)

After counting everything, copy the contents of the map into a vector as pairs and sort the vector on the int in the pair. I think that should still keep you at O(n log n) complexity, although it does have a bunch of copying. Reserve space in the vector before copying to make it a little less bad.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

Well I ended up just using a vector of pairs. I made a noob mistake and passed the vector by value to my insert/increment function instead of by reference. Once I fixed that it worked.

MrMoo
Sep 14, 2000

HFX posted:

Anyone have a recommendation for an embedded HTTP server that does not use FD_SET?

My application uses a large number of non TCP connections. Unfortunately, the embedded HTTP server we use for control and status monitoring use select() and FD_SET and this is leading to a crash under Linux.

It sounds that part of your project has overridden FD_SETSIZE so that calculations inside the FD_SET() macro are invalid causing the crash. The resolution would be to define the same size for the entire project.

Otherwise you would have to bump up to using poll() instead.

Nomikos
Dec 31, 2003

Thanks for the replies. I looked through the other libraries I'm already using and discovered that Gtkmm depends on Glibmm, which includes a very reasonable wrapper for the Glib options parser. This should have been fairly obvious now that I think about it.

HFX
Nov 29, 2004

MrMoo posted:

It sounds that part of your project has overridden FD_SETSIZE so that calculations inside the FD_SET() macro are invalid causing the crash. The resolution would be to define the same size for the entire project.

Otherwise you would have to bump up to using poll() instead.

It is a defined limit under Linux. The section of code that generates a lot of sockets and keeps them open is not a problem as I'm already using polling there. The embedded http server we were using does use the select method and associated methods / macros. Since I generate > 1024 socket descriptors through my sockets in another section, this makes the socket descriptor for the incoming http connections exceed 1024 thus select causes a segmentation fault. Looking around, it seems most other embeddable http servers end up using FD_SET in their source code, so I'm starting to console myself to having to fix the server by switching it over to epolling.

MrMoo
Sep 14, 2000

HFX posted:

It is a defined limit under Linux.

You're not getting it, simply recompile you application with -DFD_SETSIZE=8192 and you will be good to go. This is a known issue with the select() API on any platform.

man 3C select posted:

The default value for FD_SETSIZE (currently 1024) is larger than the
default limit on the number of open files. To accommodate 32-bit appli-
cations that wish to use a larger number of open files with select(),
it is possible to increase this size at compile time by providing a
larger definition of FD_SETSIZE before the inclusion of any system-sup-
plied header. The maximum supported size for FD_SETSIZE is 65536. The
default value is already 65536 for 64-bit applications.

MrMoo fucked around with this message at 09:39 on Apr 1, 2011

HFX
Nov 29, 2004

MrMoo posted:

You're not getting it, simply recompile you application with -DFD_SETSIZE=8192 and you will be good to go. This is a known issue with the select() API on any platform.

No luck with that on Centos 5.5 x32

MrMoo
Sep 14, 2000

HFX posted:

No luck with that on Centos 5.5 x32

Ahh, Linux. Try __FD_SETSIZE instead, on Solaris FD_SETSIZE works fine as I have it in production in a few banks.

http://www.issociate.de/board/post/504324/FD_SETSIZE_with_large_

MrMoo fucked around with this message at 04:24 on Apr 2, 2011

mobby_6kl
Aug 9, 2009

by Fluffdaddy
Looks like I'm going to need some help guys. I wrote two programs for the "request tiny app" thread as an excuse to learn C and it's been going fine ("hello world" to DLLs, WinApi and basic GUI in one evening) but I ran into some problems. This is as much of WinApi as C, but I don't think there's a separate Windows programming thread.

1. I'm replacing double spaces keyboard input with a period. I set up a global WH_KEYBOARD with a callback's function body like so:
code:
LRESULT CALLBACK KeyHookCallback(int code, WPARAM wParam, LPARAM lParam)
{
	if(!(lParam & 0x80000000)) {
time_t t;
time(&t);

if ((wParam == VK_SPACE) && (last_key == VK_SPACE) &&  (t - last_time < 3)) {
	//send the backspace down and up, twice
	keybd_event(VK_BACK,0,0,0);
	keybd_event(VK_BACK,0,KEYEVENTF_KEYUP,0);
	keybd_event(VK_BACK,0,0,0);
	keybd_event(VK_BACK,0,KEYEVENTF_KEYUP,0);
	//send the period
	keybd_event(VK_OEM_PERIOD,0,0,0);
	keybd_event(VK_OEM_PERIOD,0,KEYEVENTF_KEYUP,0);
	last_key = 0;
} else {
	last_key = wParam;
	last_time = t;
}
}
return CallNextHookEx(my_hook, code, wParam, lParam);
This worked perfectly fine until the requester asked to add a space after the period. I added another keybd_event for the space down and up, but then the the whole thing goes into a loop, and I don't understand why. If my keybd_events trigger the callback function, by the time I send the space, last_key should be the period and so it shouldn't enter the if block. I tried to manually set last_key to 0 before and/or after sending the space with no results. Also, bizarrely it doesn't enter the loop when testing in Notepad, but it does in UltraEdit and Word completely freaks out.

2. Resetting the display resolution. I can set my display resolution to any supported combination smaller than my native resolution (1920x1080). If my current resolution is below that and I try to set it to 1920x1080, ChangeDisplaySettings returns DISP_CHANGE_BADMODE (display mode not supported). However, if the current resolution is already 1920x1080, it successfully changes it, pointlessly. Here's the relevant part of main():
code:
DEVMODE display_data;
display_data.dmSize = sizeof(DEVMODE);
display_data.dmDriverExtra = 0;

if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &display_data)) {
	display_data.dmPelsWidth = 1920;
	display_data.dmPelsHeight = 1080;
	display_data.dmDisplayFrequency = 60;

	switch (ChangeDisplaySettings(&display_data, 0)) {
		case DISP_CHANGE_BADMODE:
			printf("The graphics mode is not supported. Supported modes are:\n");
			enum_modes();
			break;
                [more cases here]
	}
}


enum_modes just lists the supported modes, where 1920x1080@60 is listed. Any ideas on what I'm doing wrong here?

nielsm
Jun 1, 2009



mobby_6kl posted:

2. Resetting the display resolution. I can set my display resolution to any supported combination smaller than my native resolution (1920x1080). If my current resolution is below that and I try to set it to 1920x1080, ChangeDisplaySettings returns DISP_CHANGE_BADMODE (display mode not supported). However, if the current resolution is already 1920x1080, it successfully changes it, pointlessly. Here's the relevant part of main():
code:
DEVMODE display_data;
display_data.dmSize = sizeof(DEVMODE);
display_data.dmDriverExtra = 0;

if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &display_data)) {
	display_data.dmPelsWidth = 1920;
	display_data.dmPelsHeight = 1080;
	display_data.dmDisplayFrequency = 60;

	switch (ChangeDisplaySettings(&display_data, 0)) {
		case DISP_CHANGE_BADMODE:
			printf("The graphics mode is not supported. Supported modes are:\n");
			enum_modes();
			break;
                [more cases here]
	}
}


enum_modes just lists the supported modes, where 1920x1080@60 is listed. Any ideas on what I'm doing wrong here?

You should probably make sure you zero out the entire DEVMODE structure. The easy way:
code:
DEVMODE display_data = {0};
Give an incomplete initialiser list. I customarily provide the first element as zero, but if the first element is a struct size field you could also provide the size there directly. When you provide an incomplete initialiser list, the remaining part not specified will be filled with zero bytes. Effectively, you just zeroed the entire structure. If you don't provide the initialiser, the structure may be filled with junk data.

Edit: Another thing you're missing:

"DEVMODE posted:

dmFields
Specifies whether certain members of the DEVMODE structure have been initialized. If a member is initialized, its corresponding bit is set, otherwise the bit is clear. A driver supports only those DEVMODE members that are appropriate for the printer or display technology.
You need to fill that.

nielsm fucked around with this message at 13:43 on Apr 2, 2011

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe

mobby_6kl posted:

This worked perfectly fine until the requester asked to add a space after the period. I added another keybd_event for the space down and up, but then the the whole thing goes into a loop, and I don't understand why. If my keybd_events trigger the callback function, by the time I send the space, last_key should be the period and so it shouldn't enter the if block. I tried to manually set last_key to 0 before and/or after sending the space with no results. Also, bizarrely it doesn't enter the loop when testing in Notepad, but it does in UltraEdit and Word completely freaks out.

The only thing I can see that you're doing wrong, is that you're not checking the value of code(see the documentation here). If code is negative your function should skip straight to return CallNextHookEx without doing any processing. It's also possible that code is HC_NOREMOVE meaning the message hasn't been popped from the queue and might be processed again (which may well explain your problem).

mobby_6kl
Aug 9, 2009

by Fluffdaddy
Wow, thanks a lot guys. In both cases that was it.

nielsm posted:

[...]
Edit: Another thing you're missing:
[dm_Fields]
You need to fill that.

Yep, although dm_Fields gets filled (with something), the following line made everything work properly:

code:
display_data.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
display_data was indeed filled by junk initially, but I thought it would be overwritten by the EnumDisplaySettings call. Turns out that's not the case, I stepped through the code and some of the fields remained junk unless I zeroed out the structure as you suggest. Good catch, I'll keep this in mind from now on.

Gerblyn posted:

The only thing I can see that you're doing wrong, is that you're not checking the value of code(see the documentation here). If code is negative your function should skip straight to return CallNextHookEx without doing any processing. It's also possible that code is HC_NOREMOVE meaning the message hasn't been popped from the queue and might be processed again (which may well explain your problem).

Checking that code != HC_NOREMOVE fixed my problem, I just didn't make the connection based on the function documentation. Adding code >= 0 didn't have any effect, but that's obviously the correct thing to do as well. Thanks again both.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Okay, Boost is awesome and very useful, but I cannot stand how fractured the header files are.
code:
; cat ow.cpp 
#include <boost/range/algorithm/for_each.hpp>
; clang++ -I/opt/local/include -MM ow.cpp | wc -l
     188
; cat ow2.cpp 
#include <boost/range/algorithm.hpp>
; clang++ -I/opt/local/include -MM ow2.cpp | wc -l
     331
That is a lot of files to open for every file that just doesn't want to type c->begin(), c->end().

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Mustach posted:

That is a lot of files to open for every file that just doesn't want to type c->begin(), c->end().
Using more of the template libraries got me to realize the value of precompiled headers which I'd never cared for before.
(Which in turn got me to stop using my 15-years-old laptop as the test server for my game, because I didn't feel like upgrading gcc to a version that supports precompiled headers.)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Not a question really, more of a grumbling complaint - why the hell doesn't C/C++ have some sort of precompiler directive for raw data, something like #datainclude(pFileContents,FileLength,"file.dat")

which would enumerate out to
code:
const char *pFileContents[]="(the contents of the file escaped and encoded as necessary)";
const size_t FileLength=(the length of the file)
I'm certain I'm not the only person who has ever wanted to do this. You used to be able to do it in Assembly language back in the day, in the "data" section.

Sure you can write a precompile script that turns your datafile into code like this and make a horrible mess of your makefile/project getting it to work at the right time and be included usefully, but as a thing I know is desirable more than once, it seems like a feature that would have been added to compiler spec at some point.

Runtime loading isn't cool if you want some raw data included as part of a library.

pseudorandom name
May 6, 2007

code:
.section .rodata
.global someData
.type someData, @object
someData:
.incbin "somefile.dat"
.size someData, .-someData
.LsomeDataEnd:

.align 4
.global someDataLength
.type someDataLength, @object
someDataLength:
.int .LsomeDataEnd-someData
.size someDatLength, .-someDataLength

pseudorandom name fucked around with this message at 07:01 on Apr 7, 2011

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Nice idea, but not so helpful in a Windows environment - it appears MASM doesn't have an incbin either!

But that's okay, because you can always stick your raw data into resources, which is great for every situation except A. it's not as convenient as just using a pointer is it you Microsoft bastards, and B. you can't have resources in a .lib, only in a .dll

Which brings me back to my original complaint, a standard compiler way of doing this would be most welcome!

I've just dug around and found a "bin2coff" tool that will just about do the job for me, but only because the file I wanted in there is a text file - it doesn't give access to length, but it appears to append a zero so with a string strlen will work.

pseudorandom name
May 6, 2007

roomforthetuna posted:

Nice idea, but not so helpful in a Windows environment - it appears MASM doesn't have an incbin either!

YASM does.

chucky.z
Mar 28, 2011
When referencing a linked list that is created inside of another struct and editing that linked list inside of a function, can I leave the function void or do I need to return something? Let me just copy/paste my code so it's easier to understand.

code:
//list of buddies
typedef struct buddyList 
{
	int buddy;
	struct buddyList *next;
} buddies;


//node in the binary search tree
typedef struct tree_node 
{
	int id;
	char firstName[21];
	char lastName[21];
	int age;
	buddies *myBuddies;
	int numBuddies;
	struct tree_node *left;
	struct tree_node *right;
} BSTnode;
I'm editing the "myBuddies" in a function, but I'm not really sure what to return, or if I should leave the function void.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
If a function is designed to be run purely for its side-effects, and it doesn't have anything useful to tell its caller, then it's fine for it to return void.

chucky.z
Mar 28, 2011

rjmccall posted:

If a function is designed to be run purely for its side-effects, and it doesn't have anything useful to tell its caller, then it's fine for it to return void.

The function in question is adding a "buddy" to the myBuddies linked list contained within the BSTnode struct (It's inserting the id of a BSTnode into the buddy portion of the myBuddies). This is where I'm confused, should I be returning a member of "buddies," "BSTnode," or simply a null value? (e.g. "return;")

The function itself takes in two members of BSTnode that are looked up through a search function.

chucky.z fucked around with this message at 05:55 on Apr 6, 2011

nielsm
Jun 1, 2009



It doesn't sound like there is anything meaningful you could return, apart from possibly a success/failure code. (E.g. you might discover that those two persons actually exist in two separate trees, and that might be an error condition.)

I don't know exactly what your function is doing, but I'll assume that it adds the ID of the other person to each of the passed person objects, allocating a new buddyList struct for each, adding it somewhere in the buddy list of each tree node.

So what could you return?
- A pointer to a buddyList struct? Which one, you allocated two of them.
- A pointer to a tree_node struct? But those were passed in as parameters already, so that isn't much use either. Also, again which of the two would you return?
- A new count of buddies? For which of the persons? You could just as well read it out of the tree_node struct you already hold a pointer to.
- An error code? If the operation can fail in any way, this may be a good choice.
- Nothing, i.e. void? Why not, if you can't fail, just perform the operation. Anything the caller wants to know, they can extract from the pointers they already held before calling your function.

Edit: If your function only creates a one-way relationship (i.e. makes person A a buddy of person B, but not person B a buddy of person A) then the first three points in my list above could make sense. But even here, the caller could just extract the same information from the tree_node struct after performing the call.

nielsm fucked around with this message at 06:38 on Apr 6, 2011

rufius
Feb 27, 2011

Clear alcohols are for rich women on diets.
I've been working with C++ for a while now and have a good grasp on just about every area *except* templates. I'm used to working in a lot of Windows-oriented C++, mostly because I work a lot with COM and related technologies. Now I want to learn more "idiomatic" C++ as opposed to what I like to call "C+". My shop is pretty much no-STL because we rely heavily on COM and don't use exceptions.

I own a copy of Alexandrescu's (sp?) Modern C++ Design and paged through it, no thorough reading yet. I'm also considering purchasing Vandervoorde's "C++ Templates: The Complete Guide" and/or Josuttis's The C++ Standard Library.

My primary questions are:
1) Will buying Vandervoorde's book (mentioned above) suffice for me figuring out the STL style of programming? I want to learn more about using the STL (and/or Boost). I don't need a whole lot of hand-holding, more like principles for understanding why X is done a particular way in the STL.

2) Is Vandervoorde's the best reference for templates?

3) Are there any other books besides the three I mentioned that are worth looking at regarding my two weak areas (STL & Templates)?

rufius fucked around with this message at 14:39 on Apr 7, 2011

Dicky B
Mar 23, 2004

Effective STL.

Vandervoorde's is great but it's not about the STL.

Adbot
ADBOT LOVES YOU

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

can someone take a look at my code and see why the vector it builds is size+1 larger than the list it's reading?
code:
void city_c::read_config( const char *fname )
{
    ifstream in(fname);

    stringstream ss;
    char inputline[256];
    while(in.getline(inputline, 256)) {
        ss.str(inputline);
        if (ss.peek() != '#')  { // comments in citylist.enc start with a # and should be ignored
            cityinfo_c new_city;
            ss  >> new_city.name
                >> new_city.mylocale
                >> new_city.mytype
                >> new_city.latitude
                >> new_city.longitude
                >> new_city.population;
            city_list.push_back(new_city);
        }
        ss.clear();
    }
    in.close();
}
Would really appreciate any help as the .size()=N+1 return is messing up other functions.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply