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
seiken
Feb 7, 2005

hah ha ha
Erasing from a map invalidates iterators pointing to the erased element. Helpfully (edit: assuming C++11, apparently), it also returns a new valid iterator to the next element. You need to do this:
code:
map<string, string> start_and_stops(map<string, string> &codon_map) {
	map<string, string> start_stops;
	for (auto it = codon_map.begin(); it != codon_map.end();) {
		if (it->second == "START" || it->second == "STOP") {
			start_stops[it->first] = it->second;
			it = codon_map.erase(it);
		}
		else {
			++it;
		}
	}
	return start_stops;
}
vvv that doesn't erase from the input map, though

seiken fucked around with this message at 02:22 on Oct 24, 2013

Adbot
ADBOT LOVES YOU

FamDav
Mar 29, 2008
alternatively, you could just write

code:
map<string, string> start_and_stops(map<string, string> &codon_map) {
	map<string, string> start_stops;
	copy_if( codon_map.begin(), codon_map.end(), inserter(start_stops, start_stops.begin()), 
		[] (const map<string, string>::value_type& x) {
			return x.first == "START || x.first == "STOP";
		});
	return start_stops;
}

raminasi
Jan 25, 2005

a last drink with no ice

Plorkyeran posted:

Coverity tells me that the following code results in an out-of-bounds array read:
code:
std::vector<std::string> vec;
vec.insert(vec.begin(), "");
Is it just being dumb, or is there some reason this would be unsafe other than a libc++ bug?

Does changing it to vec.end() shut Coverity up?

hooah
Feb 6, 2006
WTF?

seiken posted:

Erasing from a map invalidates iterators pointing to the erased element. Helpfully (edit: assuming C++11, apparently), it also returns a new valid iterator to the next element. You need to do this:


vvv that doesn't erase from the input map, though

Well, that runs (after changing the dots to ->), but it's just copying everything that's not START or STOP, rather than only copying those.

OddObserver
Apr 3, 2009

GrumpyDoctor posted:

Does changing it to vec.end() shut Coverity up?

Surely they're the same for an empty vector, considering what a standard
loop over range looks like?

raminasi
Jan 25, 2005

a last drink with no ice

OddObserver posted:

Surely they're the same for an empty vector, considering what a standard
loop over range looks like?

Well if the original behavior made sense the question wouldn't be here. I'm really just curious about what happens with Coverity.

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde
insert() at the beginning of an empty vector appears in the C++98 standard as a valid expression. Coverity would appear to be wrong.

FamDav
Mar 29, 2008

seiken posted:

vvv that doesn't erase from the input map, though

ok, then do this:

code:
map<string, string> start_and_stops(map<string, string> &codon_map) {
	map<string, string> start_stops, rest;
	auto pred = [] (const map<string, string>::value_type& x) { return x.second== "START || x.second == "STOP"; };

	partition_copy( codon_map.begin(), codon_map.end(), inserter(start_stops, start_stops.begin()), inserter(rest, rest.begin()), pred);
	swap(codon_map, rest);

	return start_stops;
}

FamDav fucked around with this message at 04:15 on Oct 24, 2013

hooah
Feb 6, 2006
WTF?
I just got clarification from the professor that we can add a parameter to functions that are given in the assignment, so I re-wrote the fill_codon function to fill both maps at once:
code:
void fill_codon(map<string, string> &codon_map, map<string, string> &start_stop, ifstream &in_file){
	string codon, protein;
	while (in_file >> codon >> protein){
		if (protein == "START" || protein == "STOP")
			start_stop[codon] = protein;
		else
			codon_map[codon] = protein;
	}
}
However, this still creates two identical maps. Why is that happening?

hooah fucked around with this message at 13:27 on Oct 24, 2013

Boz0r
Sep 7, 2006
The Rocketship in action.
I'm doing some performance tests in CUDA where I've created a particle system with collisions. The size of my data takes the warp size into account, so it's dividable by 32. I've run some tests with data sizes of 4096, 4097 and 4128. 4097 is slower than 4096, but 4128 is faster than both. How can this happen, theoretically? I've run the tests a bunch of times and the results are consistent.

FamDav
Mar 29, 2008

hooah posted:

I just got clarification from the professor that we can add a parameter to functions that are given in the assignment, so I re-wrote the fill_codon function to fill both maps at once:
code:
void fill_codon(map<string, string> &codon_map, map<string, string> &start_stop, ifstream &in_file){
	string codon, protein;
	while (in_file >> codon >> protein){
		if (protein == "START" || protein == "STOP")
			start_stop[codon] = protein;
		else
			codon_map[codon] = protein;
	}
}
However, this still creates two identical maps. Why is that happening?

How are you calling this function.

hooah
Feb 6, 2006
WTF?
It turns out that I'm an idiot and was in fact printing out the larger map twice. Changed the second print statement to print the start_stop map, and what do you know, it prints properly :doh: There goes a day or so of wasted time.

more like dICK
Feb 15, 2010

This is inevitable.
AI've got an class that owns a std::vector<Foo>. A Foo can be in one of two states, up or down. Foos are big and don't like being copied. Clients of this class only care about getting a sequence of Foos that are up, so I'd like to provide a view over the vector. Is something like a forward_list<reference_wrapper<Foo>> the best way to provide this? Assuming here that the class will add and remove Foo references to the list as they change state. Does a list of reference_wrappers offer any advantage over a list of pointers?

Volguus
Mar 3, 2009

more like dICK posted:

AI've got an class that owns a std::vector<Foo>. A Foo can be in one of two states, up or down. Foos are big and don't like being copied. Clients of this class only care about getting a sequence of Foos that are up, so I'd like to provide a view over the vector. Is something like a forward_list<reference_wrapper<Foo>> the best way to provide this? Assuming here that the class will add and remove Foo references to the list as they change state. Does a list of reference_wrappers offer any advantage over a list of pointers?

shared_ptr's could help you here.

more like dICK
Feb 15, 2010

This is inevitable.
Ownership is already well defined, handing out shared_ptrs would muddy that up.

nielsm
Jun 1, 2009



A) Do those client classes need random access to the virtual collections?
B) Can the state of a contained object change in another thread during enumeration?

If the answers are yes+no, then build a temporary vector of plain pointers to those objects and hand that out. Tell the clients to not delete those objects, and it's their own problem to skip over or remove objects they cause to change state.

If the answer to A is no, then just provide a filtering iterator. If at the same time B is yes, then include "stuff may change state at any time" in the contract.

If the answers are yes+yes, you probably won't have a good solution. (Pretend the answer to A is no, and tell the clients it's their own problem if they need random access; build a temporary vector of pointers from the filtering iterator or something with the risk of being invalid right after.)

shodanjr_gr
Nov 20, 2007
I'm porting some code over to OSX and among a number of issues, one of my dependent libraries is dumping some random stuff to the console...

Is there some sort of breakpoint I can set so I can figure out what the source of the printouts is?

ctz
Feb 6, 2003

shodanjr_gr posted:

Is there some sort of breakpoint I can set so I can figure out what the source of the printouts is?

Try breaking on calls to write and writev with the first argument as 1 or 2. That should capture everything going to stdout or stderr, whether it goes through C stdio, C++ iostreams, etc.

more like dICK
Feb 15, 2010

This is inevitable.

nielsm posted:

A) Do those client classes need random access to the virtual collections?
B) Can the state of a contained object change in another thread during enumeration?

If the answers are yes+no, then build a temporary vector of plain pointers to those objects and hand that out. Tell the clients to not delete those objects, and it's their own problem to skip over or remove objects they cause to change state.

If the answer to A is no, then just provide a filtering iterator. If at the same time B is yes, then include "stuff may change state at any time" in the contract.

If the answers are yes+yes, you probably won't have a good solution. (Pretend the answer to A is no, and tell the clients it's their own problem if they need random access; build a temporary vector of pointers from the filtering iterator or something with the risk of being invalid right after.)

