0

How can I read multiple lines from a text file (variable width) and store all of them in a C "string"?

EDIT: I guess I'll be fget'ing the strings and storing them in one flexible buffer (via realloc) :) Also, this is not homework even though it apparently seems so (programming is just a hobby for me). I was just asking out of curiosity

pwseo
  • 313
  • 1
  • 5
  • 15
  • Is this homework? Have you tried anything that you can show us? Do you have any more detail to share? – Cogwheel Jul 13 '10 at 01:50
  • No, it's not homework; just having fun (my studies are in healthcare lol) I thought of reading the strings with fgets and then strcat'ing them together in one final string, but just wanted to know if there was a more efficient way of doing it. I'll be trying it anyway, while still reading possible replies :) – pwseo Jul 13 '10 at 01:57

4 Answers4

2

Since this apparently isn't homework, here's some sample code of how I'd do it. I'm just allocating a huge block of memory for the entire file, since you're going to read the whole thing eventually anyway, but if you're dealing with large files it's usually better to handle them a line at a time.

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

int main(int argc, char *argv[])
{
        // first, get the name of the file as an argument
        if (argc != 2) {
                printf("SYNTAX: %s <input file>\n", argv[0]);
                return -1;
        }

        // open the file
        FILE* fp = fopen(argv[1], "r");

        if (fp == NULL) {
                printf("ERROR: couldn't open file\n");
                return -2;
        }

        // seek to the end to get the length
        // you may want to do some error-checking here
        fseek(fp, 0, SEEK_END);
        long length = ftell(fp);

        // we need to seek back to the start so we can read from it
        fseek(fp, 0, SEEK_SET);

        // allocate a block of memory for this thing
        // the +1 is for the nul-terminator
        char* buffer = malloc((length + 1) * sizeof(char));

        if (buffer == NULL) {
                printf("ERROR: not enough memory to read file\n");
                return -3;
        }

        // now for the meat. read in the file chunk by chunk till we're done
        long offset = 0;
        while (!feof(fp) && offset < length) {
                printf("reading from offset %d...\n", offset);
                offset += fread(buffer + offset, sizeof(char), length-offset, fp);
        }

        // buffer now contains your file
        // but if we're going to print it, we should nul-terminate it
        buffer[offset] = '\0';
        printf("%s", buffer);

        // always close your file pointer
        fclose(fp);

        return 0;
}

Whew, it's been a while since I've written C code. Hopefully people will chime in with helpful corrections/notices of massive problems. :)

Faisal
  • 4,687
  • 1
  • 19
  • 13
  • That's an interesting solution... You just gave me an idea. Throughout my file I have some delimiters... I could pre-scan the file and build a list of delimiters and then run through it again using said list to allocate memory (difference in position of two delimiters is the size of the string between them). Thanks! – pwseo Jul 13 '10 at 02:30
  • How about `fstat` to get the file length instead of `fseek` + `ftell` + `fseek`? – Ben Voigt Jul 13 '10 at 03:08
1

Here's the general process

  1. Create an initial buffer.
  2. Read a line from the file, or up to the remaining space in the buffer.
  3. EOF? Skip to 6.
  4. Filled the buffer? Reallocate with more space.
  5. Rinse and repeat.
  6. Add a terminating 0
Cogwheel
  • 22,781
  • 4
  • 49
  • 67
  • That's what I was thinking... I just asked because there could be some abstraction I was not aware of. Thanks anyway – pwseo Jul 13 '10 at 02:04
  • There are some additional string methods in `string.h`, but nothing directly applicable to your problem. If you want to program in C, you have to get used to doing this kind of thing yourself. – Larry Wang Jul 13 '10 at 02:19
0

Is this homework? The tricky thing here is that you must keep track of the string length and how much of it is used/empty. Either guess high enough to begin with, or call malloc() or one of its brothers when you are out of space.

Larry Wang
  • 986
  • 6
  • 17
0

You can try the "variable length" string implementation here:

How to implement a variable-length ‘string’-y in C

And then, you'll have to write the "add" operation to the string. Then, you can safely read any chunk of bytes, and concatenate it to what you have already read.

Community
  • 1
  • 1
Baltasarq
  • 12,014
  • 3
  • 38
  • 57
  • I have implemented a variable length string type in the past, so I'll be using that one instead, but thanks anyway, Baltasarq :) – pwseo Jul 13 '10 at 11:35