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
ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Ari posted:

GCC's not linking in certain libraries in the C standard library. I can't find any documentation anywhere to help me figure out how to link these in, or force GCC to always link whatever's necessary - any ideas?

New Debian installation, GCC 4.1.2.

The standard library is only a single library, libc, which is always linked in unless you explicitly specify not to. What error are you getting?

Adbot
ADBOT LOVES YOU

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Ari posted:

code:
ari@beren:~/cs$ cat thing.c
#include <stdio.h>
#include <math.h>

int main()
{
        double x = 4.0;
        printf("%f\n",sqrt(x));
        return 0;
}
ari@beren:~/cs$ gcc -o thing thing.c
/tmp/cceWZZcu.o: In function `main':
thing.c:(.text+0x35): undefined reference to `sqrt'
collect2: ld returned 1 exit status
ari@beren:~/cs$
This happens whenever I need to reference a function from math.h or stdlib.h - I just gave an example here from math.h. The stdio functions work fine though.

You can add -lm to the end of the gcc command, which will link in the math library, or if you're on x86 you can add -O which turns on optimizations, including transforming sqrt calls to direct FPU invocation, removing the need for the math library.

In the manpage for sqrt(3) you may note the line "Link with -lm.", which specifies which library the function is defined in. Another way to find symbols is "nm -A --defined-only /usr/lib/*.a 2>/dev/null | grep sqrt", which will list all the symbols in all the development libraries you have installed, and search for those that match "sqrt". If a library is called "/usr/lib/libm.a", then you link to it by adding "-lm" at the end of the gcc line.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Thug Bonnet posted:

Is it possible to examine the memory space a program resides in from within the program?

...yes, programs can read their own memory. But that can't possibly be what you mean to be asking. What are you trying to do?

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Sarah Sherman posted:

I'm still pretty new to C++ (first-year student), and I have some quick questions for a personal program of mine.

You need to do a better job of describing what you want your program to do.

Sarah Sherman posted:

I'm writing a program that will randomly generate a number between 1 and 20 for a specified number of players, and then team up the players based on what number they got. The pairings are based on highest number is teamed up with lowest number, and the two middle numbers are paired together.

OK, so let's say there are four players: Alice, Bob, Carol, and Dennis. Alice rolls 20. Bob rolls 3. Carol rolls 7. Dennis rolls 14. The teams are (Alice, Bob) and (Carol, Dennis), right? What happens if Dennis rolled a 3? What happens if there are some number of players other than four?

Sarah Sherman posted:

How would I go about doing this? I can code most of the program just fine, but don't really have the programming knowledge to do the 'teaming up' aspect of the program.

How you would "team up" players depends on what you're going to do with the teams later on. We can discuss appropriate data structures after we have the rules of the game down, because they tend to depend on the application logic.

Sarah Sherman posted:

Also, after generating these random numbers, I need to set the order of who goes first, based on how biggest number to smallest. How could I do that?

If the teams are decided as you said above, then the team with (High roller,Low roller) always goes first, and the team with (Middle roller,Middle roller) always goes second.

Sarah Sherman posted:

But, just to complicate things up a bit, the teams must alternate on turns. For example, if the two players on team one gets a 20 and a 19, and team two gets a 1 and a 2,

As I understand your rules for how teams are formed, this is impossible.

Sarah Sherman posted:

then the turns must go team one, then team two, then team one again, even though team one got both the highest numbers. I'm still fairly new when it comes to programming, so help is very much appreciated.

I think the problem you're having is likely a problem very typical of new programming students: You think you understand what you want the computer to do, but you haven't yet set it down step by step, so you don't know how to program it. You're focusing on the "little" problems of your application instead of the "big picture", which makes everything more difficult because you aren't yet sure how the parts all need to fit together.

Don't worry, it's easy to fix! For new programmers, I always suggest a top-down approach, which is a little slower than "real" programming, but will help you get used to thinking the right way. (And, by the time you are dealing with larger projects, you'll be better prepared to use a more streamlined approach.) Do this:

1) Get a notebook. Seriously. Programming is mostly about writing down ideas in a very detailed way. The programming language is just a way that happens to be something the computer can run, but most of the work you're doing should be written down in English, at least until a year or more from now when you find yourself doing it automatically in your head. Make notes to yourself constantly -- what works, what doesn't work, what problems come up in debugging and how you fixed them, critiques you get from your TA or Prof, everything. It'll help you learn more about your personal strengths and weaknesses as a programmer, and you'll never be in a situation where you're looking at some code that you wrote and you can't understand how it works, or how it fits into the whole, or how to change it to do something new. All good programmers keep notes to themselves in some form, and a paper notebook is the best way to do it for new programmers because you don't have to learn to use some software tool and it's easy to just take it out whenever you have an idea, instead of having to wait until you can get to your computer. As you become more familiar with the kinds of notes that work well for you, and you get better at intuitively seeing how a program should be structured, you'll take fewer notes and may migrate to something more powerful like issue-tracking software or a personal wiki or something, but I know many professional programmers who maintain a paper notepad for every project they work on, and keep it by their side whenever they are working.

2) Write down the largest phases of your project. You're writing a turn-based game, so those should probably be something like "Set up a new game", "Take turns playing", and "Decide who won".

3) For each phase, break it down into the next largest phases. "Set up a new game", for example, may have phases like "Decide how many teams there will be", "Decide who is on which team". Continue this refinement process, breaking down phases into smaller and smaller parts, until the instructions are specific enough that someone reading them will understand all the rules of your game. Don't break them down past where it's easy to describe each step with a single normal English sentence.

4) What you have produced is pseudocode, a formal description of your program in a language that is easily readable, but very unambiguous. You should now work out how to organize your instructions into code and begin writing it, starting from the outermost phases and gradually filling in the inner phases.

As an example of the process, I'm going to make up a simple betting game and go through the steps of describing it here:

code:
Set up the game.
  There are two players, A and B.
  Both players start with $100.
  Players each roll a die to decide who plays first.
    Player with higher roll plays first.
    If both roll the same, each rolls again.
Take turns until one player runs out of money.
  Current player rolls a die, in secret.
  Current player announces some amount of money.
    Cannot be more than what either player has.
  Opposing player may either pay half (rounded down) the amount, or accept the bet.
    If opposing player pays, then the turn is over.
    If opposing player accepts, then they roll a die, and winner takes the money.
      Opposing player rolls a die.
      Both die rolls are revealed.
      If one die is higher than the other, loser pays winner the announced price.
      If both die are the same, then the turn is over, and neither player pays.
To make this, I started with just "Set up the game" and "Take turns until one player runs out of money", then added each further layer until I couldn't easily add more detail.

I now need to check over it a little. I need to keep track of the amount of money each player has, and I also need to know who's turn it is. Those are going to be pretty important variables.

To code this, I would start from the top again:

code:
int main ( int argc, char *argv[] ) {

  setup_game( );

  do {
    take_turn( );
  } while ( /* both players have money */ );

  return 0;

}
And, gradually, I fill it in...

code:
int player_money[2];

void setup_game ( void ) {

  player_money[0] = 100;
  player_money[1] = 100;

  // roll dice to decide who starts

}

int main ( int argc, char *argv[] ) {

  setup_game( );

  do {
    take_turn( );
  } while ( player_money[0] > 0 && player_money[1] > 0 );

  return 0;

}
and then refining it...

code:
int player_money[2];
int whos_turn;

void setup_game ( void ) {

  int player_die[2];

  player_money[0] = 100;
  player_money[1] = 100;

  do {

    player_die[0] = roll_die( );
    player_die[1] = roll_die( );

    if ( player_die[0] > player_die[1] ) {
      whos_turn = 0;
    } else if ( player_die[0] < player_die[1] ) {
      whos_turn = 1;
    };

  } while ( player_die[0] != player_die[1] );

}
And then I might add...

code:
void take_turn ( void ) {

  int secret_die;
  int bet;
  int bet_accepted;

  secret_die = roll_die( );

  tell_current_player( secret_die );

  bet = get_bet_from_current_player( );

  tell_opposing_player( bet );

  bet_accepted = ask_opposing_player_to_accept( );

  if ( bet_accepted ) {
    roll_to_see_who_wins( secret_die, bet );
  } else {
    player_money[whos_turn] += bet / 2;
    player_money[whos_turn] -= bet / 2;
  };

}
And so on, until I was finished. At each step of refinement, I'm trying to add in the code for only a few small steps of my pseudocode, so that I don't get confused and everything stays organized. If I need to refer to a step that I don't want to write the code for just this second, I replace it with a comment or a call to a function I haven't yet written. These are replaced or defined one by one, until the program is finished.

Once the code is finished, then it's on to the task of debugging and potentially refactoring. (say, deciding that some variables that you made global should really be parameters, or that your functions should be broken up differently.) Unfortunately, both debugging effectively and refactoring code are skills that are best taught through exposure and practice; I can't give you easy rules for them, but I strongly suggest that while you are learning to program, find a TA or Professor or somebody who can look over your code once you get to this point and suggest refinements or talk about how they would implement it.

I hope all this helps! If you can make a more clear description of your game, I'd be happy to help you with any particular parts you can't get implemented.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Sarah Sherman posted:

I hope that is enough information about what I'm trying to do. I don't want the program to go any further, this is just so me and my friends can easily assign teams for a game we play without going through the motions of rolling actual dice.

OK, that makes this pretty easy.

Sarah Sherman posted:

The output that I'm looking for (if it was a 4 player game with teams) would simply be:
code:
Enter the number of players: 4
Is this a team game or free-for-all?
Enter T for team game, or enter F for free-for-all: T 

Player 1 rolled a 2!
Player 2 rolled a 14!
Player 3 rolled a 20!
Player 4 rolled a 7!

Team 1: Player 3 and Player 1
Team 2: Player 2 and Player 4

Order of turns is: Player 3, Player 2, Player 4, Player 1

That's a Team 1, Team 2, Team 2, Team 1 turn order; is that right? That makes this relatively simple, because we don't have to care about teams when deciding turn order...

Here's an implementation of this in C. It's all in the main function, which is terrible but saves me some typing. I tried to implement simple algorithms instead of "good" algorithms, so it does things in a pretty naive manner.

code:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ( int argc, char *argv[] ) {

  int ret;
  int players;
  int teams;

  // Prepare the random number generator by seeding with the time.
  srandom( time( NULL ) );

  // Ask how many players are involved.
  fprintf( stdout, "How many players total? " );
  ret = fscanf( stdin, "%i\n", &players );
  assert( ret == 1 );
  assert( players <= 20 ); // If there are more than 20 players, then
                           // we will never not have duplicate rolls.

  // Ask if this is a team game.
  // Teams only make sense with an even number of players greater than 2.
  if ( players > 2 && players % 2 == 0 ) {

    char yesno;

    do { 
      fprintf( stdout, "Is this a team game? (y/n) " );
      ret = fscanf( stdin, "%c\n", &yesno );
    } while ( yesno != 'y' && yesno != 'Y' && yesno != 'n' && yesno != 'N' );

    if ( yesno == 'y' || yesno == 'Y' ) {
      teams = 1;
    } else {
      teams = 0;
    };

  } else {
    teams = 0;
  };

  int die[players];

  // This die-rolling logic is a little bit complicated...
  // I'm trying to preserve exactly the "if two people have the same roll,
  // then only they reroll" behaviour.

  // First, I set each die as "not-yet-rolled", for which I use the value -1.
  for ( int i = 0; i < players; ++i )
    die[i] = -1;

  // Now, for each player, I roll a die...
  for ( int i = 0; i < players; ++i ) {

    if ( die[i] == -1 ) {
      // This player needs to roll.
      die[i] = random( ) % 20;
      fprintf( stdout, "Player %i rolled %i.\n", i + 1, die[i] + 1 );
    };

    // Check to see if this roll is the same as any other roll before it.
    for ( int j = 0; j < i; ++j ) {

      if ( die[i] == die[j] ) {
        // These players rolled the same, so they both need to reroll.
        fprintf( stdout, "Player %i has the same roll as player %i, so they both reroll.\n", i + 1, j + 1 );
        // This is probably the subtlest part of the code I've written.
        die[i] = -1;
        die[j] = -1;
        i = j - 1;
        break; // Goes back to the outer loop.
      };

    };

  };

  // Print out the order of the players.
  // This would be better done by sorting a list of the players;
  // the algorithm I have here is equivalent to a bubble sort, but I'm
  // using it because it's simple and speed probably doesn't matter too much.
  // This is marginally subtle and kind of fun to prove why it works.

  int highest_score = 20; // Die rolls are 0..19, so this is higher than any of them.

  // This is a loop over play positions.
  for ( int i = 0; i < players; ++i ) {

    int next_highest_score = -1;
    int next_player;

    // And this is a loop over players.
    for ( int j = 0; j < players; ++j ) {

      // We are searching for the player with the largest die roll that is
      // still smaller than highest_score.
      if ( die[j] < highest_score && die[j] > next_highest_score ) {
        next_highest_score = die[j];
        next_player = j;
      };

    };

    fprintf( stdout, "Position %i: Player %i\n", i + 1, next_player + 1 );

    highest_score = next_highest_score;

  };

  // Print out the teams, if we're in team play mode.
  if ( teams ) {

    // The algorithm here mangles the die array,
    // which is why I'm doing it after printing the turn order.

    // For each team, I'm going to select the players with the highest and lowest
    // rolls that haven't yet been chosen. This loop is over teams.
    for ( int i = 0; i < players / 2; ++i ) {

      int lowest_player, lowest_roll;
      int highest_player, highest_roll;

      // Out of bounds values.
      lowest_roll = 20;
      highest_roll = -1;

      // And this loop is over players.
      for ( int j = 0; j < players; ++j ) {

        // If this player hasn't yet been chosen...
        if ( die[j] != -1 ) {

          // Check if they are the highest roll we've seen so far.
          if ( die[j] > highest_roll ) {
            highest_roll = die[j];
            highest_player = j;
          };

          // Check if they are the lowest roll we've seen so far.
          if ( die[j] < lowest_roll ) {
            lowest_roll = die[j];
            lowest_player = j;
          };

        };

      };

      // Mark the two players as chosen.
      die[highest_player] = -1;
      die[lowest_player] = -1;

      fprintf( stdout, "Team %i: Player %i and Player %i\n", i + 1, highest_player + 1, lowest_player + 1 );

    };

  };

  return 0;

}

