简体   繁体   中英

C: how to read in a variable amount of info from files and store it in array

I am not used to programming in c, so I am wondering how to have an array, and then read a variable amount of variables in a file, and those these files in the array.

//how do I declare an array whose sizes varies
do {
     char buffer[1000];
     fscanf(file, %[^\n]\n", buffer);
     //how do i add buffer to array
}while(!feof(file)); 
int nlines = 0
char **lines = NULL; /* Array of resulting lines */
int curline = 0;
char buffer[BUFSIZ]; /* Just alloocate this once, not each time through the loop */
do {
     if (fgets(buffer, sizeof buffer, file)) { /* fgets() is the easy way to read a line */
       if (curline >= nlines) { /* Have we filled up the result array? */
         nlines += 1000; /* Increase size by 1,000 */
         lines = realloc(lines, nlines*sizeof(*lines); /* And grow the array */
       }
       lines[curline] = strdup(buffer); /* Make a copy of the input line and add it to the array */
       curline++;
     }
}while(!feof(file)); 

Arrays are always fixed-size in C. You cannot change their size. What you can do is make an estimate of how much space you'll need beforehand and allocate that space dynamically (with malloc() ). If you happen to run out of space, you reallocate. See the documentation for realloc() for that. Basically, you do:

buffer = realloc(size);

The new size can be larger or smaller than what you had before (meaning you can "grow" or "shrink" the array.) So if at first you want, say, space for 5000 characters, you do:

char* buffer = malloc(5000);

If later you run out of space and want an additional 2000 characters (so the new size will be 7000), you would do:

buffer = realloc(7000);

The already existing contents of buffer are preserved. Note that realloc() might not be able to really grow the memory block, so it might allocate an entirely new block first, then copy the contents of the old memory to the new block, and then free the old memory. That means that if you stored a copy of the buffer pointer elsewhere, it will point to the old memory block which doesn't exist anymore. For example:

char* ptr = buffer;
buffer = realloc(7000);

At that point, ptr is only valid if ptr == buffer , which is not guaranteed to be the case.

It appears that you are trying to read until you read a newline.

The easiest way to do this is via getline .

char *buffer = NULL;
int buffer_len;
int ret = getline(&buffer, &buffer_len, file);

...this will read one line of text from the file file (unless ret is -1 , in which there's an error or you're at the end of the file).

An array where the string data is in the array entry is usually a non-optimal choice. If the complete set of data will fit comfortably in memory and there's a reasonable upper bound on the number of entries, then a pointer-array is one choice.

But first, avoid scanf %s and %[] formats without explicit lengths. Using your example buffer size of 1000, the maximum string length that you can read is 999, so:

/* Some needed data */
int n;
struct ptrarray_t
{
    char **strings;
    int  nalloc; /* number of string pointers allocated */
    int  nused;  /* number of string pointers used */
} pa_hdr; /* presume this was initialized previously */
...
n = fscanf(file, "%999[\n]", buffer);
if (n!=1 || getc(file)!='\n')
{
    there's a problem
}
/* Now add a string to the array */
if (pa_hdr.nused < pa_hdr.nalloc)
{
    int len = strlen(buffer);
    char *cp = malloc(len+1);
    strcpy(cp, buffer);
    pa_hdr.strings[pa_hdr.nused++] = cp;
}

A reference to any string hereafter is just pa_hdr.strings[i], and a decent design will use function calls or macros to manage the header, which in turn will be in a header file and not inline. When you're done with the array, you'll need a delete function that will free all of those malloc()ed pointers.

If there are a large number of small strings, malloc() can be costly, both in time and space overhead. You might manage pools of strings in larger blocks that will live nicely with the memory allocation and paging of the host OS. Using a set of functions to effectively make an object out of this string-array will help your development. You can pick a simple strategy, as above, and optimize the implementation later.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM