Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
953 views
in Technique[技术] by (71.8m points)

c - can anyone explain me how does this function work?

I don't understand what this function do. Can anyone explain me in detail please?

char *my_getline(FILE *stream) {
    char *line = NULL;
    size_t pos = 0;
    int c;

    while ((c = getc(stream)) != EOF) {
        char *newp = realloc(line, pos + 2);
        if (newp == NULL) {
            free(line);
            return NULL;
        }
        line = newp;
        if (c == '
')
            break;
        line[pos++] = (char)c;
    }
    if (line) {
        line[pos] = '';
    }
    return line;
}

If you can add a comment on my code, I think that will help me. I want to search a substring in a string and I found this function code.

This is the main function:

int main(void) {
    char *str, *sub;
    size_t len1, len2, i, count = 0;
    printf("Insert string :
");
    str = my_getline(stdin);
    printf("insert substring :
");
    sub = my_getline(stdin);

    if (str && sub) {
        len1 = strlen(str);
        len2 = strlen(sub);
        for (i = 0; i + len2 <= len1; i++) {
            if (!memcmp(str + i, sub, len2)) {
                count++;
                printf("Substring found at index : %d
", i);
            }
        }
        printf("in the number of: %d
", count);
        if (count == 0) {
            printf("Substring not found
");
        }
    }
    free(str);
    free(sub);
    return 0;
}

I understand the main function but unable to understand the logic in function my_getline.

Please help me in understanding the logic. Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
char *my_getline(FILE *stream) {
    // pointer to the line to be read:
    char *line = NULL;
    // position of the next character:
    size_t pos = 0;
    // single character:
    int c;

    while ((c = getc(stream)) != EOF) { // read 1 character at a time until EOF
        // allocate a new buffer with room for the char just read + a 0 terminator
        // when `line` is NULL, this is the same as `malloc()`, otherwise it 
        // will change the size of the allocation:
        char *newp = realloc(line, pos + 2);

        // check for errors:
        if (newp == NULL) {
            free(line);
            return NULL;
        }

        // no errors, assign new buffer to `line`:
        line = newp;

        // end of line found: we're done:
        if (c == '
')
            break;

        // otherwise add new character to the line:
        line[pos++] = (char)c;
    }

    // if there was *anything* to read, add 0 terminator (marks end of string):
    if (line) {
        line[pos] = '';
    }
    return line;
}

That's about it. Note it's horribly inefficient for two reasons: It reads only one character at a time and it calls realloc() for each and every character.

A better solution would use e.g. fgets() and increase the buffer size in reasonable chunks, for example like this:

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

#define GETLINE_CHUNK 1024

static void xrealloc(void *bufPtr, size_t size)
{
    void **buf = bufPtr;
    void *tmp = realloc(*buf, size);
    if (!tmp)
    {
        free(*buf);
        *buf = 0;
    }
    *buf = tmp;
}    

char *my_getline(FILE *stream)
{
    // allocate first chunk:
    char *buf = malloc(GETLINE_CHUNK);
    if (!buf) return 0;
    *buf = 0;
    size_t pos = 0;

    // read up to GETLINE_CHUNK bytes, until newline:
    while (fgets(buf + pos, GETLINE_CHUNK, stream))
    {
        // look for newline:
        char *nlPos = strchr(buf, '
');
        if (nlPos)
        {
            // found, then our line is complete
            *nlPos = 0;

            // shrink buffer to needed size
            xrealloc(&buf, nlPos-buf+1);
            return buf;
        }

        // set next offset to read
        pos = strlen(buf);

        // increase buffer size to have room for a whole other GETLINE_CHUNK:
        xrealloc(&buf, pos + GETLINE_CHUNK);
        if (!buf) return 0;
    }

    // if nothing was read, free buffer and return NULL:
    if (*buf == 0)
    {
        free(buf);
        buf = 0;
    }
    return buf;
}

int main(void)
{
    char *line = my_getline(stdin);
    if (line)
    {
        puts(line);
        free(line);
    }
    else puts("no input!");
    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...