Sarah Sherman posted:

I understand now what you mean about not looking at the 'bigger picture' of the program. When I was trying to think out this program before I got to a computer, I was just focusing on the smaller parts of the program, like rolling the dice, and when I finally got to a computer realized I was stuck because I don't know how to do the other aspects of the program. I've never used the rand( ) function before, so I don't really know how to access the number it will spit out and use that to set up teams, and order of turns.

I used random(3) and srandom(3) instead of rand(3) and srand(3) by force of habit because on some systems they're higher-quality; the usage for what you're doing is the same. There are a few tricks I used: most significantly, at one point I manipulate the index of a loop I'm in, to force it to go back over earlier work. I also felt free to scribble over data that I didn't need anymore; this is how I wrote the team-selection code without storing a lot of extra data about what teams I've already made.

If you need to alternate teams in play order instead of just going by die rolls, then you need to come up with a rule for exactly how that's done, and you'll need to store the teams instead of just printing them out, as well as calculating them before the turn order and without trashing the die rolls. This might be simpler if you fix the teams so they are only in the 4-player case instead of the n-player case as I did.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Incoherence posted:

I'm not convinced this is particularly fair (you resolve ties as they happen, instead of having everyone roll then resolving ties). Not that it terribly matters for this application, but you might get around this by having everyone roll once, then making another pass through the whole loop to resolve ties, and then you might end up doing the same thing again recursively... okay, never mind, we're getting way off the scope of Sarah Sherman's problem.

I didn't want to do a separate pass, because it introduces the possibility of ties with arity greater than two and dealing with simultaneous ties, both of which somewhat complicate the logic. Although I suppose my effective ordering on the rolls is essentially cheating in that the "real world" does deal with those situations.

Of course, the correct approach is to just stick the player indices in an array and shuffle that with something like a Mersenne twister. I was more interested in trying to show how to go from a spec to code; Sarah Silverman should find a local mentor or TA or someone who can go over their code with them and point out where a more general common algorithm would be better suited for what they're doing.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Drx Capio posted:

I'd like to add that generally if you want a set of unique numbers randomly selected from another set, it's cheaper to simply sort your set of available numbers with a random metric, then just pull your 'rolls' from the front of the randomly sorted array.

Sorting with a random metric is O(n ln2 n) and potentially has problems if your sorting algorithm is stable, but you can shuffle an array in linear time with, for example, the Fisher-Yates shuffle:

code:
int nums[20];
int j;
int temp;

for ( int i = 0; i < 20; ++i ) {
  j = random( ) % (i + 1);
  temp = nums[i];
  nums[i] = nums[j];
  nums[j] = temp;
};

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Drx Capio posted:

Besides, I would probably just use random_shuffle anyway.

That uses the algorithm I posted.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Avenging Dentist posted:

Is there a way to truncate a stream at a certain offset? That is, suppose I have a file open and want to delete a line of text and shorten a file by so many bytes. I can shift the subsequent lines of text with no problem, but there'll be extra space at the end, which kind of defeats the purpose in this case.

The ftruncate(2) system call is probably what you want.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Kessel posted:

I am using the pow function from math.h in my program. What should I change to get this out of the way?

Either compile with optimizations or add "-lm" to the compiler command line so you link with the math library. You'll probably want -lm after all your source files.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Kessel posted:

Thanks! That fixed it.

Out of interest, why does this happen with the math library, but not when I include things like ctype.h?

