5

I have a defined array sample:

char *arguments[] = {"test-1","test-2","test-3"};

I am trying to add an argument input given by the command line. I tried the strcpy function and also to pass it through the array element e.g. arguments[num+1] = argv[1] but again not successfully.

I know that this is a very simple question but I am not an experienced programmer and all my experience comes from higher level programming languages (PHP, Perl).

The closest sample of work that I found online is C program to insert an element in an array and C program to delete an element from an array. But are not exactly what I am looking for and they are working with intigers not characters that I need.

My goal is to find a way to add and remove strings from a dynamic array that can grow and shrink based on the process of the script.

Thanks everyone for their time and effort to assist me.

Sample of a working code is given under:

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

/* Set as minimum parameters 2 */
#define MIN_REQUIRED 2
#define MAX_CHARACTERS 46

/* Usage Instructions */
int help() {
  printf("Usage: test.c [-s <arg0>]\n");
  printf("\t-s: a string program name <arg0>\n");
  printf("\t-s: a string sample name <arg1>\n");
  return (1);
}

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

  if ( argc < MIN_REQUIRED ) {
    printf ("Please follow the instructions: not less than %i argument inputs\n",MIN_REQUIRED);
    return help();
  }
  else if ( argc > MIN_REQUIRED ) {
    printf ("Please follow the instructions: not more than %i argument inputs\n",MIN_REQUIRED);
    return help();
  }
  else {
    int size, realsize;
    char *input = NULL;

    char *arguments[] = {"test-1","test-2","test-3"};

    int num = sizeof(arguments) / sizeof(arguments[0]);

    printf("This is the number of elements before: %i\n",num);

    int i;
    for (i=0; i<num; i++) {
      printf("This is the arguments before: [%i]: %s\n",i,arguments[i]);
    }

    printf("This is the input argument: %s\n",argv[1]);
    printf("This is the array element: %i\n",num+1);

    input = (char *)malloc(MAX_CHARACTERS);
    if (input == NULL) {
      printf("malloc_in failled\n");
      exit(0);
    }

    memset ( input , '\0' , MAX_CHARACTERS);

    int length_before = strlen(input);
    printf("This is the length before: %i\n",length_before);
    strcpy(input , argv[1]);
    int length_after = strlen(input);
    printf("This is the length after: %i\n",length_after);

    //arguments[num+1] = input;

    strcpy(arguments[num+1],input);

    int num_2 = sizeof(arguments) / sizeof(arguments[0]);

    printf("This is the number of elements after: %i\n",num);

    for (i=0; i<num_2; i++) {
      printf("This is the arguments after [%i]: %s\n",i,arguments[i]);
    }

  } // End of else condition

  return 0;
} // Enf of int main ()
thanos
  • 111
  • 1
  • 4
  • 10
  • You can't use array that way. Either declare array large enough (e.g. `char *arguments[MAX_ARGUMENTS]`, where constant is some sane number), or allocate it dynamically at the point where you know how many arguments you have. – keltar Jul 25 '14 at 17:29

2 Answers2

5
  1. "My goal is to find a way to add and remove strings from a dynamic array":

    char *arguments[] = {...} is statically allocated, so it cannot serve as a "dynamic array".

  2. strcpy(arguments[num+1],input):

    You cannot access arguments[num+1] when this array has only num entries.


Suggested fix - allocate and initialize arguments dynamically, according to the value of argc:

char* strings[] = {"test-1","test-2","test-3"};
int i, num = sizeof(strings) / sizeof(*strings);
char** arguments = malloc((num+argc-1)*sizeof(char*));
if (arguments == NULL)
    ; // Exit with a failure

for (i=0; i<num; i++)
{
    arguments[i] = malloc(strlen(strings[i])+1);
    if (arguments[i] == NULL)
        ; // Deallocate what's already been allocated, and exit with a failure
    strcpy(arguments[i],strings[i]);
}

for (i=0; i<argc-1; i++)
{
    arguments[num+i] = malloc(strlen(argv[i+1])+1);
    if (arguments[num+i] == NULL)
        ; // Deallocate what's already been allocated, and exit with a failure
    strcpy(arguments[num+i],argv[i+1]);
}

...

// Deallocate everything before ending the program
barak manos
  • 29,648
  • 10
  • 62
  • 114
  • Note that if you're going to actually exit after a failure (or after doing something), there's no need to deallocate everything, as exiting will do that automatically. If you're going to try to continue despite the error, then you need to deallocate things. – Chris Dodd Jul 25 '14 at 17:59
  • @ChrisDodd: sounds to me like something that depends on the OS, and not something that is defined by the standard. – barak manos Jul 25 '14 at 18:19
  • Thanks I think I got the idea on how to go over this small problem. I will have a go. – thanos Jul 26 '14 at 09:47
2

There are no dynamic arrays in C, arguments has a static size, capable of holding 3 elements,

strcpy(arguments[num+1],input);

is simply undefined behaviour, the expression arguments[num+1] accesses an array out of bounds (two elements after the last); no magical reallocation or something will happen.

In general, you have three options:

  1. You have an upper bound of how many items you want to be able to store in the array and declare the array to have that size. Either keep track of the numbers actually stored in it or add some sentinel value (which needs additional space!) indicating the end.
  2. You have an upper bound, and if the number of items you want to store happen to exceed this limit, you abort (returning an error indicator, telling the user that the input data is too big, …).
  3. Look for malloc, realloc and free.
mafso
  • 5,433
  • 2
  • 19
  • 40
  • Ok ok I understand what you mean. I thought that I do not need to specify a size of an array. I was under the impression that can increase or decrease based on the elements that it has. Well in this case scenarios in higher programming languages how the arrays are specified? Thank you for your time and effort to assist me. – thanos Jul 26 '14 at 09:52
  • You're welcome :) Arrays always have a constant size, there's no way of resizing it. Higher languages don't really have something like C-arrays. Java arrays, for example, are more like C pointers pointing to `malloc`ed (the “`new` equivalent”) memory (the latter being more flexible, however, e.g. you can resize such “Java arrays” in C). Lists in e.g. Python or Haskell aren't arrays at all (in the sense of O(1) random access), they're linked lists (you'll find a bunch of examples on linked list implementations in C by a quick web search). – mafso Jul 26 '14 at 12:16
  • You can write data structures on your own which automatically resize if necessary to get the behaviour similar to lists in other languages. Many container formats are already implemented in some libraries, e.g. Glib. At the beginning of a C project, you usually spend some time on planning which memory strategies to use. That's something you should become familiar with. Also related to your question: http://stackoverflow.com/a/24894968/1741125 – mafso Jul 26 '14 at 12:17