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
Brecht
Nov 7, 2009

Haywood Japwnme posted:

Paniolo suggested, a few posts up, that I should use a trie. Anyone have any suggestions for a good C++ implementation or library for trie? Preferably one that compiles in GNU.
gcc ships with a GNU implementation of a trie.

http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds

Adbot
ADBOT LOVES YOU

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Brecht posted:

gcc ships with a GNU implementation of a trie.

http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds

Thanks, I saw that one and am trying out.

Another question, what's the MySQL C++ connector of choice around here? I was looking at libmysqlcppconn but the documentation is a little iffy.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
Hopefully someone can help me with this. I'm writing a threaded application to mimic a very very simple course management system where each thread is a different user. So I complete the basic implementation my teacher wanted, and start adding extra features since that's 10 points of the grade. The current thread I'm adding is saving the courses you add between uses.

So, the feature got implemented and worked great, except I realized I put the code where I split up into the threads which could cause an error during run-time, so I put a "initialize user" type thing in the main function to do this for me in a sequential way. Anyway, after changing it up, it just doesn't seem to work properly, so I check my map and stuff, it seems right, so I check to make sure things are being read in properly. Well, seems like something has gone horribly wrong:
code:
	ifstream courseFile ("courseFile.txt");
	if(courseFile.is_open())
	{
		//string courseTmp;
		//Course tmp;
		//SavedUsers tmpUser;
		//stringstream oss,pss;
		string line;
		while(courseFile.good())
		{
			getline(courseFile,line);
			cout << line << " " << line.length() << endl;
		}
		courseFile.close();
	}

	return 0;
gives me:
code:
 14HY 101 5 0
 6er1
 6er2
 14SC 101 5 0
 0
out of:

courseFile.txt posted:

* PHY 101 5 0
user1
user2
* CSC 101 5 0

Uh, what? :psyduck:

Quebec Bagnet
Apr 28, 2009

mess with the honk
you get the bonk
Lipstick Apathy
Make sure your reading code is only running on one thread.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
This is before it creates the threads. If more than one things is running this ever, then C++ is then just actively trying to sabotage me.

The code before this is includes, initialization of global shared variables, and an error check on args.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
What does getline contain?

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

Suspicious Dish posted:

What does getline contain?
What? Does it contain anything since it reads in the stream, reads till it hits the delim character, and saves what it read to the string second param. Does it save/contain anything?


edit:
so seperating them out into separate prints "fixes" it so that it displays properly. Which confuses me, since then I can't help wonder if it's affecting my map function which I use on the input:
code:
			if(line[0] == '*')
			{
				courseTmp = line.substr(2,3);
				tmp.setDetails(courseTmp,atoi(line.substr(6,3).c_str()));
				tmp.setSize(atoi(line.substr(10,((line.size()-1)-(line.size()-3))).c_str()));
				if(line.substr((line.size()-1),1).compare("1") == 0)
				{
					tmp.cancelCourse();
				}

				if(courseTmp.compare("PHY") == 0)
				{
					PHY.push_back(tmp);
				}
				else if(courseTmp.compare("CSC") == 0)
				{
					CSC.push_back(tmp);
				}
				else if(courseTmp.compare("MAT") == 0)
				{
					CSC.push_back(tmp);
				}
			}
			else if(line.size() > 0)
			{
				pss << line;
				cout << pss.str() << endl;
				check[pss.str()] = pss.str();
				cout << "Added to map" << endl;
			}
and then running:
code:
	map<string,string>::iterator it;
	for ( it=check.begin() ; it != check.end(); it++ )
		cout << (*it).first << " => " << (*it).second << endl;
Gives me:
code:
string => test
 => user1
