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
rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

That Turkey Story posted:

A non-dynamically allocated char array or a vector are your best standard options given the interface he's dealing with. Do you have a better suggestion without changing windows?

He can at least allocate the thing on the stack, unless it absolutely needs to be (1) global or (2) dynamically sized and compiled with a pre-C99 compiler.

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

ehnus posted:

You could always use alloca() to get around that, too.

Absolutely, if you're on a system that supports alloca(). It's one of these things that really requires compiler support, but that you can sortof get away with in a library if your compiler is nice enough to leave your assumptions intact.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Mr.Mojo posted:

I'm doing a problem that asks me to implement logical negation, !, without using !. My idea is to use "~x+1", but the tester says this is incorrect. What am I doing wrong?

Do you understand the semantics of logical negation? Your proposal doesn't satisfy them for... well, for anything.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Clock Explosion posted:

This is sort of C++ and 80x86 assembly together, but I'll include it here.

I have to pass a string of characters from cin into an assembly procedure.

Out of ease of use mostly, would using std::string or using c-style strings be easier? Would I even have any difficulty if I used just a normal string?

If you're already using C++, then unless you're reading fixed-length records I can't see a good reason not to use std::string here. Your assembly procedure will probably expect a char* and an int, but you can get those from a std::string without any trouble, and it'll save you from writing a lot of error-prone code.

I don't know what you mean by "normal string" in contrast with both "c-style strings" and "std::string".

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Clock Explosion posted:

The string that the user inputs is fixed-length, actually. I probably should have mentioned that.

So this isn't so much a "user" as a file format? If it's really a user, you probably don't want to assume fixed-length records.

I don't know the best way to read fixed-length records from an istream; I've never had to do it.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Clock Explosion posted:

Maybe I'm just getting the fixed-length records part wrong or confused (which happens with me a lot, unfortunately), but essentially the user types in 8 hexadecimal digits. That's it. The string is validated anyways, so there will be 8 hexadecimal digits that reach the ASM procedure.

Okay. When people say fixed-length records, they generally mean some sort of data layout scheme where every record is exactly n bytes long, which lets you jump freely around the input to the record with a particular index. Generally, when dealing with fixed-length records, it's sometimes nicer to use the lower-level APIs. Since that's not really what you're talking about, I'd just use a std::string.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

DontMockMySmock posted:

I *think* I know how to copy the binary file to an array of size (N*N*K), but then is it 1-dimensional? How do I convert it to a 3D array? Also, I'm not entirely sure on the syntax of fread/fwrite anyway, and if anyone could explain that to me I would appreciate it.

I'm assuming that N and K can grow large. Your program should be able to extract the data with a minimum of reads and writes, but that's contingent on some other constaints:
  • Are N and K global constants, or are they only constants on a per-file basis?
  • Does this binary file solely contain the matrix data? If not, is the other data fixed in size?
  • What's the layout of the matrix? i.e. what axis is "most continguous" in the file? For example, if I had a 3x3x2 matrix (((1 2) (3 4) (5 6)) ((7 8) (9 10) (11 12)) ((13 14) (15 16) (17 18))), would that be laid out as (1 2 3 4 5 6...), or as (1 2 7 8 13 14 ...), or (1 3 5 7 9 11 ..., or....?
  • Do you know the physical representation of numbers? Are they native-ordered IEEE floats or doubles? If not, are they at least fixed-size?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

DontMockMySmock posted:

Yes they are global constants, yes the file has solely the matrix data, it is laid out so the first dimension varies first, so in your example it would be 1,2,3,4,5, etc. the way you drew it which would actually be called 2x3x3; in other words it varies x then y then z. The numbers are 8-byte floating point numbers.

Okay, in that case you can do this really efficiently: fopen the file, fseek to the offset (N*x+y)*K*8, fread K*8 bytes into an appropriately-sized buffer, and fclose. You probably want to disable library-level buffering on the FILE*.

Just in case you've never used fread-like APIs before: fread can return to you with an incomplete result, so you'll need to loop until you've read all K entries. Of course, if you don't need to materialize the entire K-vector at once, you can just read it in bits and pieces and process the data as it's read.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

ShinAli posted:

I'm not sure if I'm allowed to do that, though. Do I cast the pointers to some other type, do what I need to do, and cast it back to a pointer?

Your original proposal sounds like perfectly correct and portable C. But why on earth do you need to allocate strings in a consecutive block like that?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

DontMockMySmock posted:

I'm not sure I understand that entirely, but it seems like you think the K values I am trying to read are next to each other in the file, which they are not. They are separated by N*N-1 other data points, or something like that.

Ah, okay. I think we talked past each other a bit there.

DontMockMySmock posted:

Also, this needs to be done several thousand times for different x and y values.

That radically changes the problem. I was treating your question as follows: "I have a file which acts as a sort of database of matrix data, and I want to extract a small amount of information from it." It sounds more like you're trying to do a matrix "rotation", i.e. transforming a sequence of K NxN matrices into an NxN matrix of K-vectors. This will perform much better if you process your file sequentially rather than trying to extract each vector individually.

What you really want is something like this (assuming I'm understanding your matrix major order):

code:
double output[][N][K] = malloc(N*N*K*sizeof(double));
for (int m = 0; m < K; ++m) {
  for (int x = 0; x < N; ++x) {
    for (int y = 0; y < N; ++y) {
      output[x][y][m] = read_next_double();
    }
  }
}
(Note that this code assumes that N and K are compile-time constants, i.e. defined using #define N 26, not const int N = 26;)

This code strides over memory wastefully, but that's way better than striding over disk wastefully.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

DontMockMySmock posted:

I'm still not sure that's the fastest way to do it, since I am not going to need the data sequentially, I will be sampling each K-size matrix at random as part of an algorithm. Any thoughts?

What do you mean by "k-size matrix"? I've been assuming that you need the entire k-vector at a particular (x,y), and that your sampling process is looking at a subset of the possible (x,y)-coordinates. Since your vectors are not compact on disk, you will be touching many of the file's blocks, even if you only end up needing a very small proportion of the actual bytes from each block. Now, disks are much faster at reading sequential blocks than they are at reading randomly-accessed blocks, and competent filesystems try to lay files out to make sequential access faster. Therefore, it's quite possible that you will find it faster to read in the entire file than to try to avoid reading the parts you don't need.

This all assumes that it's actually possible to read the entire file into memory, and of course it might be too large for that.

Things you can try if you're worried about reading in the entire file:
  • If your algorithm allows you to precompute your sampling coordinates, you can just scan over the file once and selectively materialize exactly the k-vectors you need. You might be able to skip some blocks this way.
  • If the file's small enough to fit into the memory space of your machine, you can try mmapping it. That won't magically make your disk-access patterns more efficient, but it will likely make better use of the disk cache if you're still using the random-access patterns.
  • If you might need to run this computation many times on the same file, you might consider pre-processing it into a new file which records the k-vectors compactly.
  • Similarly, if you have control over the production of the original file, you might want to consider altering it to place the k-vectors sequentially. Of course, that depends on the efficiency needs of the producer and any other consumers out there.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

awesmoe posted:

I've been some of the best-practice textbooks out there and they strongly discourage macro use (for pretty sensible sounding reasons).
I was wondering if there was an accepted replacement for debug/instrumentation macros? Or if I've been lied to my whole professional life and there's no reason to do debugging as a macro in the first place.

Programming language style guides are every bit as full of sketchy folk wisdom and misguided over-prescriptions as, well, natural language style guides. There are lots of sensible uses for macros, and debugging and instrumentation are high among them. Moreover, they are often the only reasonable way of accomplishing things like, say, globally-scoped compile-time constants or basic compiler/platform portability. In an ideal world, many of these things would be accomplished by safer, more principled language features; but we do not live in such a world, at least inasmuch as we are writing code in C and C++.

Of course, there's a pretty long list of things you should not use macros for:
  • Do not use macros as a cheap form of inlining.
  • Do not use macros as a cheap form of polymorphism.
  • Do not use macros to "override" external declarations, unless you are absolutely forced to.
  • Do not use macros to implement your own private syntax.
  • etc.

But as long as you obey the principle of least surprise, you should be fine.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

npn posted:

I occasionally implement foreach using macros since it saves a bunch of repetitious declaration/initialisations and, to my mind, makes it easier to see what is being done at a glance. Am I a bad person?

It's sketchy but not completely evil, at least if it avoids re-evaluating its arguments and doesn't internally hardcode knowledge about the ending condition. I wouldn't do it myself, though, and certainly not in code meant for wider reading. I've gotten pretty used to instantly deciphering for loops, so I'd probably spend longer looking at your macro and verifying that it does the sensible thing than I would just reading the for loop.

I agree that the typing is obnoxious.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
code:
bob = getFoo();
This has completely different semantics in your two examples.

EDIT: Sorry if you understood that; late night snark is not helpful. Basically, no, there's no way to do what you want to do, at least not unless you can't rework it to use a ternary operator: the referent of a reference variable has to be fixed at the time of creation.

rjmccall fucked around with this message at 10:18 on Oct 12, 2008

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
rand is usually typed to return an int, and C doesn't require a particular semantics for the % operator when applied to negative dividends. Many platforms use modulus semantics, i.e. (x/y,x%y)=(a,b) where 0<=b<y and ay+b=x, but it's also permitted to use remainder semantics, i.e. |ay|<=|x| and -y<b<y. If you're seeing a range of 40-120, this may be why.

EDIT: to be precise, C requires / and % to be consistent (i.e. (x/y)*y+x%y=x), and it requires the absolute value of x % y to be less than the absolute value of y whenever y is non-zero, and it furthermore requires x % y to be non-negative whenever x is, but that's it.

rjmccall fucked around with this message at 12:24 on Oct 17, 2008

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Vanadium posted:

rand is also guaranteed to return a non-negative int. What are you getting at?

So it is, my mistake.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

rrenna posted:

I'm representing my university at a programming competition next week and the team was formed last minute. It's me and two other guys but i was the most experienced programmer so i'm in charge of writing all the code and they are in charge of coming up with the algorithms.

Anyways I was pretty confident going in because I have boatloads of c# and java experience, however our "coach" has just told us he wants us to do it all in C++ (which the other two have never done). I've done C, but this was years ago and when i was just starting to learn programming.

For what it's worth, your coach is an idiot, and you should always do programming competitions in languages/environments that you're comfortable with. C++ (and likewise C) is already a poor choice of language for programming competitions, which often involve a lot of rapid prototyping and redevelopment, but which typically don't emphasize constant-factor efficiency. The last thing you want to do in a programming competition is waste an hour tracking down a memory error.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah, literals in C-like languages are not polymorphic. If you were compiling with -Wall, your compiler would probably be warning you that that literal exceeds the range of an int.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Avenging Dentist posted:

Here's a better way:

The debt clock estimates that the current population of the United States is 305,7,812 people.

code:
#include <limits.h>
#include <inttypes.h>

const char *itoa_comma(int32_t val) {
  /* forward-declared variable for conformance to antiquated standards */
  int d;

  /* incomprehensible #define with undocumented fudge factor */
#define MAXLEN (4 + 32 * sizeof val / 10)
 
  /* static buffer to needlessly clobber thread safety */
  static char buffer[MAXLEN];

#define quo(i) #i
  /* unportable reliance on literal representation */
  if (val == INT_MIN) return quo(INT_MIN);

  /* possibly misleading type */
  int negative = val < 0;
  if (negative) val = -val;

  char *position = &buffer[MAXLEN];

  /* lots of pointer arithmetic ahead */
  *--position = '\0';

  while (val >= 1000) {
    d = val % 10; val /= 10;
    *--position = '0' + (char) d;

    d = val % 10; val /= 10;
    *--position = '0' + (char) d;

    d = val % 10; val /= 10;
    *--position = '0' + (char) d;

    *--position = ',';
  }

  while (val != 0) {
    d = val % 10; val /= 10;
    *--position = '0' + (char) d;
  }

  if (negative) *--position = '-';
  return position;
}

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Honestly, I'd just do this the brain-dead way. I'm using the C functions because I'm more familiar with them; I'm sure there's a C++-ism for this.

code:
DiceExpr parse(const char *input) {
  DiceExpr out; /* if this is C, be sure to initialize this */

  const char *cur = input, *nxt;

  /* read the count; zero-length counts default to 1 */
  out.count = strtol(cur, &nxt, 10);
  if (nxt == cur) out.count = 1;

  cur = nxt;

  while (cur[0] != '\0') {
    char which = cur[0];

    /* read the value for this feature; zero-length is an error */
    long value = strtol(cur+1, &nxt, 10);
    if (cur == nxt) {
      out.count = 0; /* signal error */
      return out;
    }

    cur = nxt;

    switch (which) {
      case 'd': out.dice = value; break;
      case 'r': out.reroll = value; break;
      case 'x': out.explode = value; break;
      case 'k': out.keep = value; break;
      case '+': out.modifier += value; break;
      case '-': out.modifier -= value; break;
      default: out.count = 0; return out; /* error */
    }
  }
  return out;
}

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Ari posted:

I can also add a quick check in there to make sure nobody's putting in more than one of the same expression - 4d6k3k3 for example; it'd check against a default of -1 or something.

If you're going to do real validation, you should also check against negative values, since my function will happily parse something like 3d-6.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

crazylakerfan posted:

i have tried searching online, but i can't seem to phrase this right so all i get is how to pass a stream as a parameter, but that isn't what i want.

You are going to have to elaborate on what you're trying to do. An (input) stream is just a source of data. If you want a function to read some of that data out of the stream, you'll have to pass the stream as a parameter. If you want to remember any of that data after it's been read, you'll have to save it somewhere.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

DontMockMySmock posted:

It is working now. I have no idea why. The world of computer science is a great big enigma to me.

Wild guess: something didn't get recompiled/relinked properly.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

xluna posted:

My assumption here is that the author is converting the returns of LoadImage and SelectObject into HBITMAP types. How did the author know to do this, and why does it work?

Assumptions about the implementations of those functions. In particular, I assume LoadImage returns an HBITMAP when you pass in IMAGE_BITMAP. I don't know this API well enough to tell you why the call to SelectObject works; maybe those are both HBITMAPs?

You're right that they can both be static_casts, though.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

JoeNotCharles posted:

There must be one, because it's stuck in my head that ^ and ** are the two common power operators. I was gonna say Pascal, but Pascal uses it for pointers or references or something.

Oh, Basic, of course.

And TeX, but of course it isn't computational there.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

sandkabob posted:

So what should I declare arrayPointer as? What type is array?

If x and y are constant expressions, &array will be a double (*)[x][y], and array itself will "decay" to a double (*)[y]. If x and y need to be dynamic, you will either need to 1) represent the array as an array of pointers to double arrays or 2) use a single-dimensional array of length x*y and use y*i+j as your index.

