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
No Safe Word
Feb 26, 2005

Though 4(x) obviously needs to be changed to (4*x).

e:f;b ... and by like an hour, man I need to stop replying to tabs that have been open so long

Adbot
ADBOT LOVES YOU

Llama Patrol
Mar 11, 2007

ColdPie posted:

Just kind of at a first glance (about to run out the door to school myself), this looks all right. I'd add in a check to make sure x isn't negative -- that'd create an infinite loop.

Or just

code:
int recursive(unsigned int x){ ... }

Soldat
Jan 22, 2008
my name is soldat and I get respect, your cash and your jewelery is what I expect

Paniolo posted:

Here's a tutorial for writing a small Scheme interpreter in Scheme. I think it would be straightforward to take most of the concepts and re-implement them in C++.

For parsing, you could look into boost::spirit, which lets you specify grammars in EBNF-like syntax. Given the syntactical simplicity of Scheme you could probably get a parser up and running relatively easily.

This was very helpful, thank you. Our team has decided that we're going to use structs rather than classes, so we've entered the realm of C now.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?
Being aware that invoking reinterpret_cast is something that should be done with extreme care in good C++ code, I was wondering if there is anything wrong with this, or if there is a better way to do this:

code:

struct Packet {
  uint16_t foo;
  uint16_t bar;
  uint8_t isLong;
  char optData[];
};

struct LongPacket {
  Packet shortPacket;
  uint16_t extraField1;
  uint16_t extraField2;
};

void parsePacket(Packet* pkt) {
  std::cout << "Foo: " << pkt->foo << std::endl;
  std::cout << "Bar: " << pkt->bar << std::endl;
  std::cout << "Is Long: " << pkt->isLong << std::endl;

  if (pkt->isLong != 0) {
    LongPacket* l_pkt = reinterpret_cast<LongPacket*>(pkt);
    std::cout << "Extra Field 1: " << l_pkt->extraField1 << std::endl;
    std::cout << "Extra Field 2: " << l_pkt->extraField2 << std::endl;
  }
}
Where this packet is something that is going to be sent/received over a network socket, and assuming, of course, that the isLong field is accurate.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Since this is C++ code, why doesn't LongPacket just inherit from Packet so you can use static_cast?

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

JoeNotCharles posted:

Since this is C++ code, why doesn't LongPacket just inherit from Packet so you can use static_cast?

I considered that, but - and I guess this should have been an alternate question - I couldn't find any definitive answer on whether or not that would preserve field ordering and packing.

Since it's a network packet, it needs to be bit-for-bit accurate. So, if I write:

code:
#pragma pack(1)

struct Packet { 
  uint16_t foo; 
  uint16_t bar; 
  uint8_t isLong; 
}; 

struct LongPacket : public ShortPacket { 
  uint16_t extraField1; 
  uint16_t extraField2; 
};
Am I absolutely guaranteed that if I copy the contents of a LongPacket struct into a char[] buffer that, for example, buf[56] is the first byte of extraField2?

Lexical Unit
Sep 16, 2003

JoeNotCharles posted:

why doesn't LongPacket just inherit from Packet
When you get the data out of the socket on the receiving end, it'll just be a bunch of bytes. Understanding how these bytes are packed is important. So there's a desire for the datatypes to be POD. At least that's what I assume... assuming I'm not misunderstanding something.

Smackbilly posted:

I was wondering if there is anything wrong with this
Isn't there a problem if optData isn't always the same length? If not, then it seems like it'll work.

Smackbilly posted:

or if there is a better way to do this
What about this?
code:
struct Packet {
  uint16_t foo;
  uint16_t bar;
  uint8_t isLong;
  uint16_t extraField1;
  uint16_t extraField2;
  char optData[];
};
Can't you just ignore extraField1 and extraField2 if isLong isn't set?

Lexical Unit fucked around with this message at 22:51 on May 5, 2008

Vanadium
Jan 8, 2005

I do not think the language guarantees absence of padding in any case, with or without inheritance.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

Vanadium posted:

I do not think the language guarantees absence of padding in any case, with or without inheritance.

