Reputation: 313
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
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
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
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
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