Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie
Hi there,
There is an issue with role permissions that is being worked on at the moment.
If you are having trouble with access or permissions on regional forums please post here to get access: https://www.boards.ie/discussion/2058365403/you-do-not-have-permission-for-that#latest

C GTK simple problem

  • 01-02-2009 5:48pm
    #1
    Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭


    hey,

    i have this simple gtk program that consists of a gtk spin button and a button.

    what i'm trying to do is display a pop up dialog window with the value of spin button when the button is clicked.

    here's what i got so far.
       //connect the button to the button_clicked function
       g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), spinner);
    
    my button_clicked() function
    void button_clicked(GtkWidget *widget, gpointer data)
    {
    
       //get the value from the spinner passed to the button_clicked function
    
       gint value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
    
    
       //quickmessage takes a gchar* pointer and creates a dialog box
       quick_message();
    
    }
    

    void quick_message (gchar *message)
    {
       GtkWidget *dialog, *label, *content_area;
    
       /* Create the widgets */
    
       dialog = gtk_dialog_new_with_buttons ("Message", GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);
    
       content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
    
       label = gtk_label_new (message);
    
       /* Ensure that the dialog box is destroyed when the user responds. */
    
       g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
    
       /* Add the label, and show everything we've added to the dialog. */
    
       gtk_container_add (GTK_CONTAINER (content_area), label);
    
       gtk_widget_show_all (dialog);
    
    }
    

    now i know i have to gint value to a gchar but i can't find any ways to do it.


Comments

  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    Well I'm guessing gint is just a typedef of int and gchar * is a typedef of char.

    Why not try:

    #include <string.h>
    #include <stdlib.h>

    gchar charoutput[10]; //big enough to hold integer length
    gint gvalue; // your obtained gintvalue

    strcpy(charoutput,itoa((int)gvalue));

    Hav'nt tested or anything. Worth a try.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    cheers for that, i got it working.

    stupidily enough i forgot that GtkWiget* widget is referring to the actual widget the event is connected to in this case the button, so this line

    gint value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));

    was failing, cause widget refered to the button.

    fix it by doing this if anyone is interested.
    void button_clicked(GtkWidget* widget, gpointer spinner)
    {
        gchar* buff;
        char output[10];
        int value;
    
        value = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(spinner) );
    
        sprintf(output, "%d", fig);
    
        buff = (gchar*)output;
    
        quick_message(buff);
    
    

    it's always the simplest things that cause the most hair loss isn't it? :D


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    Ah good stuff, good luck with the project.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    cheers, you too.

    i'm back again with another problem.

    i need to get a file name from a file selector that i have.

    according to http://library.gnome.org/devel/gtk/stable/GtkFileSelection.html#gtk-file-selection-get-filename the get_filename() function should not be used in newly written code. i've tried searching the web for the new way to do this but have come up empty handed.
    void go_clicked_a(GtkWidget* widget, gpointer fileselector)
    {
            GtkWidget *file_selector = GTK_WIDGET (fileselector);
    	const gchar* filename;
    
    	filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector));
    
    	g_print("%s", filename);
    }
    

    here's the error that the terminal spits out.
    (main1:6930): Gtk-CRITICAL **: gtk_file_selection_get_filename: assertion `GTK_IS_FILE_SELECTION (filesel)' failed
    


  • Closed Accounts Posts: 7 silliussodus


    The error your seeing is an assertion error by Gtk. It's checking at runtime that the object you passed to it is a genuine GtkFileSelector. Seems like it's a widget alright because the GTK_WIDGET macro didn't spit out an error but it's not a GtkFileSelector, so some other widget.

    How did you set up the callback? Is it connected to a callback in your GtkFileSelector widget? If so, the first argument to your callback function is your GtkFileSelector widget "widget":
    go_clicked_a(GtkWidget* widget, gpointer fileselector)
    Try passing that as the argument to the get_filename() function.




    The function gtk_file_selector_get_filename() should not be used in new code because it is deprecated along with the GtkFileSelector widget. So you shouldn't be using that widget at all for new code. See the top of the doc page for more info. The replacement for GtkFileSelector is GtkFileChooser which is more user friendly than the old one. Your code will still work with the older GtkFileSelector though if you must use it.

    Hope this helps.


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    thanks, that worked.

    now for a totally unrelated problem, but still with GTK.

    i want a window to contain a vbox with two elements in it. a button and a drawing area.

    i want to create a function that will draw various shapes on the drawing area once the button has been clicked but i'm having problems getting just one shape drawn.

    here's what i've got so far.

    [php]
    #include <cairo.h>
    #include <gtk/gtk.h>

    //declare widgets.
    GtkWidget *window;
    GtkWidget *darea;
    GtkWidget *button;
    GtkWidget *vbox;


    //function declaration
    void drawSB(GtkWidget *widget, gpointer darea);


    int main(int argc, char *argv[])
    {
    //initialise gtk
    gtk_init(&argc, &argv);


    //create the window
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 680, 480);

    //create and show button
    button = gtk_button_new_with_label("Go!");
    gtk_widget_show(button);

    //create vertical box
    vbox = gtk_vbox_new(FALSE,0);

    //stick the button in the box
    gtk_box_pack_start(GTK_BOX(vbox),button, FALSE, TRUE, 0);


    //link the callback function to clicked event to the button, passing drawing area as well.
    g_signal_connect(button, "clicked", G_CALLBACK(drawSB), darea);

    //default destroy function
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);


    //stick the drawing arey in the box and show the box.
    gtk_box_pack_start(GTK_BOX(vbox),darea, TRUE, TRUE, 0);
    gtk_widget_show(vbox);

    //add box to the window.
    gtk_container_add(GTK_CONTAINER(window), vbox);

    //show window and run gtk main.
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
    }

    //function the draw a simple rectangle.
    void drawSB(GtkWidget *widget, gpointer darea)
    {
    darea = gtk_drawing_area_new();

    cairo_t *cr;
    cr = gdk_cairo_create(GDK_DRAWABLE(darea));

    cairo_set_source_rgb(cr, 0.1, 0, 0);

    cairo_rectangle(cr, 30, 30, 100, 30);
    cairo_set_line_width(cr, 2);
    cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
    cairo_stroke(cr);

    cairo_destroy(cr);
    }
    [/php]

    the window and button show up fine. here's the error

    (test:10932): Gdk-CRITICAL **: gdk_cairo_create: assertion `GDK_IS_DRAWABLE (drawable)' failed
    Segmentation fault


    i based what i have above loosly on the last tutorial on this page http://zetcode.com/tutorials/cairographicstutorial/basicdrawing/


  • Closed Accounts Posts: 7 silliussodus


    First off, you should not be declaring your widget pointers as global variables.
    You should declare them in main and pass them as arguements to your callback functions.
    There is one obvious problem that I see with darea. You try to pack the darea widget into your vbox before darea has even been created:

    //stick the drawing arey in the box and show the box.
    gtk_box_pack_start(GTK_BOX(vbox),darea, TRUE, TRUE, 0);


    You need to create the drawable (darea) before packing it into the vbox.
    Also, I'm not sure exactly what you want to do but you are creating a new drawable in your callback function each time the button is pressed, and not packing it into the vbox. You should move that gdk_drawing_area_new() function up into the main() function. You will also fix a memory leak by moving it as you won't be creating a new drawable area every time the button is clicked.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    basically what i want to do in a nutshell is to have a window that will look like this

    72480.png

    and then when the button is clicked

    72481.png

    in the above screen shots the area below the "Go!" button is a drawing area.

    thanks silliussodus, i'm stilling trying to re-learn and refresh what i know with C (only very basics no industry experience).


  • Closed Accounts Posts: 7 silliussodus


    I fixed it up for you to help you along a bit. GtkDrawingArea does not inherit from GdkDrawable (see the docs : "Object Hierarchy" for each widget) so you need something that inherits from GdkWindow. Luckily every GtkWidget does so you can use any GtkWidget or object derived from it and use (widget->window) to access it's GdkWindow. I substituted a GtkHbox in place of the GtkDrawingArea you used.
    Crude but works ;)

    #include <cairo.h>
    #include <gtk/gtk.h>
    
    //function declaration
    void drawSB(GtkWidget *widget, gpointer darea);
    
    
    int main(int argc, char *argv[])
    {
      /* declare widgets. */
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *vbox;  
      GtkWidget *darea;
    
      //initialise gtk
      gtk_init(&argc, &argv);
    
      //create the window
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 680, 480); 
    
      //create and show button
      button = gtk_button_new_with_label("Go!");
      gtk_widget_show(button);
    
      //create vertical box
      vbox = gtk_vbox_new(FALSE,0);
     
      //stick the button in the box
      gtk_box_pack_start(GTK_BOX(vbox),button, FALSE, TRUE, 0);
      
      //default destroy function
      g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    
      
      /*
       * Create and stick the drawing area in the box and show the box.
       * darea needs to inherit from GdkDrawable so any GtkWidget
       * will do.
       */
      darea = gtk_hbox_new(FALSE, 0);  
      gtk_box_pack_start(GTK_BOX(vbox),darea, TRUE, TRUE, 0);
      gtk_widget_show(vbox);
    
      //link the callback function to clicked event to the button, passing drawing area as well.  
      g_signal_connect(button, "clicked", G_CALLBACK(drawSB), darea);
    
      //add box to the window.
      gtk_container_add(GTK_CONTAINER(window), vbox);
    
      //show window and run gtk main.
      gtk_widget_show_all(window);
      gtk_main();
    
      return 0;
    }
    
    //function the draw a simple rectangle.
    void drawSB(GtkWidget *widget, gpointer darea)
    {
      GtkWidget *boxwidget;
      g_return_if_fail(GTK_IS_WIDGET(darea));
    
      boxwidget = GTK_WIDGET(darea);
      cairo_t *cr;
      cr = gdk_cairo_create(GDK_DRAWABLE(boxwidget->window));
    
      cairo_set_source_rgb(cr, 0.1, 0, 0);
    
      cairo_rectangle(cr, 30, 30, 100, 30);
      cairo_set_line_width(cr, 2);
      cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); 
      cairo_stroke(cr);
    
      cairo_destroy(cr);
    }  
    


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    dude you're a genius, thanks so much.

    it's a bit of a long winded way to draw something on the screen but at least it works that's the main thing :)


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    another day another problem.

    i have a function that will return a gchar* of a random number so that i can use with cairo to create a piece of text using the cairo_set_text() function.


    here's the function:
    //function to return a string of a random number.
    gchar* gen_random()
    {
    	int n; 
            n = rand()%1000;
    	
    	char text[10];
    	sprintf(text, "%d", n);
    
    	gchar* textreturn;
    	textreturn = (gchar*)text;
    
    	printf("in gen_random function: %s\n", text);
    
    	return text;	
    }
    

    and where i'm trying to use it.
      for(i = 35 ; i <= 195 ; i += 40)
      {
     	cairo_move_to(cr, i, 80);
      
            //create a gchar* var to hold random number string.
    	gchar* text;
    	text = gen_random();
    
           //print it out.
    	g_print("outside gen_random function: %s\n", text);
    
            //show it on screen.
    	cairo_show_text(cr, text);
      }
    

    i out put in the function and in the for loop what is being returned by the gen_random function and what the contents of the variable is after text = gen_random(); line.

    here's what i get.
    in gen_random function: 183
    outside gen_random function: &#65533;&#65533;,&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;0&#65533;;\	H&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;
    in gen_random function: 541
    outside gen_random function: 541
    in gen_random function: 764
    outside gen_random function: 764
    in gen_random function: 19
    outside gen_random function: 19
    in gen_random function: 832
    outside gen_random function: 832
    

    i'm assuming that because of the random characters printed in the first iteration of the loop that it is a pointer issue?

    it's strange as i've done something similar in other parts of my program and haven't had any errors.

    cairo_show_text(cr, text); line does not get executed, or it does but has empty strings in text but i doubt that due to the print out of the string before this line.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    another question for ya's

    i have a int value that is taken from a spin button like so

    int spin_value;
    spin_value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinbutton) );

    and if i g_print(spin_value); i get whatever value in the box, which is all well and good.

    now what i want to do is to create x amount of rectangles in a straight line (along the x axis (left to right)).

    what i want is something like in this picture

    72815.png

    the above was created using the following code:
    int spin_value;
    spin_value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinbutton) );
    
    //values for the rectangle.
    gint* xy_wh = g_new(gint, 4);
    	xy_wh[0] = 30;
    	xy_wh[1] = 60;
    	xy_wh[2] = 40;
    	xy_wh[3] = 30;
    	
    	int i;
            //start at 30        // number of boxes * 60      // i + width of rect
    	for(i = xy_wh[0] ; i <= spin_value*xy_wh[1]; i+=xy_wh[2])
    	{
    		cairo_rectangle(cr, i, xy_wh[1], xy_wh[2], xy_wh[3]);
    		cairo_set_source_rgb(cr, 255.0/255, 0.0/255, 0.0/255);
    		cairo_stroke(cr);		
    	}
    

    when the value of the spin button is:

    1 i get 1 box
    2 i get 3 boxes
    3 i get 4 boxes
    4 i get 6 boxes
    and so on...

    i had worked this out on paper and it seems right but it just doesn't work correctly. anyone have any ideas?


  • Registered Users, Registered Users 2 Posts: 2,082 ✭✭✭Tobias Greeshman


    I don't have a gtk build environment to test this, but:
    for(i = xy_wh[0] ; i <= spin_value*xy_wh[1]; i+=xy_wh[2])
    

    I think the problem is "i <= spin_value*xy_wh[1]" in the loop guard. So you are testing for a value greater than the width (the y-value of the rectangle).

    From my understanding of gui rectangles in gtk are:
    0 x pos
    1 y pos
    2 width
    3 height

    So the loop guard should be "i < spin_value * xy_wh[2]"

    The only reason it works the 1st time is:
    1st iteration
    for (i = 30; i <= 1 * 60; i += 40) { ... } // does 1 iteration as the 2nd time you get 70
    for (i = 30; i <= 2 * 60; i += 40) { ... } // does 3 iteration as the 3rd time i just happens to be 120


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    thanks dude, you're a legend.

    i have to admit that the for loop there is the most advanced loop i've written in C.

    in college all we were taught was for(i = 0 ; i < some_var ; i++) or i -- :P

    when i worked it out on paper i originally had the guard using xy_wh[2] but i must have made a typo when coding it.

    Once again cheers.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    ya's are gonna hate me for this but i'm stuck again.

    i want to be able to sort the rectangles in groups of fours.

    eg if the user selected 7 in the spin button, it would look like this:

    72927.png

    and if it was 9 it would be 2 rows of 4, and one box on it's own on a third row.

    this is what i have
    for(i = xy_wh[0] ; i < spin_value*xy_wh[2]; i+=xy_wh[2])
    {
    
    			cairo_rectangle(cr, i, xy_wh[1], xy_wh[2], xy_wh[3]);
    			cairo_set_source_rgb(cr, 255.0/255, 0.0/255, 0.0/255);
    			cairo_stroke(cr);			
    }
    

    this will create as many boxes as the spin value on one row.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    i hate bumping this guys, but i haven't gotten anywhere on this in the last couple of days.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    sorry for dragging this back up again, but i might as well reuse the thread than create a new one.

    ok i'm having an odd problem with a function of mine ( create_blocks() ) the function basically assigns values to a global structure that i have created.

    now when i call the function in another function (in function draw() ) which i'm doing now the numbers that are generated are random, but i now need to call create_blocks() in my main function.

    here's the function.
    void create_blocks()
    {
        int i;    
        int b[BLOCKS];
    
        gint* xy_wh = g_new(gint, 4);
        xy_wh[0] = 30; // x pos
        xy_wh[1] = 60; // y pos
        xy_wh[2] = 40; // width
        xy_wh[3] = 30; // height
    
        //create an array of random numbers
        //these will be used for the num part of the structure.
        for(i = 0 ; i < BLOCKS; i++)
        {
            b[i] = gen_random();
        }
    
        //sort the numbers as i need the list sorted
        //before creating the structure.
        quicksort(b, 0, BLOCKS);    
    
        /*populate the block structures */
        for(i = 0 ; i < BLOCKS ; i++)
        {
            blocks[i].x = xy_wh[0];
            blocks[i].y = xy_wh[1];
            blocks[i].w = xy_wh[2];
            blocks[i].h = xy_wh[3];
            blocks[i].num = b[i];
            blocks[i].colour = "green";
            
            g_print("block %d is... x:%d y:%d w:%d h:%d num:%d col: %s\n", i, blocks[i].x, blocks[i].y, blocks[i].w, blocks[i].h, blocks[i].num, blocks[i].colour);
    
            /* increase the x pos by the width of a block. */    
            xy_wh[0] += xy_wh[2];
            
            /* to only print out 5 blocks in a row, reset the x position
             * and increase the y position to move further down the screen.
             */
            if( (i+1) % 5 == 0)
            {                    
                xy_wh[0] = 30;
                xy_wh[1] += 70;
            }
        }
    }
    
    and when i call that from main i get this output every time without fail.
    block 0 is... x:30 y:60 w:40 h:30 num:11 col: green
    block 1 is... x:70 y:60 w:40 h:30 num:12 col: green
    block 2 is... x:110 y:60 w:40 h:30 num:13 col: green
    block 3 is... x:150 y:60 w:40 h:30 num:13 col: green
    block 4 is... x:190 y:60 w:40 h:30 num:14 col: green
    block 5 is... x:30 y:130 w:40 h:30 num:16 col: green
    block 6 is... x:70 y:130 w:40 h:30 num:17 col: green
    block 7 is... x:110 y:130 w:40 h:30 num:21 col: green
    block 8 is... x:150 y:130 w:40 h:30 num:23 col: green
    block 9 is... x:190 y:130 w:40 h:30 num:30 col: green
    block 10 is... x:30 y:200 w:40 h:30 num:35 col: green
    block 11 is... x:70 y:200 w:40 h:30 num:39 col: green
    block 12 is... x:110 y:200 w:40 h:30 num:43 col: green
    block 13 is... x:150 y:200 w:40 h:30 num:47 col: green
    block 14 is... x:190 y:200 w:40 h:30 num:49 col: green
    block 15 is... x:30 y:270 w:40 h:30 num:54 col: green
    block 16 is... x:70 y:270 w:40 h:30 num:56 col: green
    block 17 is... x:110 y:270 w:40 h:30 num:63 col: green
    block 18 is... x:150 y:270 w:40 h:30 num:64 col: green
    block 19 is... x:190 y:270 w:40 h:30 num:70 col: green
    block 20 is... x:30 y:340 w:40 h:30 num:74 col: green
    block 21 is... x:70 y:340 w:40 h:30 num:74 col: green
    block 22 is... x:110 y:340 w:40 h:30 num:90 col: green
    block 23 is... x:150 y:340 w:40 h:30 num:92 col: green
    block 24 is... x:190 y:340 w:40 h:30 num:95 col: green
    
    now if i call it from a function that's tied to a button click (just a simple create button) i get this as the ouput.
    block 0 is... x:30 y:60 w:40 h:30 num:14 col: green
    block 1 is... x:70 y:60 w:40 h:30 num:17 col: green
    block 2 is... x:110 y:60 w:40 h:30 num:17 col: green
    block 3 is... x:150 y:60 w:40 h:30 num:18 col: green
    block 4 is... x:190 y:60 w:40 h:30 num:21 col: green
    block 5 is... x:30 y:130 w:40 h:30 num:21 col: green
    block 6 is... x:70 y:130 w:40 h:30 num:30 col: green
    block 7 is... x:110 y:130 w:40 h:30 num:31 col: green
    block 8 is... x:150 y:130 w:40 h:30 num:31 col: green
    block 9 is... x:190 y:130 w:40 h:30 num:32 col: green
    block 10 is... x:30 y:200 w:40 h:30 num:36 col: green
    block 11 is... x:70 y:200 w:40 h:30 num:37 col: green
    block 12 is... x:110 y:200 w:40 h:30 num:42 col: green
    block 13 is... x:150 y:200 w:40 h:30 num:43 col: green
    block 14 is... x:190 y:200 w:40 h:30 num:45 col: green
    block 15 is... x:30 y:270 w:40 h:30 num:46 col: green
    block 16 is... x:70 y:270 w:40 h:30 num:56 col: green
    block 17 is... x:110 y:270 w:40 h:30 num:62 col: green
    block 18 is... x:150 y:270 w:40 h:30 num:75 col: green
    block 19 is... x:190 y:270 w:40 h:30 num:83 col: green
    block 20 is... x:30 y:340 w:40 h:30 num:84 col: green
    block 21 is... x:70 y:340 w:40 h:30 num:85 col: green
    block 22 is... x:110 y:340 w:40 h:30 num:85 col: green
    block 23 is... x:150 y:340 w:40 h:30 num:85 col: green
    block 24 is... x:190 y:340 w:40 h:30 num:98 col: green
    
    ie the num variable is doing creating numbers randomly and the way i want it to do it.

    anyone have any idea why it would be different in main? could it have something to do with the gtk_main() function which sleeps and waits for events to occur?


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    Not sure what you mean here but is it, that calling from the main isn't generating the random numbers where as when not in main it does?


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    yeh when i call it from main() i get the same set of random numbers every time i run the program.

    if i call it from another function say X and call X in main i get random numbers generated.

    it's a complete noodle scratcher.


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    Even when you re run the program? or is it just once you do it once in main and then call again in main, it has the same values.


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    i call it once in main, and return 0;

    i isolated the code, and stuck it into a non gtk program and i still have the same problem.
    so everytime i re-run the program i still get the same numbers.


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    What's the contents of gen_random()

    By the way I don't see a global structure in there. You are defining int b[BLOCKS] so it only has local scope in that function so gone once you exit again. Which is the global structure?


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    sorry i should have given a bit more relevant detail.

    here's gen_random()
    int gen_random()
    {
        //(rand()%(maximum-minimum))+minimum
        int n; 
            n = (rand()%(100-4))+4;
        return n;
    }
    

    here's the whole program
    #include <cairo.h>
    #include <gtk/gtk.h>
    
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    //global params
    #define SPIN_MIN     0
    #define SPIN_MAX    BLOCKS
    #define SPIN_INC     1
    
    #define DISKSIZE    100
    #define BLOCKSIZE     4
    #define BLOCKS         DISKSIZE / BLOCKSIZE
    
    struct block
    {
        int x;
        int y;
        int w;
        int h;
        int num;
        char* colour;
    };
    
    struct block blocks[BLOCKS];
    
    void create_blocks();
    
    int gen_random();
    void quicksort( int a[], int l, int r);
    int partition( int a[], int l, int r);
    
    int main(int argc, char *argv[])
    {
    
        create_blocks();
    
        return 0;
    }
    
    void create_blocks()
    {
        int i;   
        int b[BLOCKS];
    
        int xy_wh[4] = {30,60,40,30}; //x,y,w,h
       
        //create an array of random numbers
        //these will be used for the num part of the structure.
        for(i = 0 ; i < BLOCKS; i++)
        {
            b[i] = gen_random();
        }
    
        //sort the numbers as i need the list sorted
        //before creating the structure.
        quicksort(b, 0, BLOCKS);   
    
        /*populate the global block structures */
        for(i = 0 ; i < BLOCKS ; i++)
        {
            blocks[i].x = xy_wh[0];
            blocks[i].y = xy_wh[1];
            blocks[i].w = xy_wh[2];
            blocks[i].h = xy_wh[3];
            blocks[i].num = b[i];
            blocks[i].colour = "green";
           
            g_print("block %d is... x:%d y:%d w:%d h:%d num:%d col: %s\n", i, blocks[i].x, blocks[i].y, blocks[i].w, blocks[i].h, blocks[i].num, blocks[i].colour);
    
            /* increase the x pos by the width of a block. */   
            xy_wh[0] += xy_wh[2];
           
            /* to only print out 5 blocks in a row, reset the x position
             * and increase the y position to move further down the screen.
             */
            if( (i+1) % 5 == 0)
            {                   
                xy_wh[0] = 30;
                xy_wh[1] += 70;
            }
        }
    }
    
    
    int gen_random()
    {
        //(rand()%(maximum-minimum))+minimum
        int n;
        n = (rand()%(100-4))+4;
        return n;
    }
    
    
    void quicksort( int a[], int l, int r)
    {
        int j;
    
        if(l < r)
           {
            // divide and conquer
            j = partition( a, l, r);
            quicksort( a, l, j-1);
            quicksort( a, j+1, r);
           }
       
    }
    
    int partition( int a[], int l, int r)
    {
        int pivot, i, j, t;
        pivot = a[l];
        i = l; j = r+1;
           
        while(1)
        {
            do ++i; while(a[i] <= pivot && i <= r);
               do --j; while( a[j] > pivot );
               if( i >= j ) break;
               t = a[i]; a[i] = a[j]; a[j] = t;
        }
       
        t = a[l]; a[l] = a[j]; a[j] = t;
        return j;
    }
    
    


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    You might want to seed the generator first:
    int gen_random()
    {
        //(rand()%(maximum-minimum))+minimum
        srand(time(0));
        int n; 
            n = (rand()%(100-4))+4;
        return n;
    }
    

    Think you may require time.h in your #includes.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    when i seed it, i get one random number, but then every other random number is the same number as the first one.


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    Oh yeah that makes sense. You must place srand() outside of the random function before:
     for(i = 0 ; i < BLOCKS; i++)
        {
            b[i] = gen_random();
        }
    


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    Webmonkey wrote: »
    Oh yeah that makes sense. You must place srand() outside of the random function before:
     for(i = 0 ; i < BLOCKS; i++)
        {
            b[i] = gen_random();
        }
    

    done this
     for(i = 0 ; i < BLOCKS; i++)
        {
            srand(time(0));
            b[i] = gen_random();
        }
    
    and still get the same thing happening.


  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    No you have to place it before the for loop:
    srand(time(0));
     for(i = 0 ; i < BLOCKS; i++)
        {
            b[i] = gen_random();
        }
    

    Otherwise you will be seeding it with the same value, the time and since it occurs so quick, the time hasn't changed so same seed every time and you end up with same number.

    Code above should work however, make sure the time has changed before using srand again.


  • Registered Users, Registered Users 2 Posts: 26,584 ✭✭✭✭Creamy Goodness


    ahh of course, sorry i ain't with it today, heavy night last night :).

    that worked perfectly i owe ya a pint if ya ever head to a boards beers :)


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 9,579 ✭✭✭Webmonkey


    Wish I was having heavy nights haha, no probs. Good luck with rest of it.


Advertisement