I hadn't even considered providing an iterator. Boost provides a nice filter_iterator so I'll just use that.

shodanjr_gr
Nov 20, 2007

ctz posted:

Try breaking on calls to write and writev with the first argument as 1 or 2. That should capture everything going to stdout or stderr, whether it goes through C stdio, C++ iostreams, etc.

Breakpoints on write in libysystem_kernel do not trigger during the various print outs. I can't seem to be able to get writev to resolve in any way...

Fuck them
Jan 21, 2011

and their bullshit
:yotj:
I've wanted to go play with C again, but then I realized that I'm so used to OOP idioms that I have no frigging idea how to manage my data in good old C.

My first thought was to have a library of functions to work over whatever structure I had in mind, which would necessarily have to have a pointer to the 'root' of whatever structure I used; the thought of wrapping them in structs for other things like the tail of a two way linked list, or the length of a dynamic array also occurred to me.

What are the actual idioms that tend to be used in C? Would macros actually help here? I'm so used to data.doSomething(); that going back to C is honestly making me scratch my head.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
doSomething(data); ?

Fuck them
Jan 21, 2011

and their bullshit
:yotj:

Suspicious Dish posted:

doSomething(data); ?

But what about types of data and how the data is structured?

I'd need a whole set of functions for linked lists, arrays, trees, and hashes. I'd probably do well to have function pointers for comparators as pat of the argument list so that it can compare floats, ints and... whatever the hell I'd do with char* "strings."

I'm just wondering what the best practices are or where I could see a good example.

Now I'm wondering if I could bundle them in structs which would have metadata for "I am this kind of structure containing that kind of data, branch and work that magic now!" or if that would be defeating the purpose of bothering to do C in the first place.

nielsm
Jun 1, 2009



Yes, liberal use of function pointers, macros to generate generic code for specific types, plenty of use of the fact that if one struct has an initial field sequence that matches the entirety of another struct you can cast pointers to the smaller of the two and be guaranteed it's valid, and stuff like that.
Also, use of the static keyword on functions private to one compilation unit can be good to avoid contaminating the global namespace.

(Use C++ and let the compiler do the hard work for you.)

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

2banks1swap.avi posted:

But what about types of data and how the data is structured?

I'd need a whole set of functions for linked lists, arrays, trees, and hashes. I'd probably do well to have function pointers for comparators as pat of the argument list so that it can compare floats, ints and... whatever the hell I'd do with char* "strings."

I'm just wondering what the best practices are or where I could see a good example.

There are a lot of libraries for this. glib is a fairly popular one. Here's its singly-linked list for example.

hooah
Feb 6, 2006
WTF?
Is there a way to determine if a file is ending within some number of lines? The project is to take a text file representing a music library and process it. The file has 5 lines per track, then a blank line. I'd like to be able to see ahead of time if there's another 5 lines to process.

nielsm
Jun 1, 2009



hooah posted:

Is there a way to determine if a file is ending within some number of lines? The project is to take a text file representing a music library and process it. The file has 5 lines per track, then a blank line. I'd like to be able to see ahead of time if there's another 5 lines to process.

You could buffer large parts of the file manually and look ahead in it, but that will be weird to program.
I think a better solution would be to just attempt to read the five lines and store the results away in a temporary structure as you go. Whenever that structure has been filled out with all the data, store it in your master list of things to process (or process it right away), and if your partly fill a structure and the file suddenly ends, just pretend you didn't find anything more (throw away the unfinished structure.)

hooah
Feb 6, 2006
WTF?

nielsm posted:

You could buffer large parts of the file manually and look ahead in it, but that will be weird to program.
I think a better solution would be to just attempt to read the five lines and store the results away in a temporary structure as you go. Whenever that structure has been filled out with all the data, store it in your master list of things to process (or process it right away), and if your partly fill a structure and the file suddenly ends, just pretend you didn't find anything more (throw away the unfinished structure.)