user2ser1
(string => test is just a test to see if strings could be key elements since something seems to be going wrong and I just have no idea and it's just coming down to C++ :argh:)

Anyway, that leads me to believe that my map has one good element, one element that doesn't have a key, and then an element that uh...I don't know, ignores "=>" I guess?

Is there some fundamental part of strings that I've failed to learn in my teachings (ie. strings are insane and do whatever the gently caress they want) as this is frustrating as all hell as the project is supposed to be "done".

Master_Odin fucked around with this message at 07:06 on Apr 24, 2012

brosmike
Jun 26, 2009
It looks like you're getting input from a text file with windows-style line endings (they end in \r\n, where '\r' is a special control character that means "go back to the beginning of the current line" and '\n' is a newline), but your program is trying to parse the file as if it were using unix-style line endings (expecting just \n, no \r).

In your first example, this would lead you to parse the line "* PHY 101 5 0" as "* PHY 101 5 0\r", so your code would be doing this:

code:
cout << "* PHY 101 5 0\r" << " " << 14 << endl
..which prints "* PHY 101 5 0", goes back to the beginning of the line, and prints " 14", giving you " 14HY 101 5 0" like you saw. The rest of the errors you're seeing look similar.

C++ implementations are expected to deal appropriately with the line endings for the platform your program is compiled for, so this sort of problem most typically means that your professor created courseFile.txt on a Windows system and you're developing on a Linux/Mac system. Your options to fix it include:

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

brosmike posted:

It looks like you're getting input from a text file with windows-style line endings (they end in \r\n, where '\r' is a special control character that means "go back to the beginning of the current line" and '\n' is a newline), but your program is trying to parse the file as if it were using unix-style line endings (expecting just \n, no \r).

In your first example, this would lead you to parse the line "* PHY 101 5 0" as "* PHY 101 5 0\r", so your code would be doing this:

code:
cout << "* PHY 101 5 0\r" << " " << 14 << endl
..which prints "* PHY 101 5 0", goes back to the beginning of the line, and prints " 14", giving you " 14HY 101 5 0" like you saw. The rest of the errors you're seeing look similar.

C++ implementations are expected to deal appropriately with the line endings for the platform your program is compiled for, so this sort of problem most typically means that your professor created courseFile.txt on a Windows system and you're developing on a Linux/Mac system. Your options to fix it include:


Any idea why intro to C++ classes make people gently caress with iostream? It's not like you can ever use it in a real project because it sucks so much rear end, and it's actually completely not intuitive how it works at all.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

brosmike posted:

answer
Thanks for this. Ended up just recreating the affect files in my Linux VM rather than implement any fancy getline alternatives since it is a school project and it only needs to run on Linux (since pthreads) and viola, strings are acting normally, my mapped array is actually mapped properly and at least now I'm just getting the occasional seg fault error as I'm forced to implement more pointers into the project.

hieronymus posted:

Any idea why intro to C++ classes make people gently caress with iostream? It's not like you can ever use it in a real project because it sucks so much rear end, and it's actually completely not intuitive how it works at all.
My CSC department didn't bother imparting the fact that importing std namespace into all headers is bad practice either. I feel like I'm teaching myself a lot of the actual usage of the language through project assignments and my need to do things in some neat way then from class.

On this project, I swear, my teacher probably wanted us to roll our own semaphore implementation, rather than use the handy semaphore.h library, which she didn't mention existed at all ever.

Master_Odin fucked around with this message at 18:46 on Apr 24, 2012

shrughes
Oct 11, 2008

(call/cc call/cc)

Master_Odin posted:

On this project, I swear, my teacher probably wanted us to roll our own semaphore implementation, rather than use the handy semaphore.h library, which she didn't mention existed at all ever.

Uh... how would you recommend learning how to implement concurrency primitives?

brosmike
Jun 26, 2009

Master_Odin posted:

My CSC department didn't bother imparting the fact that importing std namespace into all headers is bad practice either. I feel like I'm teaching myself a lot of the actual usage of the language through project assignments and my need to do things in some neat way then from class.

I certainly hope your department is encouraging its students to seek out information like this (pragmatically useful but conceptually uninteresting) on their own. Assuming you plan to make a career out of this, you'll be spending a LOT of next few decades teaching yourself how to solve exactly these sorts of problems, and most people start out pretty bad at doing so and needing all the practice they can get.

Most software development jobs you would actually want to have will expect you to be able to pick up a basic working knowledge of the "actual usage of the language" for whatever language you need in pretty short order without much in the way of formal classes (obviously mastery of a language is expected to take much longer, but is again done through mostly practice)

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

shrughes posted:

Uh... how would you recommend learning how to implement concurrency primitives?
Through lectures/small lab, not a major programming assignment? I agree it's important to know the primitives and all that, but no real point re-inventing the wheel if you really don't have to.

I wrote a small PHP/mySQL database driver, doesn't mean if I ever got a project, I'd use that over PDO. Clearly I'm ill suited for academia, and probably wrong about this, so I won't clutter up the thread with my ill advised stances on it.

brosmike posted:

I certainly hope your department is encouraging its students to seek out information like this (pragmatically useful but conceptually uninteresting) on their own. Assuming you plan to make a career out of this, you'll be spending a LOT of next few decades teaching yourself how to solve exactly these sorts of problems, and most people start out pretty bad at doing so and needing all the practice they can get.

Most software development jobs you would actually want to have will expect you to be able to pick up a basic working knowledge of the "actual usage of the language" for whatever language you need in pretty short order without much in the way of formal classes (obviously mastery of a language is expected to take much longer, but is again done through mostly practice)
While I get having to read stuff (which I've done for design patterns, the various STL containers, miscellaneous facts about C++ like not using std namespace.), having to read about stuff like design patterns and proper coding etiquette (such as namespace stuff) seems like something that could be mentioned when teaching C++. But then again, potential bad teachers and all that. If nothing else, school has gotten me to become pretty effective about googling about my problem or potential solution. I'm fine teaching myself as its how I know all I do about web programming and the like as the classes offered at my school an equivalent of just giving the college money and then leaving.

Master_Odin fucked around with this message at 01:11 on Apr 25, 2012

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm getting my rear end beat by Boost's upgrade locks while trying to use them with shared locks for read/write locking.

The common method you'll find online for using those locks is:
1. For reading, used a shared lock
2. For reading and potentially writing, start with an upgradable lock and get a unique lock at the point of writing.

I have found a lot of people just as confused as me, who then saw in the documentation something to the effect that only one thread can have the upgradable lock at a time. They'd post about it and everybody would just be standing around, scratching their heads.

This isn't Boost, but I suppose it describes the behavior:
http://home.roadrunner.com/~hinnant/mutexes/locking.html#Upgrade

If it's the same mechanism, when multiple shared threads could potentially want to write, they want to wait for all other shared threads to exit first. The fight happens at the upgrade, not at the exclusive portion. At this point, I wonder--what's the point of upgrading to a unique lock when the upgradable lock is already demanding exclusivity?

I'm wondering then what I should be doing for my read/write section. It looks like I need to unlock the shared lock before acquiring an exclusive lock--upgradable or unique or whatever.

Looking at my code further, I like to lock on STL lists, and I was trying to get a write lock when it came time to erase something from the list. It looks like I need to stop doing that since I'm going to invalidate anybody else iterating through the list at the same time.

poverty goat
Feb 15, 2004



What's the difference between ++thing and thing++?

I have a loop where I want to start iterating at the second item:
code:
for(tokenizer<>::iterator i = ++tok.begin(); i != tok.end(); i++)
{
	somevalue = atoi(i->c_str());
	cout << somevalue << " ";
	themap.insert(std::make_pair(currentkey,somevalue));
}
++tok.begin() works correctly, but tok.begin()++ begins at the first item.

nielsm
Jun 1, 2009



gggiiimmmppp posted:

What's the difference between ++thing and thing++?

Pre-increment versus post-increment.
++foo evaluates foo, increments it by one, stores the new value back to foo, then returns the incremented value.
foo++ evaluates foo, increments it by one, stores the new value back to foo, then returns the original value.

Note that the actual order of the two last parts, "store back" and "return value" is not well-defined. The actual store-back might happen before or after the rest of the statement the increment operator is part of finishes executing.

In some cases, pre-increment is faster than post-increment, but never the other way around.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Rocko Bonaparte posted:

If it's the same mechanism, when multiple shared threads could potentially want to write, they want to wait for all other shared threads to exit first. The fight happens at the upgrade, not at the exclusive portion. At this point, I wonder--what's the point of upgrading to a unique lock when the upgradable lock is already demanding exclusivity?

The upgradable lock is not exclusive with shared lockers, so you get better concurrency for that time. The analysis you linked discusses why you can't have a shared upgradeable lock — the API implies that the shared lock is continuously held, so if you ever had two simultaneous upgraders, their upgrade operations would necessarily deadlock. What you probably want is to drop the shared lock and then pick up the exclusive lock; by forcing you to do this explicitly, the API makes it clear that you can't rely on any information you gained during the read phase.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

rjmccall posted:

The upgradable lock is not exclusive with shared lockers, so you get better concurrency for that time. The analysis you linked discusses why you can't have a shared upgradeable lock — the API implies that the shared lock is continuously held, so if you ever had two simultaneous upgraders, their upgrade operations would necessarily deadlock. What you probably want is to drop the shared lock and then pick up the exclusive lock; by forcing you to do this explicitly, the API makes it clear that you can't rely on any information you gained during the read phase.
Yeah I had two upgrade locks deadlocking. It was a real treat not knowing what the problem was and trying to figure out why those two were stuck.

Now that I see how this is working, I'm wondering when one would ever actually want an upgrade lock instead of a unique lock.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
A writer which spends a relatively small amount of time actually writing, but which can't give up the shared lock without invalidating itself. For example, a periodic task to strip dead records from a "database" might queue up its actual deletion work to minimize the amount of time it's forced to exclude readers, but it might not have been written to be safe against intervening writes. Or you might be inserting a record, but you need to link it against a bunch of other records, and finding them is an expensive operation.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

rjmccall posted:

A writer which spends a relatively small amount of time actually writing, but which can't give up the shared lock without invalidating itself. For example, a periodic task to strip dead records from a "database" might queue up its actual deletion work to minimize the amount of time it's forced to exclude readers, but it might not have been written to be safe against intervening writes. Or you might be inserting a record, but you need to link it against a bunch of other records, and finding them is an expensive operation.

That's kind of funny because that's in the spirit of what I was trying to do, although I think the activity was too long and regular. I was going through a list of callback listeners, and triggering their event handler if the event I needed to transmit matched what they were listening to. While doing that, I was also checking if there were deleted listeners. If so, I removed them from the list right then and there. So I figured I needed an upgradable lock.

I know that using a shared lock for the reads would be dumb because I'd invalidate the list for somebody else while they're in it. The thread that did the cleanup would have the right iterator, but anybody that was inside at the time would have gotten their rear end beat.

When I switched it to an upgrade lock, I got deadlocked on the lock when two threads ended up blocking on it. Knowing a little more now about what's going on, I need to check back if somebody else didn't have a shared lock for that block. I assume that would do it. However, I've heard a lot online about two thread deadlocking each other on an upgrade lock. It just doesn't sound right since in my head it sounds like this:
1. Thread #1 has a shared lock on the mutex.
2. Thread #2 wants an upgrade lock on the mutex and blocks.
3. Thread #3 comes along and also wants an upgrade lock on the mutex.
4. Thread #1 releases the shared lock. But somehow #2 and #3 are deadlocked now.

Anyways, at some point I started using shared pointers to the callback receivers, so there's no way for them to slip out undetected anymore. So I can effectively scrub that code away and stick to shared locks for most everything. Still I want to know how the heck to actually use these things right.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Rocko Bonaparte posted:

That's kind of funny because that's in the spirit of what I was trying to do, although I think the activity was too long and regular. I was going through a list of callback listeners, and triggering their event handler if the event I needed to transmit matched what they were listening to. While doing that, I was also checking if there were deleted listeners. If so, I removed them from the list right then and there. So I figured I needed an upgradable lock.

It's probably better to remember that you found something and then go back over it with an exclusive lock.

I can't see why someone else having a shared lock would cause a deadlock for you. In your hypothetical:

Rocko Bonaparte posted:

1. Thread #1 has a shared lock on the mutex.
2. Thread #2 wants an upgrade lock on the mutex and blocks.
3. Thread #3 comes along and also wants an upgrade lock on the mutex.
4. Thread #1 releases the shared lock. But somehow #2 and #3 are deadlocked now.
Only one of thread 2 or 3 should actually be able to succeed at grabbing an upgradeable lock; the other should block until the first unlocks (or downgrades to a normal shared lock).

Note that you can get a single-thread deadlock if one thread has a shared lock *and* an upgrade lock and then tries to upgrade.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
I believe what's happening is that the threads are holding shared locks while trying to grab the upgrade lock. One thread is fine, because it can release the shared lock before it tries to upgrade to an exclusive lock, but a second thread still waiting on the upgrade lock will cause the whole thing to deadlock.

The way I would think to manage this is by not blocking while waiting for the upgrade lock - instead if you don't get it, just carry on dispatching events and let the thread with the upgrade lock handle deleting stuff. Unfortunately, it seems boost doesn't actually have a try_lock_upgrade() and so the only way to acquire an upgrade lock is to block on it.

FamDav
Mar 29, 2008
Short question:

If I can "delete this", why can't I assign to this?" i.e. "delete this; this = new Item()".

Long question:

I've implemented double dispatch with a visitor pattern on an expression tree that contains operators, integers,and identifiers. What I want to do is create a visitor that will simplify the tree as much as possible. My problem is that I need some way of changing a node to a different node while I'm looking at. Otherwise, I'm having to thread a new node back through the visitor pattern to the parent node.

nielsm
Jun 1, 2009



FamDav posted:

Short question:

If I can "delete this", why can't I assign to this?" i.e. "delete this; this = new Item()".

The "this" pointer kind-of belongs to the caller, you can't really (directly) change what the caller has.
You can assign to *this however. That will call the appropriate operator= for the types.

It sounds like you're trying to have the tree nodes themselves know and implement the algorithm to simplify the tree however. I would suggest instead either implementing the algorithm in the tree (and make "a tree" a container of nodes, not just the top node) or as a separate utility function. In both cases you would eliminate the need to "change the identity of this".

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

FamDav posted:

Short question:

If I can "delete this", why can't I assign to this?" i.e. "delete this; this = new Item()".

this does not name a variable; it's just a keyword which happens to evaluate to a particular pointer value. Since it's a pointer value, you can use with delete, although in many cases that won't work dynamically. Since it's not a variable, you can't assign to it.

FamDav posted:

I've implemented double dispatch with a visitor pattern on an expression tree that contains operators, integers,and identifiers. What I want to do is create a visitor that will simplify the tree as much as possible. My problem is that I need some way of changing a node to a different node while I'm looking at. Otherwise, I'm having to thread a new node back through the visitor pattern to the parent node.

Well, you can't change the identity of a node like this; modifying this would not change all references to it. You can overwrite the memory that's used for an object, but it requires all your nodes to have the same size, and it is incredibly ugly and bug-prone and technically undefined behavior so I'm not going to go into it. :)

There are basically three ways to thread results out of a visitor pattern in C++.

The first way is to compute the result directly in the visitor object. This means you'll need to pass copies of the visitor to sub-nodes in many cases, but that's doable.

The second way is to template everything; of course, that means that dispatch can't use virtual dispatch, so you'd need some other way to distinguish nodes and cast down. For an AST with a fixed number of node kinds, this is not unreasonable; it may also mean that you can kill vtables completely, which can help space usage if you're making a ton of these. Macro metaprogramming helps a lot. You end up with really ugly files like clang's StmtVisitor but a programming model that's actually not that terrible.

The third way is to propagate out some really general type, like void*, and just have the visitor know how to interpret that.

rjmccall fucked around with this message at 19:00 on Apr 26, 2012

CPFinnit
Jun 5, 2008
This isn't quite homework, just brushing up on stuff before my intro C++ class starts in a few weeks.

The exercise calls for receiving a decimal number input and outputting that number rounded to the nearest integer. This seems to work, but I'm guessing it is kind of inelegant. Might there be a more direct way?

code:
#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    double inputNumber;
    double remainderNumber;
    int roundedNumber;
    int finalNumber;
    
    //Prompts for and recievies input from user
    cout << "Please input a decimal number and press enter." << endl;
    cin >> inputNumber;
    
    //Drops the decimal from the input number
    roundedNumber = static_cast<int>(inputNumber);
    
    //Seperates the numbers following the decimal 
    remainderNumber = inputNumber - roundedNumber;
    
    //Tests the decimal if the value is less 0.5 returns the lower number
    //If the decimal is greater than 0.5 returns the next highest integer 
    if (remainderNumber < 0.5)
    {
                  finalNumber = roundedNumber;
                  }
                  else
                  {
                      finalNumber = roundedNumber + 1;
    }
    //Outputs the final rounded number
    cout << finalNumber << endl;
    
    
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

jhunter46 posted:

This isn't quite homework, just brushing up on stuff before my intro C++ class starts in a few weeks.

The exercise calls for receiving a decimal number input and outputting that number rounded to the nearest integer. This seems to work, but I'm guessing it is kind of inelegant. Might there be a more direct way?

[code]

Are you allowed to use ceil() and float()?

seiken
Feb 7, 2005

hah ha ha
Arguably your code is very clear and nicely-commented I guess but cout << int(0.5 + inputNumber) << endl; does it in one line and is idiomatic enough that I don't see any reason not to use it.

seiken fucked around with this message at 01:22 on Apr 27, 2012

mjau
Aug 8, 2008

seiken posted:

Arguably your code is very clear and nicely-commented I guess but cout << int(0.5 + inputNumber) << endl; does it in one line and is idiomatic enough that I don't see any reason not to use it.

Better to use floor(inputNumber + 0.5), and cast that to int afterwards if required. Casting to int rounds towards zero (usually; I think this is actually implementation defined), but you don't want that. -1.4 would round to 0. floor rounds towards negative infinity, which works great.

CPFinnit
Jun 5, 2008
I hadn't seen floor and ceil yet. Thanks.

Fuck them
Jan 21, 2011

and their bullshit
:yotj:
I undertook figuring out how to make a linked list, in C :ohdear: and more correctly how to make functions to manipulate it on my own, not as part of a class. I don't even get to see data structures until the fall at the earliest, but I still want to get my hands on these concepts.

http://pastebin.com/6tkkq1sn <- too big to post the entire thing, so here's a link.

It compiles and runs without any problems despite me throwing pointers around and mallocing things, though for whatever reason it only manages to add one word to the linked list. If I add another, it just doesn't. As far as I know makeNode (line 42) works fine, so the problem must be in addword (line 59), but I for the life of me can't spot my mistake.

I've already asked a few people in industry, and was told summarily to "stop doing this poo poo in C," in favor of C++ or Java, and "no I can't find the bug either." Can anyone tell me what I'm doing wrong?

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!

2banks1swap.avi posted:

Can anyone tell me what I'm doing wrong?
code:
while( (strcmp(myP->word,myWord) != 0) && myP->next != root && quit == 0 ) 
// move down the line, check for matches, if you get to root, make a 
             new node and put that word in
The comment there should say "move down the line, check for matches, if you get to root stop going inside this loop including not adding the new node because that's inside this loop"

You should either move the "if the node hasn't been added add it now" bit to outside of that loop, or drop the "myP->next != root" from the loop's conditions since inside the loop you check for that and set 'quit' anyway.

You could also drop that whole 'quit' malarkey and just return from the function wherever you'd have set quit, since it means "don't do anything else in this function".

Edit: actually, what you're doing wrong is not learning to use the debugger, which could have shown you exactly where your code was going wrong pretty effortlessly. Line-stepping through code is the most useful tool of all, it's like a dry-run where you don't even have to think!

roomforthetuna fucked around with this message at 17:57 on Apr 29, 2012

That Turkey Story
Mar 30, 2003

2banks1swap.avi posted:

It compiles and runs without any problems despite me throwing pointers around and mallocing things, though for whatever reason it only manages to add one word to the linked list. If I add another, it just doesn't. As far as I know makeNode (line 42) works fine, so the problem must be in addword (line 59), but I for the life of me can't spot my mistake.

I'm just skimming through, but one thing immediately jumps out:

In makeNode, you never set temp->prev.

I only started to look at "addword" but it's way more complicated than it needs to be and has redundancy.

You're also never freeing your memory.

Fuck them
Jan 21, 2011

and their bullshit
:yotj:

roomforthetuna posted:

code:
while( (strcmp(myP->word,myWord) != 0) && myP->next != root && quit == 0 ) 
// move down the line, check for matches, if you get to root, make a 
             new node and put that word in
The comment there should say "move down the line, check for matches, if you get to root stop going inside this loop including not adding the new node because that's inside this loop"

You should either move the "if the node hasn't been added add it now" bit to outside of that loop, or drop the "myP->next != root" from the loop's conditions since inside the loop you check for that and set 'quit' anyway.

You could also drop that whole 'quit' malarkey and just return from the function wherever you'd have set quit, since it means "don't do anything else in this function".

Edit: actually, what you're doing wrong is not learning to use the debugger, which could have shown you exactly where your code was going wrong pretty effortlessly. Line-stepping through code is the most useful tool of all, it's like a dry-run where you don't even have to think!

I do need to get the codeblocks debugger working.

If the function is void, how do I return? Can I just pop "return;" as needed? I had a teacher insist that "only one return ever!" (in a given function) which is why you use these variables and &&and statements and such.

I guess school-gramming and pro-gramming are two different things.

That Turkey Story
Mar 30, 2003

2banks1swap.avi posted:

I had a teacher insist that "only one return ever!"

Don't listen to that teacher.

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!

2banks1swap.avi posted:

I do need to get the codeblocks debugger working.

If the function is void, how do I return? Can I just pop "return;" as needed? I had a teacher insist that "only one return ever!" (in a given function) which is why you use these variables and &&and statements and such.

I guess school-gramming and pro-gramming are two different things.
Yes, you can just "return;" as needed. It probably is a little bit technically nicer to only have one return, but if you're going to do that then it should be by the power of 'else' so that you never go near any of the other blocks, not via a "skip other things" bool which I think is much worse, and more error-prone, than just returning mid-function.

Fuck them
Jan 21, 2011

and their bullshit
:yotj:

roomforthetuna posted:

Yes, you can just "return;" as needed. It probably is a little bit technically nicer to only have one return, but if you're going to do that then it should be by the power of 'else' so that you never go near any of the other blocks, not via a "skip other things" bool which I think is much worse, and more error-prone, than just returning mid-function.

Got rid of my int quit, made a more readable loop in addword, ran through the debugger step by step, and I'm still absolutely confused.

I should add that I started this while running a fever yesterday and I'm still running a less high fever. Otherwise I Can't fathom how I made that big tangled mess called addword();. I also put the temp->prev = myP; into makeNode, thanks turkey story.

http://pastebin.com/j2P9FfFa here's my new and less bad code that still has bugs. The debugger had me walk through the part from 81 to 89, but I Can't see anything wrong with addword! :(

Edit: It even went through line by line in makeNode!

Fuck them fucked around with this message at 19:13 on Apr 29, 2012

Colonel Taint
Mar 14, 2004


check your printwords loop condition

vvvvv

Why not just

code:
void printwords(node *root)
{
    node* myP = root;

    do
    {
        printf("The word \"%s\" appeared %i times.\n", myP->word, myP->count);
        myP = myP->next;
    }
    while(myP != root);
}
Also, both versions will probably fail for an empty list

Colonel Taint fucked around with this message at 19:40 on Apr 29, 2012

Fuck them
Jan 21, 2011

and their bullshit
:yotj:

SintaxError posted:

check your printwords loop condition

Thank you very much! Now I have to figure out just how to make this work for my root+1 node list.

edit: It either only prints the root or does it for the root twice; it either just says "hurf" or "hurf" then "durf" then "hurf."

At least it's funny to watch this pop out.

edit v2:
code:
void printwords(node *root)
{
    int i = 0;
    node* myP = root;

    while ( 1 )
    {
        printf("The word \"%s\" appeared %i times.\n", myP->word, myP->count);
        myP = myP->next;
        if(myP == root) // hit me while walking my dog. buh. 
        {
            break;
        }

    }
}
Thank you everyone!

Fuck them fucked around with this message at 19:36 on Apr 29, 2012

Adbot
ADBOT LOVES YOU

etcetera08
Sep 11, 2008

What's a good C++ book for someone who's not a completely new programmer? I'm certainly not a good or even experienced programmer but I am having trouble finding a book in that middleground. I'm thinking Horstmann's C++ for Everyone might be a good one, as I like his Big Java quite a bit but I am not totally sure.

edit: just realized Big C++ exists too, so I'll probably check that out.

etcetera08 fucked around with this message at 20:43 on Apr 29, 2012

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