.h files are not libraries, they are header files describing an interface. The interface belongs to a library. One library, libc, which many header files describe various interfaces for, is always linked in by default because it's nearly impossible to program without it. No other libraries are linked in by default, so you have to pass them to the compiler yourself. Header files don't have a way to tell the compiler what libraries they need; you just have to know or check the documentation for the header you're using.

libm is a weird case because many of its functions can be replaced by direct invocation of the FPU, so if you turn on optimizations in your compiler it may remove the need to link to libm.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

ruden posted:

Well, I use the word fractal loosely, basically it's imitating reflecting lines in a tube. I could try the SVG, I never thought about using that, and I know it's fairly easy to get into. Is there a limit on image sizes in SVG?

How will you be printing this once you have the image file? It might be simpler to work directly in PostScript.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender
You don't need a library. You don't need to worry about storing it in memory. If all your image is is a sequence of drawn black lines, just produce trivial PostScript output.

In your code, start off the program by outputting "%!PS" to some file so you're valid PostScript, then "72 1400 div dup scale" so you're in 1400 DPI instead of 72 DPI.

For every line from (x1,y1)->(x2,y2), output "newpath x1 y1 moveto x2 y2 lineto stroke".

At the end, output "showpage".

That's it, you're done, you've produced a PostScript file that contains your image. Save it with a .ps extension and give it to the printer.

Edit: 1400, not 1440 DPI.

ShoulderDaemon fucked around with this message at 20:18 on Apr 28, 2008

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

ruden posted:

Ok, I made the PS file of the image.

Adobe is choking because your document isn't DSC compliant and Adobe doesn't actually produce raw PostScript interpreters. GhostScript isn't inferring the correct bounding box because GhostScript is a really amazingly bad PostScript interpreter. Real printers typically know what size of paper they are using instead of having to infer it from the document being printed, and they also tend to not care about the metadata that lets them do fancy tricks like print pages out of order, but software does.

The solution is to add the DSC headers.

I think making your output look something like this should be enough:
code:
%!PS-Adobe-3.0
%%BoundingBox: 0 0 1728 17280
%%DocumentMedia: banner 1728 17280 0 () ()
%%Pages: 1
%%EndComments
%%Page: banner 1

72 1400 div dup scale
0 setlinewidth

newpath 10 10 moveto 33600 336000 lineto stroke

showpage

%%EOF
Note that you'll probably have a hell of a time getting software to display this no matter what; they have to create a multi-gigabyte raster to render to, and most software renderers are just going to choke and display a blank page at this size. If you want to test it, either make a much smaller test banner to be printed by the same printer at presumably a low enough cost that it's not a problem, or just ask the people who own the printer to verify your document. If the printer is actually a plotter, that's really easy: just ask them to do a print with no ink, and watch the pen to verify that it's drawing the correct lines. If it's not a plotter, they should either have the specialized software that can simulate a large job without crashing, or they can do something like an interrupted run where they feed it a much smaller page and verify that it's at least drawing the very end of the banner correctly.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

ruden posted:

Is that the correct dimensions for the 336020x33620 banner? I'm not too familiar with the PS headers, so I basically copied and pasted it into my Perl file. If I need to change something I would appreciate it, I don't want to mess something up from having wrong dimensions.

PostScript uses 72DPI in calculating dimensions, and doesn't really have a concept of a pixel - You specified 20 ft by 2 ft at one point, so I just did 72 * 12 * 2 by 72 * 12 * 20. If you want those exact "pixel" counts at 1400 DPI, you'll want 72 * 3620 / 1400 and 72 * 336020 / 1400, which aren't round numbers (and BoundingBox is constrained to integer values). I'd probably round up, and go with 1730 and 17282. Whoever setup the printer should be able to tell you exactly what bounding box is most appropriate.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Soldat posted:

For a programming project, I need to write a real basic interpreter for a scheme like language. All it really needs to do is be able to handle basic primitives, if statements, literals, numbers, local variable bindings..and that's probably about it. I was hoping I could download the source code for something similar as a reference point, but so far I've been unable to download anything that it isn't wayyyy too complex..does anyone know where I might be able to download a basic c++ interpreter like this?

Are you constrained to a C/C++ host language? Because Scheme is really easy to write an interpreter for, but C and C++ are really not the greatest languages for the task, and any non-trivial interpreter in them is going to be at least fairly complex.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Soldat posted:

Unfortunately I am constrained to c++. The interpreter itself will be somewhat trivial I think, everything else I've found has been way too extensive. Any other suggestions?

Well, TinyScheme is the C version I would suggest studying. The opcode evaluator uses some occasional magic because it's designed for embedded systems, but the garbage collector and handling of closures and continuations is about as straightforward as you're likely to see outside of a textbook. It's only about 5300 lines of code for a very large portion of the R5RS.

The only really tricky bits to reading it are that the author occasionally scatters his structure definitions around in the code; a program like cscope will probably help a lot. Oh, and it uses lots of conditional compilation, but if that bothers you just run it through a preprocessor step or manually remove the features you don't care about.

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?

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

vanjalolz posted:

I'm doing an assignment involving signals/semaphores/forks in POSIX/unix and I need a function that will suspend execution until a certain signal is sent. I was under the impression that the function I want is sigpause, sigwait or sigsuspend, but I can't get the fuckers to work.

Am I meant to be using a few functions together? I'm after something that will do all this atomically: enable signal X, sleep until signal X, disable signal X, return.

It's probably simplest to just use pause(2). That will wait for any signal you have a handler for; if you want to wait for a particular signal, just set a variable in that signal's handler to false, and pause in a loop as long as that variable is true.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Zaxxon posted:

here's something that has been bothering me for a while and is pretty stupid, but I wonder if there is something else I'm not thinking about.

When declaring a pointer people usually write it like this

int *Foo

this reads to me as someone declaring an int named *Foo. Why don't they write

int* Foo

this reads to me as someone declaring an int* named Foo.

I mean I've been around long enough that it doesn't throw me off but it still bugs me just the same.

Because int* foo, bar; is the same as int *foo; int bar;, not int *foo; int *bar;.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

JoeNotCharles posted:

code:
$ git checkout -f WebKit.pro
git checkout: updating paths is incompatible with switching branches/forcing
Did you intend to checkout 'WebKit.pro' which can not be resolved as commit?
What??

That link just says to use "git reset --hard HEAD", which doesn't work because it blows away changes to the index file too, and doesn't take a list of file:

code:
$ git reset --hard HEAD WebKit.pro
Cannot do partial --hard reset.
I think git checkout is what I want, but what the hell is that error message?

You want to use git checkout without the -f, as explained in the comments of that link and the error message you got.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Drx Capio posted:

What's an easy way to determine if an arbitrary program will halt? Is there a library for it?

I provide a for-pay Turing Oracle service, charged at a reasonable hourly rate. By special arrangement I can set up a web service frontend, although the latency will be quite high for nontrivial programs or when I'm asleep. I cannot guarantee to solve all halting problems, although I will allow you to specify a maximum amount of time you want me to spend working on a problem, and if I can't reach a conclusion I'll give you half off.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Lexical Unit posted:

The API is this: http://tronche.com/gui/x/xlib/window-information/XInternAtoms.html (abandon all hope ye who clicks here).

Have you considered using XCB instead of xlib? It's much nicer.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender
Short answer: you are looping 255 times, instead of once per character in the string. Consider what would happen if you had a string with 255 'a's followed by every other letter, or if you had a string (as is the case here) with less than 255 characters.

Furthermore, your indentation is mildly headache-inducing, the function calls you're making look like you're inappropriately abstracting in the wrong places, that's obviously not the code you ran to test with because that doesn't have any IO statements in it, and you're doing C string handling with C++. None of these are major problems, but you may want to ask your TA for a "perfect" solution after you hand in this assignment so you can see how they would structure the problem.

Edit: My solution:

code:
void print_unique_chars ( const char *str ) {

  // Initialize an empty set of characters found so far.
  bool found_set[256];
  for ( int i = 0; i < 256; ++i ) found_set[i] = false;

  // Loop through the passed string.
  while ( *str ) {

    // Only consider characters not in the found set so far.
    if ( ! found_set[*str] ) {

      // Add to found set.
      found_set[*str] = true;

      // Print the character.
      fputc( stdout, *str );

    };

    // Advance to next character in the passed string.
    ++str;

  };

}

ShoulderDaemon fucked around with this message at 02:33 on Aug 31, 2008

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Whilst farting I posted:

You're right, I just didn't know how to get the length of a dynamically allocated character array - everywhere I searched online said there was no way to do this if you don't know what it'll be at compile time.

Yep, can't be done. You just loop until you hit a nul character. I use the pointer type so that I can use while ( *str ) { ... ++str }, but if you want an explicit index you'd use something like for ( int i = 0; str[i]; ++i ) { ... }. If you want to find the length of a C-string at runtime, you use strlen(3). Note that all these methods only work under the assumption that this is a well-formed C-string; if you're passed something that doesn't have a terminating nul, the program will crash or have some more subtle bug.

Whilst farting I posted:

Whoa, it looked okay on my screen before I posted it :smith:

The only really terrible bit was the extra layer of indentation after charToInsert = arr[i].

Whilst farting I posted:

This is part of a class, I mentioned the function call was test.insert("The quick brown fox jumps over the lazy dog."); and that I stuck a cout statement in the if loop to see what exactly it was taking from the input sentence.

It's usually considered bad form to post code that isn't exactly the code you're testing, because if you're doing something stupid while inserting the missing debugging code, then no-one will be able to recreate the error you see, and everyone just gets irritated at eachother. In your case, it wasn't a big deal because your problem was elsewhere, but you should get in the habit of not making people guess what you're doing.

Whilst farting I posted:

I can't change the function parameters, it has to remain a character array. But otherwise, you really have helped me out a bunch. I'm very rusty on C++, so thank you for being patient with my retarded-looking code and vague questions.

My function would work with the same parameters yours works with, for what that's worth. Arrays are passed in C and C++ as the address of the first element, so you can treat them as pointers to a single element and explicitly manage the pointer arithmetic. As you're still learning, you shouldn't do this unless you're already comfortable with pointer arithmetic, but at some point during your class there should be a discussion about passing semantics and the array/pointer pseudo-equivalence.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

MEAT TREAT posted:

Ok wtf is 1["1234"] supposed to mean? Things like this really piss me off about C++. I know you can use the [] operator to move positions in memory. What I don't know is how "1234" is a valid offset. I guess you could use it's memory address as the value, but then how can you know where the compiler will place it? The other thing that bugs me is that 1 is a constant, so 1[] doesn't really make sense to me.

Please help my plebeian brain :(

1["1234"] is the same as *(1+"1234") is the same as *("1234"+1) is the same as "1234"[1] is the same as '2' is the same as 50.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

rjmccall posted:

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.

I think he's asking if you can do this:

code:
int foo;
cin >> foo;
someFunc( foo );
But without the temporary. I don't use streams enough to know the answer.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Jo posted:

Why is mmap always returning -1:

Perhaps you could print out the actual error? errno exists for a reason, you know.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Jo posted:

Ehr, yes. Right. It's errno 9.
Bad file descriptor. :what:

EDIT: It's late, I'm probably making a stupid error opening the file or something.

Thank you for your response at this ungodly hour, ShoulderDaemon.

It's probably because you have a bad file descriptor. I'm betting your open call is failing and returning -1. You should check that.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender
I got bored so I made a solution in plain C (possibly with some GNUisms). In C++, instead of using the read line+strtok approach, you'd either read a line then split it using something like stringSplit, or you'd just read exactly one token at a time from the input. You might also use a map or a vector or something instead of a big array for the table of Morse codes, but whatever.

Now I kind of want to try to golf the decoding problem.

Edit: fixed the constants table, because checking my work the first time would be the pansy way to program

ShoulderDaemon fucked around with this message at 06:16 on Nov 24, 2008

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Avenging Dentist posted:

Real men use Boost.Spirit and write an EBNF grammar to parse the morse code. :smug:

Using a tool to build your state table seems like cheating.

code:
#include <assert.h>
#include <stdio.h>

#define START 'K'
#define FIRST '('

static struct {
	char dot, dah;
} table[] =
	{ {0,  ')'},{0,  0  },{0,  0  },{0,  '.'},{0,  0  },{0,  0  },{0,  0  },{0,  0  }
	, {0,  0  },{'\'',0 },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  '-'},{0,  0  }
	, {':',0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  }
	, {0,  0  },{'B','2'},{'?','_'},{'+',0  },{'"',0  },{'@',0  },{';','!'},{0,  '('}
	, {0,  ','},{'8',0  },{'9','0'},{'e','t'},{0,  0  },{0,  0  },{0,  0  },{0,  0  }
	, {0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  }
	, {0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  }
	, {0,  0  },{'r','w'},{'6','='},{0,  'F'},{'b','x'},{'i','a'},{0,  0  },{'z','q'}
	, {'5','4'},{'s','u'},{0,  '1'},{'c','y'},{0,  'D'},{'g','o'},{'d','k'},{'I','J'}
	, {0,  'E'},{0,  0  },{'l','C'},{'h','v'},{'n','m'},{'f','A'},{0,  '3'},{'p','j'}
	, {'/',0  },{'G',0  },{'7','H'},{0,  0  },{0,  0  },{0,  0  },{0,  0  },{0,  0  } };

#define D(c)  (table[(int)(c - FIRST)])
#define DO(c) (D(c).dot)
#define DA(c) (D(c).dah)

#define ERR '#'

void decode(const char *str) {
	char at = START;
	while(*str){
		if (*str == '.') at = DO(at);
		else if (*str == '-') at = DA(at);
		else {
			if (at != START) putchar(at);
			at = START;
		};
		++str;
		if (at == 0) {
			putchar(ERR);
			while (*str && (*str == '.' || *str == '-')) ++str;
			at = START;
		};
	};
	if (at != START) putchar(at);
	putchar('\n');
}

int main(int argc, char *argv[]) {
	assert(argc==2);
	decode(argv[1]);
	return 0;
}
Breaks badly if you don't pass it valid Morse code because there is no error checking whatsoever. Edit: Got bored, added the 5 lines of error checking so it doesn't crash on invalid input.

ShoulderDaemon fucked around with this message at 04:29 on Feb 18, 2009

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

MEAT TREAT posted:

After looking the poo poo that yacc and lex spit out I don't relish the idea.

Tools tend to push out some of the worst looking state machines; it's possible to build readable state machines that aren't any slower without too much trouble. I'm not a good example of that, but I've heard about it happening from a somewhat reliable source who was probably not joking at the time.

Seriously, though, most of why mine looks terrible is because of the stupid gimmick I'm using where the index of a state maps directly to the character that should be printed if you terminate in that state. This neither saves memory nor speeds up execution, but I think it's kind of funny because it makes it almost impossible to read unless you have an ASCII table handy.

Anyway, Morse code doesn't really lend itself to a compact representation, which is sort of unfortunate because any state table is going to end up with icky holes in it. It actually gets slightly nicer if you add the latin character encodings and other extensions to the code, because they fill in some of the holes, but I didn't want to deal with those characters in C. Also, they would have made my stupid gimmick require a bunch of rows of nothing but {0 ,0 } which just looks bad. I suppose I could have filled most of those elements with random garbage because they'd never be reached, or I could store a huffman-encoded version of the table and decode it at runtime, but I'm not currently that bored.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Anunnaki posted:

How come? And what is the alternative?
There is no alternative. Clearing the screen does not make sense in this context.

Anunnaki posted:

Also, are there any unanimous rules for UVa submissions that aren't listed in each problem description? (Such as the "No system("cls")" thing.)
Your code has to be able to run on whatever (probably UNIX-derived) automated system they use for judging.

Anunnaki posted:

Edit: Also, I think the sample output on that page is wrong. Are they wrong, or am I wrong?
You are wrong. The sample output is consistent with the problem description.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

honeymustard posted:

Problem is, it seems to fill in every position with 9, rather than incrementing it. Is there an easier way of doing it that I'm missing?

The "clever" way; deriving the data from the indices.

code:
for( int i = 0; i < 3; ++i ) {
  for( int j = 0; j < 3; ++j ) {
    matrix[i][j] = 3 * i + j + 1;
  };
};
The "naive" way; using an explicit accumulator.

code:
int n = 1;
for( int i = 0; i < 3; ++i ) {
  for( int j = 0; j < 3; ++j ) {
    matrix[i][j] = n;
    ++n;
  };
};

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

hexadecimal posted:

Why do you have ; after }

Is it any different than from omitting it?

No, it's just habit from other languages which require it.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Anunnaki posted:

Is it feasible to come up with an algorithm that generates every possible permutation? Because we're talking 4.03 x 10^26 possibilities.

That's at least about as hard as incrementing an 89 bit counter through its range, so no, it's not computationally tractable.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Dijkstracula posted:

It's not the same thing - the expression he's talking about is the parameter to sizeof().

...yes? Mustach passed a[0], an expression, as the parameter to sizeof.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Gvaz posted:

Someone said "it cant resolve printf because somehow its not linking in standard c library" :(

That person is wrong. It's not working because you're trying to run the source code, instead of the program that is created when you compile it. Additionally: you're dumb, and so is that person.

The program being created is probably called a.out. Run that.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

functional posted:

I'm sure this is an old problem. What do people typically do?

If this is C, you can just do mystruct *anything = myvoidpointer; without any cast at all - C99 automatically promotes from void *.

Adbot
ADBOT LOVES YOU

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Car posted:

Using this code:

You never initialize currIndex, and I'm not clear on why you have it and i. You also never initialize numToRead or open inputPtr, so I'm assuming you're leaving out important bits of the code, without which we can't really help you effectively.

Edit: Also, -340 does not fit in a char, which is what your confusingly-named and never-allocated intArr is made of, and the modulo arithmetic works out to about the right value.

ShoulderDaemon fucked around with this message at 03:18 on Jan 24, 2009

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