I was wondering which method I should use to declare a 2D array. First, I was going to declare a 2D array of char arr[15][100]. In each text file, there's a number on the first line, and that displays how many columns are in the text file, so I would save those numbers in another array and whenever I wanted a certain column, I would add that number plus whatever number to the index and I could hold multiple text files of columns in a single character string array.

I was thinking, I could save some of that space if instead of the [100], I dynamically allocated the memory for the second index of the array. This means I would have to read each text file twice though to copy the number of columns first and then add them all up and then use malloc.

So my question is would it be better to go with the [15][100] array at the start, or allocate the memory by reading from each file twice?

Well in my view allocating array[15][100] would be faulty as that may lead to array overflow and illegal memory access in some cases(Because here you are handling files).
And not all files are longer there may be small files which may not use most of the allocated memory or some files which may need more than allocated memory.
So I would suggest its better to scan the file twice know the number of columns and then use malloc.

==> Here,by scanning the file twice you are decreasing the time complexity but in return you are getting a safer,more memory efficient program to run.

You're right. It's much better to be safe than fast. Could you post the code for dynamically allocating the memory please?

Do you need all those files in memory at the same time? char arr[15][100] will only hold 15 strings, each string can contain a maximum of 99 characters + null terminator. So about all you might get in that array is the first line of text that is contains in 15 files.

You could use linked list of linked lists instead of a simple array. With that the program can read the files only once and still get they dynamic allocations you are looking for.

For example you could use a structure something like this:

struct LINK
{
    void* data;       // primary data attached here
    viud* extradata;  // this could be another linked list
    struct LINK*next;
};

I got it wrong again? I thought that was 100 strings.

Do you need all those files in memory at the same time? char arr[15][100] will only hold 15 strings, each string can contain a maximum of 99 characters + null terminator. So about all you might get in that array is the first line of text that is contains in 15 files.

You could use linked list of linked lists instead of a simple array. With that the program can read the files only once and still get they dynamic allocations you are looking for.

For example you could use a structure something like this:

struct LINK
{
    void* data;       // primary data attached here
    viud* extradata;  // this could be another linked list
    struct LINK*next;
};

Ya to make the code compatible with more number of files and characters how about doing this "ANCIENT DRAGON" ???

char **array; // A 2d array pointer
int nof; // No of files required
int noc; // No of characters required in the string

// Scan values of nof and noc

array = ( char * ) malloc ( nof * sizeof( char *));

for(i = 0 ; i < nof ; i++ )
{
        array[i] = (char *) malloc ( noc * sizeof( char ));
}

@RexxX

It was this thing I had in mind when I posted you my earlier reply.I am not very sure of the above code but I think I am correct up to a major extent and ya don't forget to free memory at the end.

@ANCIENT DRAGON

Please comment on this post. I have some minute doubts which your comments may clear.I mean how would linked list help to solve the above problem in a better way?

Exactly how is each file written? can you attach on of them to your post. By noc (number of columns) I was thinking of a matrix something like and excell file where you can have X number of columns and each column can contains strings of unspecified length. Something like this, which has 3 columns of text strings.

C1                       C2                    C3
One two three     four file six       seven eight nine

I got it wrong again? I thought that was 100 strings.

Nope. its 15 strings as I said before. If you want 100 strings for 15 files, and each string has a maximum of 79 characters+terminator, then do this: char arry[15][100][80];

char **array; // A 2d array pointer
int nof; // No of files required
int noc; // No of characters required in the string

// Scan values of nof and noc

array = ( char * ) malloc ( nof * sizeof( char *));

for(i = 0 ; i < nof ; i++ )
{
        array[i] = (char *) malloc ( noc * sizeof( char ));
}

@ANCIENT DRAGON

Please comment on this post. I have some minute doubts which your comments may clear.I mean how would linked list help to solve the above problem in a better way?

That code probably works ok, but only for one file. That matrix needs another dimension if it to work for more than one file.

Nope. its 15 strings as I said before. If you want 100 strings for 15 files, and each string has a maximum of 79 characters+terminator, then do this: char arry[15][100][80];

It's actually 15 character length strings, 10 possible in each of 10 possible files, so instead of 100, I could malloc when I know both the number of files and the number of columns at the top of each file.

Personally to save more space, I'd rather it be a 2D array and to index the numbers of files by using the same information used to malloc the 2D array.
Is that explanatory enough?

strings = (char *) malloc (total_str * sizeof( char *));

  for (i = 0; i< total_str; i++){
    strings[i] = (char *) malloc (STR_LENGTH * sizeof(char *));
  }

Is giving me the error "assignment from incompatible pointer type". I declared as

char **strings;

and everything else is an integer. Why am I still getting an error?

It seems both methods are worst ;)
Think about another (more flexible and robust) approach:

typedef struct sData
{
  /* loaded data description/manipulation    */
  /* totally dynamics (lists, realloc's etc) */
} Data;

/* User interface to the Data storage: */

/** Initialize Data structure to process data */
void initData(Data*);

/** Load file contents in the memory, returns file num
 *  or error code < 0.
 *  File contents in the memory, file closed. 
 */
int addFile(Data*, const char* fname);

/** Returns path of loaded file (some sugar) */
const char* getName(Data*, int fnum);

/** Returns the number of previously loaded files */
int maxFiles(Data*);

/** Returns the number of columns in loaded file */
int getColumns(Data*,int fnum);

/** Returns the number of rows in file #fnum */
int getRows(Data*,int fnum);

/** Returns a pointer to the data cell */
const char* getCell(Data*,int fnum, int col, int row);

/** Unload data of the file */
void freeFile(Data*,int fnum);

/** Returns 1 if the file loaded, otherwise 0 */
int isLoaded(Data*,int fnum);

/** Returns the number of loaded (active) files */
int cntFiles(Data*);

/** Close data processsing, free resources */
void freeData(Data*);

/* Plus Data storage implementation stuff 
 * (structs, functions, macros etc)
 */

I'm sure that such architecture is more effective and well-maintained too ;)...

^^ That gave me an idea. Can I malloc an array of structs? I just realized I need more dimensions.

Here's a fix for your "incompatible pointer type" error.

strings = (char **) malloc (total_str * sizeof( char *));

 for (i = 0; i< total_str; i++){
    strings[i] = (char *) malloc (STR_LENGTH * sizeof(char));
 }

And of course you can malloc an array of structs.
BTW, when you say that each file starts with the number of "columns", do you actually mean "rows", i.e., how many strings, one per line, are in the file?

^^ That gave me an idea. Can I malloc an array of structs? I just realized I need more dimensions.

Thank God, you can allocate anything except functions, labels and constants ;)...

This article has been dead for over six months. Start a new discussion instead.