In gcc/g++, the #pragma pack(1) directive guarantees the absence of padding in plain structs. However I'm looking but I can't find out if this also applies if you use a struct more like a class (for example, adding constructors, using inheritence, etc).

I'm not terribly concerned about portability to other compilers at the moment, but this will have to build on gcc for several platforms, so I don't want to rely on something that might work on x86 but not on ARM.

Mr VacBob
Aug 27, 2003
Was yea ra chs hymmnos mea
Classes will usually have a vtable pointer at the beginning, so you can't rely on offsets from the beginning of the class. You can rely on offsets from other members, I guess.

Also, use __attribute__((packed)) if you don't care about compiler portability, otherwise you'll forget to undo the #pragma and it'll be slow.

Paniolo
Oct 9, 2007

Heads will roll.
There's only a vtable if there is a virtual function anywhere in the inheritance tree. Using #pragma pack(1) you can be fairly sure about the run-time size of a struct. However, the correct way to do what you're trying to do is to implement a serialize/unserialize method:

code:
class ShortPacket : public Packet {
   static ShortPacket* unserialize(const char* buf) {
      // pull data out of the short packet
   }
};

class LongPacket : public Packet {
   static LongPacket* unserialize(const char* buf) {
      // pull data out of the long packet
   }
};

Packet* accept_packet(const char* buf) {
   if(buf[PACKET_TYPE_OFFSET] == PACKET_TYPE_SHORT)
      return ShortPacket::unserialize(buf);
   else if(buf[PACKET_TYPE_OFFSET] == PACKET_TYPE_LONG)
      return LongPacket::unserialize(buf);
   throw std::runtime_error("Unknown packet type");
}
As a general rule you really don't want to initialize a class by memcpying into it or just casting a void pointer to a class pointer, there's just so many things that can go wrong (for example, padding, network byte order vs host byte order, corrupted or malicious data, etc.)

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.

Paniolo posted:

As a general rule you really don't want to initialize a class by memcpying into it or just casting a void pointer to a class pointer, there's just so many things that can go wrong (for example, padding, network byte order vs host byte order, corrupted or malicious data, etc.)
Specifically, if you have the choice, serialize/deserialize through text and not directly as binary.

Viper2026
Dec 15, 2004
I got iRaped by Steve Jobs and all I got was this custom title.
If anyone could take a look at this bit of code for me I'd appreciate it:

http://rafb.net/p/Xr46gD55.html

Line 61 is giving me the following error:
Blob.cpp:61: error: cannot convert 'color' to 'color (*)[5]' for argument '1' to 'int count_cells(color (*)[5], int, int)'

And I can't seem to figure out what's wrong.
The count_cells function returns the number of cells marked "abnormal" or '1' which are connected to the cell being tested.
The array it's trying to read in from the file is a 5x5 grid, and I'm attempting to fill it up with the color enumeration types depending if a 1 or 0 is read (the other 2 infile variables at the beginning are the test row/column, the size of the grid and the test cell are the first 4 characters in the file). As I said before, the grid is 5x5 so once I figure out how to fix this error I'll figure out some way to make the function called on a grid of arbitrary size.

In case anyone wants to see the contents of the file in question:
code:
5 5 1 1
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
So the expected printout of my function call would be 10. (grid and row indexes start at 0)

Viper2026 fucked around with this message at 05:08 on May 6, 2008

Paniolo
Oct 9, 2007

Heads will roll.
code:
// This doesn't pass an array, this passes the cell at [r_size][c_size]
// Even if it did compile, this would cause a segfault
count_cells(grid[r_size][c_size], r_test, c_test)

// Try this
count_cells(grid, r_test, c_test)
Also you can't declare an array like this:

code:
int x = 5; // or whatever
int array[x];

// You have to dynamically allocate the array
int* array = new int[x];
Finally, if you do that, you'll have bugs if the array you're dynamically allocating isn't 5x5 because what you're passing to the count_cells function is. Frankly, multidimensional arrays are more trouble than they are worth, and are typically a sign of a newbie programmer. A better solution is this:

code:
int* grid = new int[width*height];

int get_cell_state(int* grid, unsigned int width, unsigned int height, int x, int y) {
   assert(width > 0);
   assert(height > 0);
   assert(y < height);
   assert(x < width);
   
   return grid[(width*y)+x];
}