Ok, that helps, thanks. Now, for some reason, Visual Studio is telling me that a method call isn't matching what I've written. Here's the constructor for a MusicLibrary:
code:
MusicLibrary::MusicLibrary(string &file){
	ifstream in_file(file);
	string line, in_name, in_artist, in_date;
	long in_id, in_size;
	while (getline(in_file, line)){
		if (line.substr(0, 2) == "So")
			in_id = stol(line.substr(5));
		else if (line.substr(0, 2) == "Na")
			in_name = line.substr(5);
		else if (line.substr(0, 2) == "Ar")
			in_artist = line.substr(7);
		else if (line.substr(0, 2) == "Si")
			in_size = stol(line.substr(5));
		else if (line.substr(0, 2) == "Da")
			in_date = line.substr(11);
		if (in_date != ""){
			MusicEntry in_entry(in_name, in_artist, in_size, in_date);
			in_entry.song_id = in_id;
			library.insert(in_entry);
		}
	}
}
VS is complaining about the insert call, which is defined here:
code:
void MusicLibrary::insert(MusicEntry &track){
	if (track.song_id != -1)
		library[track.song_id] = track;
	else {
		last_id++;
		library[last_id] = track;
	}
}
The error is

quote:

cannot convert argument 1 from 'MusicEntry' to 'std::pair<const _Kty,_Ty> &&'
.

I think I can understand the error a little bit - even though insert should take a MusicEntry, it wants to make a pair (of longs and MusicEntrys?), but it can't for some reason. Is that right? Whether it is or not, how can I go about fixing this error?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
library.insert is a call to std::map<...>::insert, not a call to MusicLibrary::insert.

hooah
Feb 6, 2006
WTF?
Oh, wow, yup. Thanks, professor, for putting an existing method in your project description.

csammis
Aug 26, 2003

Mental Institution

hooah posted:

Oh, wow, yup. Thanks, professor, for putting an existing method in your project description.

Well the problem isn't that the professor necessarily did something wrong, the problem is that you're calling a method on the wrong object. I'm guessing library is a std::map member of the MusicLibrary class and instead of calling insert on the current instance of MusicLibrary you called insert on library. It's perfectly reasonable to have methods with the same name on different objects.

hooah
Feb 6, 2006
WTF?
Alright, more problems. I've re-written the MusicLibrary constructor a bit, and now I'm trying to account for there not always being 5 lines of track information per track:
code:
MusicLibrary::MusicLibrary(string file){
	MusicEntry in_entry();
	ifstream in_file(file);
	string line1, line2, line3, line4, line5, line6, in_name, in_artist, in_date;
	long in_id, in_size;
	int line_count = 0;
	while (in_file){
		
		getline(in_file, line1);
		getline(in_file, line2);
		getline(in_file, line3);
		getline(in_file, line4);
		getline(in_file, line5);
		getline(in_file, line6);
		if (line1 == ""){
// line 1		this->insert(in_entry);
		}
		in_name = line2.substr(5);
		in_artist = line3.substr(7);
		in_size = stol(line4.substr(5));
		in_date = line5.substr(11);
		;
// line 2	in_entry.song_id_ = in_id;
		this->insert(in_entry());
	}
}
The problem is that I'm getting can't convert error for line 1 ("MusicEntry (__cdecl *)(void)' to 'MusicEntry &") and line 2 is complaining that the thing to the left of .song_id_ must be a class/struct/union. VS knows that in_entry is an object of type MusicEntry because when I hover over it, it says it's that type, so what's it complaining about? I have no idea what's going on with these errors.

csammis
Aug 26, 2003

Mental Institution
You don't use parentheses for constructors with zero parameters (it looks to the compiler like a function declaration instead of calling a constructor). The error is saying "Don't pass me a void function that returns MusicEntry when I'm expecting a reference to a MusicEntry!". Try changing MusicEntry in_entry(); to MusicEntry in_entry;.

