trotter@ENUXHA.EAS.ASU.EDU (Russell T. Trotter) (04/17/91)
I am trying to get an array of strings, therefore I am using the following declaration: char *str[MAX] where MAX is an arbitrary constant. My question is how do I allocate the memory for each character position? Do all the characters strings for each element in the array need to be allocated contiguously? The problem involves reading in lines of input. Each line would be stored as a string and the number of lines make up the number of elements in the array. Any information would be greatly appreciated. Thank you. trotter@enuxha.eas.asu.edu
gordon@osiris.cso.uiuc.edu (John Gordon) (04/18/91)
trotter@ENUXHA.EAS.ASU.EDU (Russell T. Trotter) writes: >I am trying to get an array of strings, therefore I am using the >following declaration: char *str[MAX] where MAX is an arbitrary >constant. My question is how do I allocate the memory for each >character position? Do all the characters strings for each element >in the array need to be allocated contiguously? The problem involves >reading in lines of input. Each line would be stored as a string and >the number of lines make up the number of elements in the array. >Any information would be greatly appreciated. Thank you. Here's how I did something similar: use a temporary variable such as char buf[200] for getting each line of input, then do a str[i] = (char *) malloc(strlen(buf) +1) to copy each line into str. --- John Gordon Internet: gordon@osiris.cso.uiuc.edu #include <disclaimer.h> gordon@cerl.cecer.army.mil #include <clever_saying.h>
jfw@ksr.com (John F. Woods) (04/18/91)
trotter@ENUXHA.EAS.ASU.EDU (Russell T. Trotter) writes: >I am trying to get an array of strings, therefore I am using the >following declaration: char *str[MAX] where MAX is an arbitrary >constant. My question is how do I allocate the memory for each >character position? I assume by "character position" you really mean each pointer in the array; each one can be malloc'ed separately, one string at a time. >Do all the characters strings for each element >in the array need to be allocated contiguously? Unless your application wants to run blindly off the end of one string and onto the next (sounds like a bad idea to me), each string can be discontigous with the others. Each string represents a contiguous block of memory, note, so one string won't be represented by several pieces. >The problem involves reading in lines of input. >Each line would be stored as a string and >the number of lines make up the number of elements in the array. Here is where the Art of programming comes in. The most obvious implementation (which arbitrarily limits each line to 512 bytes plus newline) is: #include <stdio.h> ... #define MAX 666 char *str[MAX]; ... snuffle_file(f) FILE *f; { char buf[514], *p; int i; /* Read in lines from the file f */ for (i = 0; i < MAX; i++) { /* Read in a line */ if (fgets(buf, 514, f) == NULL) break; /* Treasure the line in a copy */ if ((str[i] = malloc(strlen(buf))) == NULL) { fprintf(stderr,"Go buy more memory.\n"); return; } strcpy(str[i], buf); /* Note that if you have strdup() the above 5 lines * become: * if ((str[i] = strdup(buf)) == NULL) { * <gripe> * } */ } } This isn't necessarily the best one can do, though; arbitrary line length limits are annoying, so the first obvious improvement is to replace the fgets-into-a-buffer strategy with something like (in pseudo-C) newstring = malloc(some pittance likely to hold most lines, like 32) while not-yet-eof and haven't-seen-a-newline fgets into a buffer if there's not enough room in newstring to add the buffer to the end, newstring = realloc(newstring, current size + some) /* remember that memory can run out */ add buffer contents to end of newstring newstring = realloc(newstring, actual size) /*free a few bytes at end*/ I believe that 4.4BSD will have a "readline()" function that does roughly that, or you can figure out how to roll your own, or dig up any one of the innumerable versions that have been lodged in netnews postings over the past decade. The next annoying limit that should die is "MAX": a similar strategy of realloc-if-out-of-room can be used to remove the arbitrary limit on the number of lines. Something else to ponder is: if you *know* that the file size is relatively small in comparison to the amount of memory you have, and if you *know* that your OS does reasonable things for large reads from files, it *may* be worth mallocing a contiguous buffer which is large enough to hold the file, slurp it all in with one single read, and then pick it apart into lines. Note that this strategy may perform poorly on someone else's machine for perfectly good reasons, and worse, may misfire badly the first time some clown gives your program a 16Mb text file when you "knew" the limit would be 16Kb. Balancing the tradeoffs well is an art.
scs@adam.mit.edu (Steve Summit) (04/19/91)
In article <3182@ksr.com> jfw@ksr.com (John F. Woods) writes: >trotter@ENUXHA.EAS.ASU.EDU (Russell T. Trotter) writes: >>I am trying to get an array of strings... >>...how do I allocate the memory for each [string]? >The most obvious implementation... is: [most code deleted] > /* Treasure the line in a copy */ > if ((str[i] = malloc(strlen(buf))) == NULL) { Make that malloc(strlen(buf) + 1). (Side note: never tangle your fingers and type malloc(strlen(buf + 1)), either.) In article <1991Apr17.203253.13854@ux1.cso.uiuc.edu> gordon@osiris.cso.uiuc.edu (John Gordon) writes: >...do a >str[i] = (char *) malloc(strlen(buf) +1) >to copy each line into str. make that "do [a malloc], *then* copy each line into str." Steve Summit scs@adam.mit.edu
jfw@ksr.com (John F. Woods) (04/22/91)
scs@adam.mit.edu (Steve Summit) writes: >In article <3182@ksr.com> jfw@ksr.com (John F. Woods) writes: >> /* Treasure the line in a copy */ >> if ((str[i] = malloc(strlen(buf))) == NULL) { >Make that malloc(strlen(buf) + 1). (Side note: never tangle your >fingers and type malloc(strlen(buf + 1)), either.) Oops. Consider that another reason to use strdup() if you've got it. Assuming the library writer didn't screw up, too. :-)
csp@gtenmc.UUCP (04/27/91)
In article <9104171614.AA14362@enuxha.eas.asu.edu> trotter@enuxha.eas.asu.edu (Russell T. Trotter) writes: >constant. My question is how do I allocate the memory for each ^^^^^^^^ Malloc , my dear Russell. Malloc ! >character position? Do all the characters strings for each element >in the array need to be allocated contiguously? The problem involves ^^^^^^^^^^^^ Did't you know that memory is linear ! ( NO ) >reading in lines of input. Each line would be stored as a string and >the number of lines make up the number of elements in the array. >Any information would be greatly appreciated. Thank you. This proves without doubt 'Ignorance is NOT bliss'. Solution : #include <string.h> #include <malloc.h> #include <stdio.h> #define MAX 20 #define MAX_SZ 512 char *str[MAX]; Read_Input() { int i; char buff[MAX_SZ]; for ( i = 0 ; i < MAX ; i++ ) str[i] = malloc(strlen(gets(buff)+1)), strcpy(str[i],buff); } C S Palkar -- > >trotter@enuxha.eas.asu.edu
gregory@ritcsh.csh.rit.edu (Greg Conway) (04/30/91)
In article <1139@gtenmc.UUCP> csp@gtenmc.UUCP () writes: > for ( i = 0 ; i < MAX ; i++ ) > str[i] = malloc(strlen(gets(buff)+1)), > strcpy(str[i],buff); My, my, my -- live on the edge, don't we? Using malloc without checking the return value is risky, at best... - Greg -- Gregory Conway @ Computer Science House, RIT