EDIT: y*i+j is the right index expression to preserve the same cell-ordering as the builtin multi-dimensional array type.
EDIT 2: Meant to say array, not arrayPointer.
EDIT 3: Also, yes, what Avenging Dentist says below about parameters: as a parameter, array is already just a double(*)[y], and C lets you give a spurious dimension there just for fun. A variable declared array[x][y] anywhere else is different, and what I said applies. Sorry, didn't pay close enough attention.

rjmccall fucked around with this message at 02:51 on Nov 21, 2008

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

hexadecimal posted:

actual C++ question: Do C++ compilers optimize tail recursive functions into iterative ones?

gcc enables -foptimize-sibling-calls at -O2 and higher; I don't know about VC++. Last time I heard, gcc's TCO is unnecessarily conservative: GCC basically doesn't do the sort of analysis which lets you selectively enable the optimization, so all sorts of code can just automatically disable it. It's not the sort of thing you want to rely on unless you do.

rjmccall fucked around with this message at 15:28 on Nov 24, 2008

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Nahrix posted:

I know I'm either declaring file improperly in the first place, or setting the parameter in fillFiles improperly, but no combination of asterisks and/or brackets have come out successful so far. I would also like to understand what I'm doing wrong rather than just trying out different combinations in hopes of getting lucky.

file is an array of length 10 of FILE* (i.e. FILE*[10]). Therefore &file will be a pointer to an array of length 10 of FILE* (i.e. FILE*(*)[10]), which won't match the argument type, hence type failure. However, values of array type can "decay" automatically to values of pointer type; hence file can decay to a FILE**, which is exactly what you want.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

HauntedRobot posted:

Given that I can't bust straight in and radically alter the design, am I SOL here, or is there something I can do to make the above work with pointers to functions with an arbitrary number of parameters?

This is one of the major incompatibilities between C and C++; it doesn't usually cause problems, but congratulations, you've found a place where it does. You will have to either (1) change the old code to conform to C++ or (2) make sure that you're compiling the old code with a C compiler instead of a C++ compiler. The easiest route to (1) is to use a union of some sort. (2) will require you to keep the code in a separate compilation module from your C++ code; if you name this file with a .c extension, usually it will automatically get compiled as C, but if all else fails your compiler should have an option to force C language semantics (in gcc, this is -x c).

The C89 language revision is independent of this. The C89 standard officially endorsed the new argument declaration syntax (int main(int argc, char **argv) {}), broke the old K&R syntax (int main() int argc; char **argc; {}), and introduced the syntax int foo(void) to explicitly declare that a function takes no arguments.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

SimpleCoax posted:

