Below is code from an assignment I am working on, the parts in bold are what I have added. What I have to do is add command line argument "-c filename". Basically the code is a hashtable that when -c is used, user will enter a list of words into the table, then when finished it will take the given filename and read words from it. Any words not input into the table will be displayed.

My problem is getting the filename from the switch function back into the main function. I have tried so many different ways, each giving me various errors. Im just not sure how to set up the filename string.

I have sat staring at this thing for no idea how long, and its probably a really simple thing I have overlooked, I have tried numerous ways including strcpy in the switch function. Also the if (filename) section, Im just trying to get it to print out the filename so I can see that it is getting changed and passed up.

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <time.h>
#include <string.h>
#include "mylib.h"
#include "htable.h"

/* A boolean type which can be TRUE or FALSE */
typedef enum bool_e {FALSE, TRUE} bool_t;

/* function declarations */
static void usage(char *progname);
static void setup(int argc, char **argv, char *filename, bool_t *double_hashing,
          bool_t *entire_table, bool_t *print_stats,
          int *snapshots, int *tablesize);

/**
 *
 * Creates a hash-table and inserts words into it read from stdin.
 * Arguments on the command line alter the behaviour of the program
 * as follows:
 *  -   -d       Use double hashing (linear probing is the default)
 *  -   -e       Display entire contents of hash-table on stderr
 *  -   -n NUM   Show NUM statistics snapshots (if -p is used)
 *  -   -p       Print stats info instead of frequencies & words
 *  -   -s SIZE  Use the first prime >= SIZE as htable size
 *  -   -h       Display this message
 *
 *  By default each word and it's frequency are printed to stdout.
 *      
 *  @param argc the number of command-line arguments.
 *  @param argv an array of strings containing the command-line arguments.
 *
 *  @return EXIT_SUCCESS if the program is successful.
 */
int main(int argc,char **argv) {
  bool_t entire_table = FALSE, double_hashing = FALSE, print_stats = FALSE;
  int tablesize = 0, snapshots = 0;
  char word[256];
  char *filename = NULL;
  htable ht;
  clock_t start, stop;

  setup(argc, argv, &filename, &double_hashing, &entire_table, &print_stats,
    &snapshots, &tablesize);

   ht = htable_new(tablesize, (double_hashing) ? DOUBLE_H : LINEAR_P);
   start = clock();
   while (getword(word, sizeof word, stdin) != EOF) {
      htable_insert(ht, word);
   }
   stop = clock();
   if (entire_table) {
      htable_print_entire_table(ht, stderr);
   }
   if (filename) {
     printf("%s\n", filename);
   }
   if (print_stats) {
     htable_print_stats(ht, stdout, snapshots);
   } else {
     htable_print(ht, stdout);  /* print words and frequencies */
   }
   htable_delete(ht);

   return EXIT_SUCCESS;
}

/**
 * Prints out a usage message to stderr outlining all of the options.
 * @param prog_name the name of the program to include in usage message.
 */
static void usage(char *prog_name) {
   fprintf(stderr, "Usage: %s [OPTION]... <STDIN>\n\n%s%s", prog_name,
           "Perform various operations using a hash-table.  By default read\n"
           "words from stdin and print them with their freqencies to stdout.\n\n"
           " -d       Use double hashing (linear probing is the default)\n"
           " -e       Display entire contents of hash-table on stderr\n",
           " -n NUM   Show NUM stats snapshots (if -p is used)\n"
           " -p       Print stats info instead of frequencies & words\n"
           " -s SIZE  Use the first prime >= SIZE as htable size\n\n"
           " -h       Display this message\n\n"
           " -c FILE  Use given file to check for missing words\n\n");
}

/**
 * Handle options given on the command-line by setting a number of
 * variables appropriately.  May call usage() if incorrect arguments
 * or -h given.
 *
 * @param argc the number of command-line arguments.
 * @param argv an array of strings contain the command-line arguments.
 * @param double_hashing set to TRUE if -d given
 * @param entire_table set to TRUE if -e given
 * @param snapshots set to NUM if -n NUM given and NUM > 0 else set to 10 
 * @param print_stats set to TRUE if -p given
 * @param tablesize set to SIZE if -t SIZE given and SIZE > 0 else set to 113
 * @param filename read in file and prints words not found in table
 */
static void setup(int argc, char **argv, char *filename, bool_t *double_hashing,
          bool_t *entire_table, bool_t *print_stats,
          int *snapshots, int *tablesize) {
   const char *optstring = "c:dehpn:s:";
   char option;

   while ((option = getopt(argc, argv, optstring)) != EOF) {
      switch (option) {
      case 'c':
    *filename = optarg;
    break;
      case 'd':
         *double_hashing = TRUE;
         break;
      case 'e':
         *entire_table = TRUE;
         break;
      case 'p':
         *print_stats = TRUE;
         break;
      case 'n':
    *snapshots = atoi(optarg);
         break;
      case 's':
    *tablesize = atoi(optarg);
         break;
      case 'h':
      default:
         usage(argv[0]);
         exit(EXIT_SUCCESS);
      }
   }
   /* set default values if nothing sensible entered */
   if (*tablesize < 1) *tablesize = 113;
   if (*snapshots < 1) *snapshots = 10;
}

Recommended Answers

All 3 Replies

Simplest solutions: Make the variable global . So you want to write some thing of this sort

char *p = NULL;

void func()
{
     p= "Value returned using global variables";
}

int
main(int argc, char *argv[])
{
         func();
         printf("%s\n",p);         
         return 0;
}

Or you can return a char array from a function. Then you are writing code of this sort

char* func()
{
      char *p = (char *)malloc(sizeof(char)*10);
      p[0]='A';
      p[1]= 'B';
      p[2]= 'C';
      return p;
}

int
main(int argc, char *argv[])
{
         char* p =func();
         printf("%s\n",p);
         free(p);
                  
         return 0;
}

>> problem is getting the filename from the switch function back into the main

In order to do that, you need to pass in the address of the pointer (filename) that you will be setting inside this setup() function. C passes arguments by value, i.e. generally arguments passed to a function are copies of the original ones. It's a basic concept you need to wrap your head around.

Maybe you'll understand better if you run the below code.

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>

static void setup(int, char **, char **);

int main(int argc, char ** argv)
{
    /* Simulate arguments to the program ... */
    char * local_argv[] = { "prog.exe", "-f", "foobar", "-c", "file.txt", NULL };

    /* Number of them, excluding the terminating NULL */
    int local_argc = sizeof(local_argv)/sizeof(*local_argv) - 1;

    char *filename = NULL;

    /* Pass in the address of the 'filename' pointer ... */
    setup(local_argc, local_argv, &filename);

    /* Did we get it? */
    if(filename)
        printf("filename [%s]\n", filename);

    return EXIT_SUCCESS;
}

static void setup(int argc, char **argv, char ** arg_filename)
{
    /* Only recognize c and f */
    const char *optstring = "c:f:";
    char option;

    while ((option = getopt(argc, argv, optstring)) != EOF)
    {
        switch (option)
        {
        case 'c':
            /* This modifies the 'filename' pointer inside main() */
            *arg_filename = optarg;
            break;
        default:
            printf("skipping [%c] [%s]\n", option, optarg);
            break;
        }
    }
}

P.S. You could use the Preview Post button to see that you've e.g. gotten the CODE tags right.

I apologize for missing the back slash in my code tag. As for my topic, Thanks for your help, I used abhimanipal's first explanation to make my variable global. I will check out the third piece of code to help get my head around what gets passed where. Thanks again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.