Viper2026
Dec 15, 2004
I got iRaped by Steve Jobs and all I got was this custom title.
Thanks for the help, but this is some crap my teacher got out of a textbook and gave us that count_cells() function along with enumeration type at the top, then was like "make it do this this and this". If I had a choice of doing it some other way I would :mad:

I changed the row/col size variables to type of size_t and now it lets me create the array given the values read in from my file. However, when I try to call my function:

cout << count_cells(the_grid[r_size][c_size], r_test, c_test) << "\n";

again, I'm getting this:

error: cannot convert 'color' to 'color (*)[5]' for argument '1' to 'int count_cells(color (*)[5], int, int)'


The code in question:
code:
	ifstream infile("tests/myfile.txt", ios::in);
	size_t r_size = 0;
	size_t c_size = 0;
	int r_test, c_test, read_data;
	
	infile >> r_size >> c_size >> r_test >> c_test;
	color the_grid[r_size][c_size];

Viper2026 fucked around with this message at 05:56 on May 6, 2008

elevatordeadline
Jan 29, 2008

TSDK posted:

I think your dev environment is misconfigured. By the looks of it, either there's a mismatch in the calling convention or the long double support between your executable and the library you're linking against.
I guess so. As it turns out, changing long doubles and %Lfs, respectively, to doubles and %fs made everything work as it should've in the first place.

Incoherence
May 22, 2004

POYO AND TEAR

Viper2026 posted:

I changed the row/col size variables to type of size_t and now it lets me create the array given the values read in from my file. However, when I try to call my function:

cout << count_cells(the_grid[r_size][c_size], r_test, c_test) << "\n";

again, I'm getting this:

error: cannot convert 'color' to 'color (*)[5]' for argument '1' to 'int count_cells(color (*)[5], int, int)'
As mentioned before, the_grid[r_size][c_size] is a cell (which is why the compiler says it's of type color). Moreover, it's a cell that's not in the grid, so even if it compiled it would immediately segfault and you'd have even less feedback.

Go look at Paniolo's post again, particular the first code block.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Paniolo posted:

Also you can't declare an array like this:

code:
int x = 5; // or whatever
int array[x];

Actually you can in gcc - it's a compiler extension. (You shouldn't, though, because it makes your code non-portable.)

Lexical Unit
Sep 16, 2003

Why does this assert?
code:
#include <vector>
#include <fstream>
#include <iterator>
#include <iostream>

using namespace std;

int main()
{
	fstream f ("blob", ios::in | ios::out | ios::trunc);
	streampos start = f.rdbuf ()->pubseekoff (0, ios::cur);
	char data[] = "this is just a test";
	f.write (data, sizeof (data));
	f.rdbuf ()->pubseekpos (start);
	vector<char> v;
	v.insert (v.end (), istream_iterator<char> (f), istream_iterator<char> ());
	assert (!f.fail ());
	return 0;
}
Edit: Never mind, I should have tried harder with google.

Answer: "After reading the last available character, the extraction not only reads past the end of the input sequence; it also fails to extract the requested character. Hence, failbit is set in addition to eofbit."

Lexical Unit fucked around with this message at 17:26 on May 6, 2008

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?
This may be silly/stupid, but is it in any way possible to do this?

code:
class Foo : public Bar<Foo::Things::Thing> {

public:

  struct Things {
    enum Thing {
      // ...
    };
   };

   // ...

};
Basically I have an enum declared (publicly) within a class. The enum is contained by an otherwise empty struct for the purpose of giving the enumerated values their own namespace. I want to pass the enum type as a template argument to a class that I want to inherit from. I can't seem to find any way to forward-declare things that occur inside a top-level class, and I'm thinking this might be impossible simply because I'm asking a base class to do something with a type declared in a derived class, but I'm wondering if there is any way to get this effect.

The motivation behind this is that I'm writing a number of classes that all have several identical member functions that accept enumerated values, but the enumerated values are different for each class. I was thinking it would be handy to have a common templated base class that handled the implementation of these member functions so that I wouldn't have to duplicate the code. The other way to do this (my present solution) is to have each class call templated utility functions that are in an unrelated clsas, but in that case there is still an identical interface to the utility function in each class.

Obviously one solution is to move the Things struct outside of the class, but then the namespace for the Thing values would have to be FooThings:: instead of Foo::Things:: which seems inelegant to me.

Mr VacBob
Aug 27, 2003
Was yea ra chs hymmnos mea

JoeNotCharles posted:

Actually you can in gcc - it's a compiler extension. (You shouldn't, though, because it makes your code non-portable.)

It's legal C99, but that assumes a C99 compiler.

vv That means they're not perfect (see the note), but I've never had any trouble with them in practice.

Mr VacBob fucked around with this message at 20:22 on May 6, 2008

KaeseEs
Feb 23, 2007

by Fragmaster

Mr VacBob posted:

It's legal C99, but that assumes a C99 compiler.

IIRC variable-length arrays are one of the most problematic C99 features with respect to the implementations of various compilers

edit: this page says they're still broken in gcc 4.3

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Smackbilly posted:

This may be silly/stupid, but is it in any way possible to do this?

code:
class Foo : public Bar<Foo::Things::Thing> {

public:

  struct Things {
    enum Thing {
      // ...
    };
   };

   // ...

};

Off the top of my head, try

code:
class FooBase {
public:
  struct Things { ... };
};

class Foo : public Bar<FooBase::Things::Thing>, public FooBase {
  ...
};
Since Foo inherits FooBase, I believe you can now refer to FooBase::Things as Foo::Things. (Not in the actual definition of Foo, but at least you're containing the inelegance.)

Paniolo
Oct 9, 2007

Heads will roll.

JoeNotCharles posted:

Since Foo inherits FooBase, I believe you can now refer to FooBase::Things as Foo::Things. (Not in the actual definition of Foo, but at least you're containing the inelegance.)

http://codepad.org/exT9EKui

You actually can refer directly to Foo::Thing from within the definition of Foo. What you have to be careful with is in the Base class.. if you do something like this:

code:
template <typename T>
struct Base {
   typedef typename T::Thing Thing;
};
Then referring to Foo::Thing is ambiguous (is it FooThing::Thing or Base<FooThing>::Thing? Even though they are identical types C++ isn't clever enough to know this.)

Professor Science
Mar 8, 2006
diplodocus + mortarboard = party
What the gently caress, Qt 4.4 supports futures? Holy poo poo.

vanjalolz
Oct 31, 2006

Ha Ha Ha HaHa Ha
code:
void runlinked(const char* cmd1, const char* argv1[], const char* cmd2, const char* argv2[], int *retval)
{
	...
	/* warning: passing argument 2 of ‘execvp’ from incompatible pointer type */
	execvp(cmd1, argv1);
Why does this code produce a warning on argument 2 of execvp?
I checked the man page and its meant to be a const char* :|
(actually it says char * const, but i tried that too and it didn't help)
What am i missing?

gcc version 4.0.1 (Apple Inc. build 5465)

Paniolo
Oct 9, 2007

Heads will roll.
You're passing a pointer to a array of const char* to a function which takes a pointer to a const char*. Try this:

code:
execvp(cmd1, argv1[0]);

vanjalolz
Oct 31, 2006

Ha Ha Ha HaHa Ha
Oh I see, thanks.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Professor Science posted:

What the gently caress, Qt 4.4 supports futures? Holy poo poo.

I took a look for that and couldn't find any docs. Can you point me to a reference?

Id4ever
Dec 2, 2004

JoeNotCharles posted:

I took a look for that and couldn't find any docs. Can you point me to a reference?

http://doc.trolltech.com/4.4/qfuture.html
http://labs.trolltech.com/blogs/2007/03/08/making-asynchronous-function-calls-with-qfuture/

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Oh, I completely missed that 4.4 already had an entry on the main doc page - I was looking around for previews and getting pissed off that all the Google links were outdated.

Wow, the whole QConcurrent framework looks fantastic.

Professor Science
Mar 8, 2006
diplodocus + mortarboard = party

JoeNotCharles posted:

Wow, the whole QConcurrent framework looks fantastic.
Any idea how it's implemented on the backend?

Soldat
Jan 22, 2008
my name is soldat and I get respect, your cash and your jewelery is what I expect
code:
bool primcheck_add (char exp[])
{
  char begin[10];
 
  if (length(exp) > 1)
    {
      for (int x=0; x < 4; x++)
    begin[x]=exp[x];
      begin[4] = '\0';
      if (begin[0] == 'a')
    if (begin[1] == 'd')
      if (begin[2] == 'd')
        if (begin[3] == '1')
          return true;
        else
          return false;
    }
  else
    return false; 
}

bool primcheck_sub (char exp[])
{
  char begin [10];

  if (length(exp) > 1)
    {  
      for (int x=0; x < 4; x++)
    begin[x]=exp[x];
      begin[4] = '\0';
      if (begin[0] == 's')
    if (begin[1] == 'u')
      if (begin[2] == 'b')
        if (begin[3] == '1')
          return true;
        else
          return false;
    }
  else
    return false; 
}

bool longprim_check (char exp[])
{
  if (primcheck_add(exp))
    return true;
  else if (primcheck_sub(exp))
    return true;
  else
    return false;
}
When I call longprim_check, I just went it to return true if the input is simply 'add1' or 'sub1'. Anything else I want it to return false. Right now it's returning true for everything. What glaringly obvious thing am I missing?

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Soldat posted:

When I call longprim_check, I just went it to return true if the input is simply 'add1' or 'sub1'. Anything else I want it to return false. Right now it's returning true for everything. What glaringly obvious thing am I missing?

The strcmp function?

haveblue
Aug 15, 2005



Toilet Rascal

Soldat posted:

When I call longprim_check, I just went it to return true if the input is simply 'add1' or 'sub1'. Anything else I want it to return false. Right now it's returning true for everything. What glaringly obvious thing am I missing?

The strcmp function and the fact that most of your nested if statements do not have else cases. If you pass "adff" to primcheck_add it's just going to fall out in the middle, returning garbage (which would be interpreted as true unless it was 0). Your compiler should be warning you about this.

Soldat
Jan 22, 2008
my name is soldat and I get respect, your cash and your jewelery is what I expect
code:
bool primcheck_mult (char exp[])
{
  char begin[4];
  char add[] = "add1";
  char sub[] = "sub1";
 
 
  if (length(exp) > 1)
    {
      for (int x=0; x < 4; x++)
    begin[x]=exp[x];
      begin[4] = '\0';
      if (strcmp (begin,add))
    return true;
      else if (strcmp (begin,sub))
    return true;
      else
    return false;
    }
  else
    return false;
}

Sorry to make you bear with me here, I'm not asking to get my work done, but I'm really beginning to get frustrated. I'm getting no warnings from the compiler, but no matter what the input is, it returns true. This doesn't need to be a very robust program, it just needs these two specific cases. I can change the first if to: if ((length(exp) > 1) && (length(exp) < 5)) if I need to, but it still is coming back true even if the input isn't specifically add1 or sub1...any advice appreciated again.

Soldat fucked around with this message at 23:22 on May 8, 2008

TheSleeper
Feb 20, 2003
In addition to what they say before, if you really refuse to use strcmp, have you never heard of the && operater?

edit: and why are you using an array of 10 characters when you only ever use 4 in both those functions.

TheSleeper fucked around with this message at 23:13 on May 8, 2008

Soldat
Jan 22, 2008
my name is soldat and I get respect, your cash and your jewelery is what I expect
oops, accidental post

crazypenguin
Mar 9, 2005
nothing witty here, move along
strcmp returns 0 when the strings are the same.

so basically, stick a ! before those strcmps

Adbot
ADBOT LOVES YOU

StickGuy
Dec 9, 2000

We are on an expedicion. Find the moon is our mission.

Soldat posted:

code:
  char begin[4];
...
      begin[4] = '\0';
Sorry to make you bear with me here, I'm not asking to get my work done, but I'm really beginning to get frustrated.
It's time to for you to familiarize yourself with two of a programmer's best friends: the debugger and the documentation. If you step through the code with a debugger, you'll see precisely where it's going wrong. Then you can look up the relevant things in the documentation to understand what's causing it. As a freebie, though, begin now only has 4 characters and you're setting the 5th to null.

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