I have a C++ question. I'm reading this code which is doing some a part of some plane regression and wondering why you may want to do the lines with question marks, or what they are actually doing. The pointer array is a one dimensional array holding a bunch of data points x,y,z,x,y,z,...etc.

Compilers can be weird, and sometimes crap like this compiles better, at least when it doesn't compile dramatically worse. In this case, though, I strongly suspect it's just typical beginner confusion about pointer arithmetic.

EDIT: also what AD said.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Avenging Dentist posted:

On the subject of memory allocation, is there a better way to allocate space for an object but not call its constructor than doing this? (malloc is an obvious choice, but 1) is more verbose and 2) doesn't allow the use of delete later.)

Arguably you should use T::operator new if it exists; I don't know how to do that (or if you can) in template metaprogramming.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Avenging Dentist posted:

EDIT: The more I think about it, the more it makes sense, given that you wouldn't necessarily know how many destructors to call. Still, this makes C++ slightly more stupid than before, since you can't dynamically allocate an array of objects unless they're default constructible.

Yeah, since string has a destructor, new string[n] has to remember n somehow. It looks like gcc basically allocates a struct { size_t; string[n]; }, and that's what delete[] expects to find.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

theg sprank posted:

Is there a way to (quasi-)portably detect how many cores the machine has, either at runtime or compile time?

No.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Presumably the entries are evaluated on a Unix box, where cls is meaningless. Basically, you really shouldn't need anything system-specific for these problems; just print the correct results to the console and don't worry about anything that your system/shell might have put there before your program started running.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Bitruder posted:

Is there a quick and reliable way to check if X11 is available? My application is (Linux of course) a CLI application that generates EPS images. If X11 is available, I'd like to launch gv image.eps to show the user, but if it's not available, I won't bother. This isn't a compile check since users could be running this off their desktop or maybe just SSH'ing in.

The standard technique is to check whether the DISPLAY environment variable is set, though I would suggest also adding a command-line option to enable/disable/configure this feature.

rjmccall fucked around with this message at 21:54 on Dec 29, 2008

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
12.2.3. Temporary objects are destroyed as the last step in evaluating the full-expression that lexically contains the point where they were created.

The two exceptions are when initializing reference (12.2.5) and non-reference (12.2.4) variables, both of which only extend the lifetime of the object. So gcc's behavior is, in fact, mandated by the standard.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
This would be somewhat less painful to debug if you were using references more and pointers less. Also, sometimes you delete[] the return value from getPoints(), and sometimes you don't.

Returning a std::list (as opposed to a pointer to a malloc'ed one, or some other way of passing the information back) is a bad idea, but it's probably not a memory bug.

Anyway, that's what I see in a quick scan.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Mustach posted:

Correct; I forgot some parens:
code:
#define ARRSIZE(a) (sizeof(a)/sizeof((a)[0]))
edit: Actually, I can't think of a situation where those parens in (a)[0] would be required. Can anybody else?

Not in C. Defensive parens in macros have two uses: they prevent unexpected parses involving binary operators, and they prevent spurious parsing successes in a lot of other cases. Now, this macro only gives useful results when a is of some statically-sized array type; since none of the C binary operators can ever return one, and since the use of sizeof(a) already prevents spurious successes for this macro, we don't need the parens for any sensible use. However, in C++ you could define some crazy binary operator that returns a (say) int[7]&, and then you'd need the parens.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Avenging Dentist posted:

Yeah, but if you're using macros in C++ you're asking for trouble.

Definitely true.

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
As a reminder, objects you create using Widget w(0, true); are created on the stack and are only valid until they go out of scope. The compiler will not catch this mistake for you. You'll need to use new if you want to create things on the heap.

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