hobbes131
hobbes131

Reputation: 313

Creating a argv[] to send args to another function

I know there is a couple of entries on this and I looked through them and couldn't quite get to where I wanted to be.

I'm building function where it can read the contents of a directory and pass the regular files to another function to build an archive.

I'm trying make an argv[] like item called items, that I can pass to my function, the issue is that I need to populate it with the file names. Rather that statically declaring it (which I saw in a lot of examples) I want to use malloc based on the file count.

Here is the function header for quick:

void quick(int argc, char *argv[])

Here is the append function:

void append(char* argv[]){
    struct dirent *dp;
    int count, i = 3;
    char *files;
    char items [*files][255];
    DIR *dirp = opendir(".");
    if(dirp == NULL){
        fail('f');
    }

    printf("ar: adding files in current directory to archive: %s", argv[2]);

    while((dp = readdir(dirp)) != NULL){
        if(dp->d_type == DT_REG){
            count++;
        }
    }

    rewinddir(dirp);
    files = malloc(count*sizeof(char));

    //copy argv[2] archive name, into files, so we can pass to quick
    strcpy(items[2], argv[2]);

    while((dp = readdir(dirp)) != NULL){
        errno = 0;
        dp = readdir(dirp);

        //leave is dir is empty
        if(dp == NULL)
            break;

        // Skip . and ..
        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
            continue;

        //if file is not the archive and a regular file add to list
        if(strcmp(dp->d_name, argv[2]) != 0 && dp->d_type == DT_REG){
            strcpy(items[i], dp->d_name);
            i++;
        }
    }
    closedir(dirp);

    quick(i, items);
}

I'm getting an error on the items arg, as incompatible pointer type, and I'm guessing that I didn't do my malloc (and possibly my array) correctly because I have still not mastered the mysteries of those.

Upvotes: 2

Views: 4849

Answers (4)

Rami Jarrar
Rami Jarrar

Reputation: 4643

With the length of the columns statically know, you could also allocate

char (*items )[255];
// obtain row count
items = malloc(rowCount * sizeof(*items));

memory to a pointer to char[255]. That way, you get a contiguous block of memory, which may give better locality, and you need only free one pointer.

If the number of rows is not too large, using a variable length array,

rowCount = whatever;
char items[rowCount][255];

may however be the best option if C99 or later is supported.

Upvotes: 0

Alexey Frunze
Alexey Frunze

Reputation: 62068

Here's how you can grow an "array" of "strings":

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

int AddString(char*** strings, size_t* count, const char* newStr)
{
  char* copy;
  char** p;

  if (strings == NULL ||
      newStr == NULL ||
      (copy = malloc(strlen(newStr) + 1)) == NULL)
    return 0;

  strcpy(copy, newStr);

  if ((p = realloc(*strings, (*count + 1) * sizeof(char*))) == NULL)
  {
    free(copy);
    return 0;
  }

  *strings = p;

  (*strings)[(*count)++] = copy;

  return 1;
}

void PrintStrings(char** strings, size_t count)
{
  printf("BEGIN\n");
  if (strings != NULL)
    while (count--)
      printf("  %s\n", *strings++);
  printf("END\n");
}

int main(void)
{
  char** strings = NULL;
  size_t count = 0;
  PrintStrings(strings, count);
  AddString(&strings, &count, "Hello World!");
  PrintStrings(strings, count);
  AddString(&strings, &count, "123");
  AddString(&strings, &count, "ABCDEF");
  PrintStrings(strings, count);
  return 0;
}

Output (ideone):

BEGIN
END
BEGIN
  Hello World!
END
BEGIN
  Hello World!
  123
  ABCDEF
END

Upvotes: 1

sheu
sheu

Reputation: 5763

Your declaration of char items [*files][255] is incorrect.

Basically, you want files to be an array of arrays; hence it needs to be a pointer-to-pointer (i.e. char**) type. Then you'll need to allocate each array in that array to hold the actual strings, like so:

char** files;
files = malloc(count * sizeof(char*));      // allocate the array to hold the pointer
for (size_t i = 0; i < count; i += 1)
    files[i] = malloc(255 * sizeof(char));  // allocate each array to hold the strings

Free the memory appropriately when you're done with it:

for (size_t i = 0; i < count; i += 1)
    free(files[i]);
free(files);

Upvotes: 3

Eddy_Em
Eddy_Em

Reputation: 872

Look here:

char *files;
char items [*files][255];

You'd better use malloc after files would be initialized.

As I understand, this should be for example

char items [count][255];

int C99 style.

BTW, count used uninitialized. Set it to zero at beginning.

Upvotes: 0

Related Questions