Thread: getopt help

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    51

    getopt help

    Hello all,
    I tried using 'getopt' for my program(sorting) ...but always end up with a Segmentation Fault..
    input suppose to be as follows:
    ./msort -i 'input file' -o 'output file' -s 'sort type' -f 'field to be sorted'

    This is a part of my main.
    Code:
            while((c = getopt(argc, argv, "iosf:")) > 0)
            {
                    switch(c)
                    {
                            case 'i':
                                    if(sscanf(optarg, "%s", file_in) != 1)
                                            fprintf(stderr,"Input file was not provided\n");
                                    break;
    
                            case 'o':
                                    if(sscanf(optarg, "%s", file_out) != 1)
                                            fprintf(stderr,"Output file was not provided\n");
                                    break;
    
                            case 's':
                                    if(sscanf(optarg, "%c", &sort_type) != 1)
                                            fprintf(stderr,"Sort type not provided\n");
                                    break;
    
                            case 'f':
                                    if(sscanf(optarg, "%d", &field) != 1)
                                            fprintf(stderr,"Field to be sorted not provided\n");
    
                                    if(field == 2)
                                            printf("String field selected to be sorted\n");
                                    else
                                            printf("Record Number field selected to be sorted\n");
                                    break;
                    }
            }
    
            fp1 = fopen(file_in,"r");
            if(fp1 == NULL) perror("Cannot open file for reading\n");
    
            rec_count = read_records(records, fp1);
            printf("%d records read from input file\n", rec_count);
    
            records = realloc(records, (sizeof(records)*(rec_count+4)));
    
            /*Sorting starts here*/
            /*Not yet complete, but default is present already*/
            if((sort_type == 'n') && (field == 2))
            {
                    /*sort with natural mergesort - string*/
                    printf("Natural Mergesort selected\n");
            }
            else
            if((sort_type = 'n') && (field == 1))
            {
                    /*sort with natural mergesort - int*/
                    printf("Natural Mergesort selected\n");
            }
            else
            if((sort_type = 'b') && (field == 2))
            {
                    /*sort with BU mergesort - string*/
                    printf("Bottom-Up Mergesort selected\n");
                    mergesortBU(records, 0, rec_count-1, comp_string);
            }
            else
            {
                    /*sort with BU mergesort - int*/
                    printf("Bottom-Up Mergesort selected\n");
                    mergesortBU(records, 0, rec_count-1, comp_key_num);
            }
    right now, i skip the write to file part and just print it to 'stdout'
    If I use this,
    file_in = argv[1]
    to test my sorting and output, it works fine.
    But doesn't seem to be working with getopt.

    Help.

    Thx.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > if(sscanf(optarg, "%s", file_in) != 1)
    How did you declare file_in ?

    > records = realloc(records, (sizeof(records)*(rec_count+4)));
    How did you declare and initialise records?

    > if((sort_type = 'n') && (field == 1))
    Use ==
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    51
    thx for replying salem

    this are my declarations in main.

    Code:
            Record *records = malloc(sizeof(records)*MAX_NUM_RECORDS);
            char c,sort_type;
            int field;
            int rec_count, free_count;
            char *file_in;
            char *file_out;
            FILE *fp1 ,*fp2;
    also a question with 'realloc'
    Let's say i malloc a struct to be of 100structs. I only use 50.
    Then i realloc it to be 50 (the used size). What happens to the other 50 empty ones initialised. Will it return to free memory, so i don't need to free() anything?

    Thx very much

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > char *file_in;
    > char *file_out;
    Well these are not pointing at any memory, so trying to scan a string into where they point (or don't point) is just trouble.
    Make them arrays, say
    char file_in[100];

    Update the sscanf call to ensure some safety
    if(sscanf(optarg, "%99s", file_in) != 1)

    > so i don't need to free() anything?
    Only the single pointer you have at the moment.

    BTW, you should do this
    Code:
    void temp = realloc(records, (sizeof(records)*(rec_count+4)));
    if ( temp != NULL ) {
        records = temp;
    } else {
        /* realloc failed, tidy up and bail out */
        free(records);
    }
    realloc can fail, even if you're just making the block smaller.

    What's the +4 for?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    > Record *records = malloc(sizeof(records)*MAX_NUM_RECORDS);
    I think you meant
    Code:
      Record *records = malloc(sizeof(Record)*MAX_NUM_RECORDS);
    and same for realloc().

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    51

    Unhappy

    Thanks for yer help people.. I've fixed the (rec_count+4) problem ...
    Yep. it's the malloc(sizeof(Record)*MAX_NUM_RECORDS) //not sizeof(records)

    However, i still have the Segmentation Fault and i just can't figure what's so wrong with my getopt. Like i said, everything's perfect if i use argv[1] or [2] as file input/output.
    But when i include getopt, then the problem arises.

    This is my whole main func. :
    Code:
    int main(int argc, char **argv)
    {
            Record *records = malloc(sizeof(Record)*MAX_NUM_RECORDS);
            char c, sort_type;
            int field;
            int rec_count;
            char file_in[100];
            char file_out[100];
            FILE *fp1,*fp2;
    
    
            while((c = getopt(argc, argv, "iosf:")) > 0)
            {
                    switch(c)
                    {
                            case 'i':
                                if((sscanf(optarg, "%s", file_in)) != 1)
                                        fprintf(stderr,"Input file was not provided\n");
                                        break;
    
                            case 'o':
                                if((sscanf(optarg, "%s", file_out)) != 1)
                                        fprintf(stderr,"Output file was not provided\n");
                                        break;
    
                            case 's':
                                if((sscanf(optarg, "%c", &sort_type)) != 1)
                                        fprintf(stderr,"Sort type not provided\n");
                                        break;
    
                            case 'f':
                                if((sscanf(optarg, "%d", &field)) != 1)
                                        fprintf(stderr,"Field to be sorted not provided\n");
    
                                if(field == 2)
                                        printf("String field selected to be sorted\n");
                                else
                                        printf("Record Number field selected to be sorted\n");
                                        break;
                    }
            }
    
            fp1 = fopen(file_in,"r");
            if(fp1 == NULL) perror("Cannot open file for reading\n");
    
            rec_count = read_records(records, fp1);
            printf("%d records read from input file\n", rec_count);
    
    
            Record *temp = realloc(records, (sizeof(Record)*(rec_count)));
            if ( temp != NULL )
            {
                records = temp;
            }
            else
                free(records);
    
            /*Sorting starts here*/
            if((sort_type == 'n') && (field == 2))
            {
                    printf("Natural Mergesort selected\n");
            }
            else
            if((sort_type = 'n') && (field == 1))
            {
                    printf("Natural Mergesort selected\n");
            }
            else
            if((sort_type = 'b') && (field == 2))
            {
                    printf("Bottom-Up Mergesort selected\n");
                    mergesortBU(records, 0, rec_count, comp_string);
            }
            else
            {
                    printf("Bottom-Up Mergesort selected\n");
                    mergesortBU(records, 0, rec_count-1, comp_key_num);
            }
    
            print_records(records,rec_count);
    
            /*Write sorted records to a new file*/
            fp2 = fopen(file_out,"w");
            if(fp2 == NULL)
            {
                    perror("Cannot open file for writing\n");
                    return 0;
            }
            else
            write_to_file(records, fp2, rec_count);
            
    
            return 0;
    }

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    So does any particular option crash, or all of them?

    What if you only have the getopt and nothing else, does it crash then. Including getopt and making it crash is not an exclusive test of there being a problem with getopt.

    > (sort_type = 'b')
    I seem to remember mentioning this already.

    You could stand to use a few more braces, especially in all your cases. It's far from obvious as to whether those breaks actually terminate each case.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    51
    I added the extra braces around those if / else statements
    and some printf statements to verify where the the Seg Fault begins.

    This is what happens.
    Code:
    >$ ./msort -i testdata -o result -s b -f 2
    Before getopt
    Segmentation Fault
    It should enter this case
    Code:
    if((sort_type = 'b') && (field == 2))
            {
                    printf("Bottom-Up Mergesort selected\n");
                    mergesortBU(records, 0, rec_count, comp_string);
            }
    but i crashed when it hits the getopt part.

    I also tried commenting everything out so that the only thing main does is getopt.
    Same thing happens.
    Code:
    Before getopt
    Segmentation Fault

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    51
    I added the extra braces around those if / else statements, and fixed the (sort_type ==..)
    and some printf statements to verify where the the Seg Fault begins.

    This is what happens.
    Code:
    >$ ./msort -i testdata -o result -s b -f 2
    Before getopt
    Segmentation Fault
    It should enter this case
    Code:
    if((sort_type = 'b') && (field == 2))
            {
                    printf("Bottom-Up Mergesort selected\n");
                    mergesortBU(records, 0, rec_count, comp_string);
            }
    but i crashed when it hits the getopt part.

    I also tried commenting everything out so that the only thing main does is getopt.
    Same thing happens.
    Code:
    Before getopt
    Segmentation Fault

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Quote Originally Posted by robatino View Post
    > Record *records = malloc(sizeof(records)*MAX_NUM_RECORDS);
    I think you meant
    Code:
      Record *records = malloc(sizeof(Record)*MAX_NUM_RECORDS);
    and same for realloc().
    Either that or
    Code:
    Record *records = malloc(sizeof(*records)*MAX_NUM_RECORDS);
    Code:
    if((sort_type = 'b') && (field == 2))
    Have you been reading Salem's posts??? = is for assignment. == is for comparison. Use ==!
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Another case of RTFM
    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char **argv)
    {
            char c, sort_type;
            int field;
            int rec_count;
            char file_in[100];
            char file_out[100];
            FILE *fp1,*fp2;
    
            /* Everything expects a parameter */
            while((c = getopt(argc, argv, "i:o:s:f:")) > 0)
            {
                printf("Opt=%c, string=%s\n", c, optarg ); /* Add DEBUG */
                    switch(c)
                    {
                            case 'i':
                                if((sscanf(optarg, "%s", file_in)) != 1)
                                        fprintf(stderr,"Input file was not provided\n");
                                        break;
    
                            case 'o':
                                if((sscanf(optarg, "%s", file_out)) != 1)
                                        fprintf(stderr,"Output file was not provided\n");
                                        break;
    
                            case 's':
                                if((sscanf(optarg, "%c", &sort_type)) != 1)
                                        fprintf(stderr,"Sort type not provided\n");
                                        break;
    
                            case 'f':
                                if((sscanf(optarg, "%d", &field)) != 1)
                                        fprintf(stderr,"Field to be sorted not provided\n");
    
                                if(field == 2)
                                        printf("String field selected to be sorted\n");
                                else
                                        printf("Record Number field selected to be sorted\n");
                                        break;
                    }
            }
            return 0;
    }

    Without this change, I was just getting right at the start a NULL pointer (this is simple debug skills at work)
    Code:
    spc@sycamore ~
    $ ./a.exe -i hello -o world -d 2 -s t
    Opt=i, string=(null)
         17 [main] a 1112 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack)
    Segmentation fault (core dumped)
    
    $ ./a.exe -ihello -oworld -d2 -st
    Opt=i, string=(null)
         15 [main] a 2428 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack)
    Segmentation fault (core dumped)
    With a : in every place in the opt string, I get
    Code:
    $ ./a.exe -ihello -oworld -f2 -st
    Opt=i, string=hello
    Opt=o, string=world
    Opt=f, string=2
    String field selected to be sorted
    Opt=s, string=t
    
    $ ./a.exe -i hello -o world -f 2 -s t
    Opt=i, string=hello
    Opt=o, string=world
    Opt=f, string=2
    String field selected to be sorted
    Opt=s, string=t
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    51
    Oh finally!!! It works! ..I'm so glad. How can i thank u.

    This is actually my 2nd time using getopt...
    I shall keep that in mind.

    Sorry... the initialise '=' and comp '==' was my mistake of copying the old post into the new one. Actually i had that changed in my prog. already.

    Btw, can i ask what is 'RTFM'?

    Thanks guys for yer help!

  13. #13
    Lean Mean Coding Machine KONI's Avatar
    Join Date
    Mar 2007
    Location
    Luxembourg, Europe
    Posts
    444
    It's a way of saying that you should read the documentation, aka Read The ........ing Manual.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. getopt question
    By -EquinoX- in forum C Programming
    Replies: 5
    Last Post: 03-26-2009, 08:42 PM
  2. Case-insensitive getopt()
    By Ehtyar in forum C Programming
    Replies: 10
    Last Post: 11-20-2008, 03:21 AM
  3. getopt and multiple options
    By bej in forum Linux Programming
    Replies: 2
    Last Post: 11-17-2005, 04:51 PM
  4. write a loop to a file, getopt()
    By kristy in forum C Programming
    Replies: 3
    Last Post: 08-15-2003, 03:57 PM
  5. getopt() and weird output
    By kristy in forum C Programming
    Replies: 2
    Last Post: 06-28-2003, 04:39 PM