Thread: how do i get a multi line string..??

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    8

    how do i get a multi line string..??

    is there any function to get a multi line string ?

  2. #2
    Registered User
    Join Date
    Sep 2012
    Posts
    357
    Not really.

    You can read individual characters (using fgetc() or equivalent); you can read individual lines (using fgets()); you can read blocks of bytes (using fread()).

    I think the best way to write your own function would be to use fgetc() and build the lines as characters keep coming in.

    Happy Coding!

  3. #3
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    If you have a POSIX.1-2008 -compatible C library (like GNU C library), then you can use getdelim() to read until the next occurrence of a character.

    For example, if you have a file containing multi-line strings, separated by NUL characters (\0), then you can use
    Code:
    #define _POSIX_C_SOURCE 200809L
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(void)
    {
        char    *data = NULL;
        size_t   size = 0;
        ssize_t  length;
    
        while ((length = getdelim(&data, &size, '\0', stdin)) != (ssize_t)-1) {
    
            /* You have a length-char string in data */
    
        }
    
        /* Free the dynamically allocated memory for the line. */
        free(data);
        data = NULL;
        size = 0;
    
        /* Did we encounter a read error? */
        if (ferror(stdin)) {
            fprintf(stderr, "Error reading standard input.\n");
            return 1;
        }
    
        /* It was an end-of-file. Success. */
        return 0;
    }
    The above is, by the way, the simplest way to read a multi-line C strings from a file. The file is not really a text file, because it contains embedded NUL characters (between each string), but it does support all ASCII-compatible character sets (actually, all non-wide character sets, including variable-width encodings like UTF-8). Because the separator is the same as C end-of-string character, you can store any C strings this way, without worrying about escaping et cetera.

    The above code works for any single-character delimiter you choose.

    If your delimiter is a string, you can either do it character-by-character, or use getdelim() using the final character in your delimiter string as the delimiter. If the string does not end with your delimiter string, you append the string to the result, and read more:
    Code:
    #define _POSIX_C_SOURCE 200809L
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    
    ssize_t getdelimstr(char **const dataptr, size_t *const sizeptr,
                        const char *const end, const size_t endlen,
                        FILE *const input)
    {
        char     *accumulator_data = NULL, *accumulator_temp;
        size_t   accumulator_size = 0;
        ssize_t  length;
    
        /* Verify parameters look valid. */
        if (!dataptr || !sizeptr || !end || endlen < 1 || !input) {
            errno = EINVAL;
            return (ssize_t)-1;
        }
    
        /* Initial read. */
        length = getdelim(dataptr, sizeptr, end[endlen - 1], input);
        if (length < (ssize_t)1)
            return (ssize_t)-1;
    
        /* Did we get the complete delimiter string? */
        if ((size_t)length >= endlen && !memcmp(*dataptr + length - endlen, end, endlen))
            return length;
    
        while (1) {
    
            /* Reallocate accumulator data buffer. */
            accumulator_temp = realloc(accumulator_data, accumulator_size + length + 1);
            if (!accumulator_temp) {
                free(accumulator_data);
                errno = ENOMEM;
                return (ssize_t)-1;
            }
            accumulator_data = accumulator_temp;
    
            /* Copy to accumulator data buffer. */
            memcpy(accumulator_data + accumulator_size, *dataptr, length);
            accumulator_size += length;
    
            /* Properly terminate accumulator data buffer, like getdelim() does. */
            accumulator_data[accumulator_size] = '\0';
    
            /* Re-check for the delimiter string. */
            if (!memcmp(accumulator_data + accumulator_size - endlen, end, endlen)) {
                /* We do have the delimiter string. Replace with the line buffer. */
                free(*dataptr);
                *dataptr = accumulator_data;
                *sizeptr = accumulator_size;
                return (ssize_t)accumulator_size;
            }
    
            /* Read more. */
            length = getdelim(dataptr, sizeptr, end[endlen - 1], input);
    
            /* Read error? End-of-file (without delimiter string)? */
            if (length < (ssize_t)1) {
                const int  saved_errno = errno;
    
                /* Read error? Not EOF? */
                if (ferror(input) || !feof(input)) {
                    free(accumulator_data);
                    errno = saved_errno;
                    return (ssize_t)-1;
                }
    
                /* It was an EOF. */
                free(*dataptr);
                *dataptr = accumulator_data;
                *sizeptr = accumulator_size;
                return (ssize_t)accumulator_size;
            }
        }
    }
    Here is an example main() that will read strings delimited with lines that contain only "NEXT", from standard input:
    Code:
    int main(void)
    {
        static const char   delimiter_str[] = "\nNEXT\n";
        static const size_t delimiter_len   = 6;
    
        char    *data = NULL;
        size_t   size = 0;
        ssize_t  length;
    
        while (1) {
    
            length = getdelimstr(&data, &size, delimiter_str, delimiter_len, stdin);
    
            if (length < (ssize_t)1)
                break;
    
            /* Remove (possible) delimiter. */
            if ((size_t)length >= delimiter_len &&
                !memcmp(data + length - delimiter_len, delimiter_str, delimiter_len)) {
                length -= delimiter_len;
                data[length] = '\0';
            }
    
            fflush(stderr);
            printf("Got %d chars: '%s'.\n", (int)length, data);
            fflush(stdout);
        }
    
        free(data);
        data = NULL;
        size = 0;
    
        if (ferror(stdin)) {
            fprintf(stderr, "Error reading standard input.\n");
            return 1;
        }
    
        return 0;
    }
    In Linux you can test it with e.g.
    Code:
    ./program <<END
    First string
    NEXT
    Second string is
    split into two lines.
    NEXT
    Third string is split
    into three lines,
    as you can see.
    END
    where the <<END and END is a facility provided by the shell to allow easier multi-line input to a command. (The getdelimstr() function is careful to handle the special case where there is no delimiter string at the end of the input correctly.)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multi line macro help
    By bmancl in forum C Programming
    Replies: 17
    Last Post: 10-26-2009, 09:19 PM
  2. writing a Multi-Line string
    By cornacum in forum C Programming
    Replies: 3
    Last Post: 02-22-2009, 09:53 AM
  3. Storing multi line text
    By beginner.c in forum C Programming
    Replies: 5
    Last Post: 07-31-2007, 11:31 PM
  4. Multi line
    By Salibea in forum Windows Programming
    Replies: 11
    Last Post: 08-11-2005, 04:00 AM
  5. Multi-line File streaming
    By Tyrael in forum C++ Programming
    Replies: 1
    Last Post: 11-14-2001, 06:32 AM