The second error is because the declaration of in_entry didn't construct a class/struct/union as far as the compiler can see so it doesn't know what in_entry.song_id refers to.

csammis fucked around with this message at 00:03 on Nov 1, 2013

hooah
Feb 6, 2006
WTF?
Wow, thanks. I don't know why I thought it needed parentheses; I swear I've worked with classes before...

raminasi
Jan 25, 2005

a last drink with no ice

hooah posted:

Wow, thanks. I don't know why I thought it needed parentheses; I swear I've worked with classes before...

Because every other constructor uses parentheses. The stupid quirk burns so many people that it has its own name.

e: Apparently your specific instance of the problem is not considered a "most vexing parse," which I find weird, because it's far more common than "actual" most vexing parses and is, to my mind, essentially the same thing.

raminasi fucked around with this message at 02:02 on Nov 1, 2013

baby puzzle
Jun 3, 2011

I'll Sequence your Storm.
I am learning more and more about how retarded C++ can be.

b0lt
Apr 29, 2005

baby puzzle posted:

I am learning more and more about how retarded C++ can be.

Yep, C++ is basically a giant set of landmines (I bet you didn't tag MusicLibrary::MusicLibrary(string&) as explicit (also it should be const string &, or better yet just const char *)), that everyone just deals with because there aren't any better options that do what it does.

DoggesAndCattes
Aug 2, 2007

Hello and Happy Halloween. For reference, I'm going through Sams Teach Yourself C++ in One Hour a Day Seventh Edition, and on page 180 I'm working on this exercise.

code:
#include <iostream>
using namespace std;

int main()
{
    cout << "How many integers you wish to enter? ";
    int InputNums = 0;
    cin >> InputNums;

    int* pNumbers = new int [InputNums];
    int* pCopy = pNumbers;

    cout << "Successfully allocated memory for " << InputNums << " integers " << endl;
    for(int Index =0; Index < InputNums; ++Index)
    {
        cout << "Enter number " << Index << ": ";
        cin >> *(pNumbers + Index);
    }

    cout << "Displaying all numbers input: " << endl;
    for(int Index = 0; Index < InputNums; ++Index)
        cout << *(pCopy++) << " ";

    cout << endl;

    // done with using the pointer? release memory
    delete[] pNumbers;

    cout << endl;

    return 0;
}
In the second for loop, there is a second initialized condition int* pCopy = pNumbers, but I had to take it out because the code won't build. Now, I'm curious as to how I can copy pNumbers array to pCopy so after delete[] pNumbers I ran an exact copy of the second for loop after it. So far it is displaying only the 0th index of the array and then random integers values in an Nth index after that. I'm still learning about dynamic arrays and pointers in C++, but I didn't see anything in the chapter or the previous chapter on arrays about this.

Nippashish
Nov 2, 2005

Let me see you dance!

Mad Pino Rage posted:

In the second for loop, there is a second initialized condition int* pCopy = pNumbers, but I had to take it out because the code won't build.

I don't understand what these words mean.

Mad Pino Rage posted:

Now, I'm curious as to how I can copy pNumbers array to pCopy so after delete[] pNumbers I ran an exact copy of the second for loop after it. So far it is displaying only the 0th index of the array and then random integers values in an Nth index after that. I'm still learning about dynamic arrays and pointers in C++, but I didn't see anything in the chapter or the previous chapter on arrays about this.

There is only one array of numbers in your code. You set up pNumbers and pCopy to both point to the beginning of it. When you delete[] pNumbers you're also deleting the memory that pCopy points at (because it's the same memory). That's why you can store through pNumbers in the first loop and print through pCopy in the second one.

Adbot
ADBOT LOVES YOU

xgalaxy
Jan 27, 2004
i write code
If you want to copy pNumbers to pCopy then you need to allocate memory to pCopy and either manually iterate thru pNumbers assigning the numbers to pCopy, sort of like you are doing with the print loop, or call memcpy after you allocated the space in pCopy.

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