Thread: Passing my array to function

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    10

    Passing my array to function

    I am having a problem where I do not understand the syntax on how to pass my array to a function and then access each argument. As it is now, while my array is in main, I can print each argument like:
    Code:
    printf("%s\n", args[0]);
    printf("%s\n", args[1]);
    etc...
    However when I try to access it like above when I try to pass the args array to a function, I get a segmentation fault, I can only print the first element using:
    Code:
    printf("%s\n", args)
    Could somebody please tell me if I'm passing the array incorrectly to the translate function and then subsequent functions, or how to acces each element beyond the first one.

    Code:
    void translate(char *input);
    void list();
    void changedir(char *list);
    void lsdir(char *list);
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    main()
    {
      char *cptr, *csh;
      char buffer[256];
      char **args = NULL;
      int nargs = 0;
    
    
      printf("sh%% ");
      cptr = fgets(buffer, 256, stdin);
      csh = strtok(buffer, " ,\n");
      
      while(strcmp(csh, "bye") != 0)
        {     
          while(csh != NULL)
    	{
    	  args = realloc(args, sizeof(char *)*(nargs + 1));
    	  args[nargs] = malloc(strlen(csh) + 1);
    	  strcpy(args[nargs], csh);
    	  nargs++;
    
    	  csh = strtok(NULL, " ,\n");
    	}
     
          
          translate(*args);
          
          nargs = 0;
          printf("sh%% ");
          cptr = fgets(buffer, 256, stdin);
          csh = strtok(buffer, " ,\n");
        }
    }
    
    
    void translate(char *input)
    {/*This function translates what command is entered and calls
      *appropriate function to execute command
      */
      
    if(strcmp(input, "?") == 0)
        {
          list();
        }
     else if(strcmp(input, "cd") == 0)
       {
         changedir(input);
       }
     else if(strcmp(input, "ls") == 0)
       {
         lsdir(input);
       }
     else return; 
    }
    
    
    void list()
    {/*This function prints a list of all available commands when
      *? is entered
      */
      
      printf("\n***List of Available Commands***\n");
      printf("?   - Displays this message\n");
      printf("bye - Exits UNIX shell\n");
      printf("cd  - changes current directory\n");
      printf("ls  - lists files in current directory\n");
      printf("\n");
    }
    	 
     
    void changedir(char *input)
    {
    }
    
    void lsdir(char *input)
    {
      int pid;
      int status = 0;
    
      pid = fork();
      
      if(pid == -1)
        printf("error!!!\n");
    
      else if(pid == 0)
        {
          execvp(list, list);
          exit(1);
        }
      else if(pid > 0)
        {
          waitpid(pid, &status, 0);
        }
    
      printf("%d\n", pid);
    }

  2. #2
    Passing functions utilize the unary operator “&”. To do this properly, you would send the address of a single row of your two-dimensional pointer:
    Code:
    translate(&args[n]);
    Instead of:
    Code:
    translate(*args);
    *args will result in an error as it may already since args is a char **, and you would have to send the memory address of args[] to translate since it only recognizes a single string, not multi-dimensional.


    char **args is in the same dimension as:
    Code:
    int myValue[2][3] = { {5, -3, 0}, {10, 17, -25} };
    Which consists of rows and columns, instead of just a single row and column. To get a better look, this initialization can be viewed as:
    Code:
    Rows/Columns	Column 0	Column 1	Column 2
    Row 0		5		-3		0
    Row 1		10		17		-25
    It is unlikely your function translate() will take all the rows and n amount of columns by sending it to a single char * called input. That's why sending the memory address of args[] is beneficial. args[] already holds a single row and column per array index.

    On further note, the unary operator “&” gives the memory address of an existing object. This assigns the address of one variable and “points to” or “passes to” another.

    I can further expound if neccessary.

    Edit: You many not need to send the memory address of args[n] to translate() if not needed.


    - Stack Overflow
    Last edited by Stack Overflow; 09-15-2004 at 11:28 AM.
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  3. #3
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I'm afraid I must disagree.
    Code:
    #include <stdio.h>
    
    void argtest( char * arg )
    {
            printf("arg is %s\n", arg );
    }
    
    int main( void )
    {
            char **args;
            char *s[] = { "Hello", "World", "!", 0 };
            args = s;
            while( *args )
            {
                    argtest( *args++ );
            }
            return 0;
    }
    /*
    arg is Hello
    arg is World
    arg is !
    */
    Dereferencing a pointer to a pointer to a type, gives you a pointer to a type, which is exactly what the function calls for.

    Quzah.
    Hope is the first step on the road to disappointment.

  4. #4
    Registered User
    Join Date
    Sep 2004
    Posts
    10
    Ok I understand how u are printing out each element out a time by passing one by one. How could I pass the whole thing to the function so that I could print it out like this:
    Code:
    printf("%s\n", args[0]);
    printf("%s\n", args[1]);
    printf("%s\n", args[2]);
    etc...
    I hope that makes sense.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    How do you think you'd past a char ** to a function?
    If you can pass a char * to this prototype:
    Code:
    void foo( char * );
    Then what would you need for a char **? Take a second and think about it. It's not hard.

    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Sep 2004
    Posts
    10
    Ok I figure if I want to pass **args to translate I would do it like this:
    Code:
    translate(**args);
    with this prototype:
    Code:
    void  translate(char **input);
    but I get an error:
    Code:
    project1a.c:42: warning: passing arg 1 of `translate' makes pointer from integer without a cast

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Close, but you're passing it wrong.

    Q) How do you pass a character pointer to a function that wants one?
    A) By passing the name of a variable:
    Code:
    void foo( char * );
    
    int main( void )
    {
        char *s = "Hello World!";
        foo( s );
        return 0;
    }
    ...
    The same holds true for a pointer to a pointer. If the variable you have to pass is exactly what the function expects, you simply pass it's name over.

    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Sep 2004
    Posts
    10
    Quzah, I love you, if I were a woman and I assume you are a man, I would marry you . You have been a great help to me, thank you very much.
    Last edited by pooty tang; 09-15-2004 at 12:17 PM.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    here's the first major problem:

    Code:
    while(csh != NULL)
    	{
    	  args = realloc(args, sizeof(char *)*(nargs + 1));
    	  args[nargs] = malloc(strlen(csh) + 1);
    	  strcpy(args[nargs], csh);
    	  nargs++;
    
    	  csh = strtok(NULL, " ,\n");
    	}
    each iteration of the loop you reallocate the char ** meaning when the loop finishes, only the last char * in the array points to valid memory. it doesn't help that you don't even free the memory when you're done with it, either!

    >> translate(*args);

    the way you have it here only one command gets executed - you'll need to either set up a loop to call the function with or else redesign the function to process a char ** internally.

    this is a good example of why it is so important to modularize code as much as possible. just start with the obvious - you need an array of char * and also a means for safely destroying the array when you're done with it. so start with a set of functions:

    Code:
    /*
     DeleteMatrix() takes the address of a char **
     so that it can set the pointer to NULL internally.
    */
    void DeleteMatrix(char *** array, int rows) {
     if(*array != NULL) {
      int index;
      for(index = 0; index < rows; ++index) {
       free((*array)[index]);
       }
      free(*array);
      *array = 0;
      }
     return;
     }
    /*
     NewMatrix() allocates an extra row which is set to
     NULL - this makes traversing the array easier...
     also, each column gets an extra char for posterity.
    */
    char ** NewMatrix(int rows, int columns) {
     char ** array = malloc(rows+1);
     if(array != NULL) {
      array[rows] = NULL;
      int index;
      for(index = 0; index < rows; ++index) {
       array[index] = malloc(columns+1);
       if(array[index] == NULL) {
        DeleteMatrix(&array, index);
        }
       }
      }
     return array;
     }
    putting all the 'guts' of the code within functions really can make coding a lot easier to develop and debug. make a list of repetitive tasks and start building a toolkit of useful functions - you won't regret it.

    [edit]
    foiled!
    [/edit]
    Last edited by Sebastiani; 09-15-2004 at 12:23 PM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Replies: 7
    Last Post: 11-21-2008, 04:27 PM
  3. function passing argument..array ?
    By jochen in forum C Programming
    Replies: 2
    Last Post: 09-30-2007, 11:53 AM
  4. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM