Tookie
Tookie

Reputation: 25

Custom getLine() function for c

I need a function/method that will take in a char array and set it to a string read from stdin. It needs to return the last character read as its return type, so I can determine if it reached the end of a line or the end of file marker.

here is what I have so far, and I kind of based it off of code from here

UPDATE: I changed it, but now it just crashes upon hitting enter after text. I know this way is inefficient, and char is not the best for EOF check, but for now I am just trying to get it to return the string. I need it to do it in this fashion and no other fashion. I need the string to be the exact length of the line, and to return a value that is either the newline or EOF int which I believe can still be used in a char value.

This program is in C not C++

char getLine(char **line);

int main(int argc, char *argv[])
{
    char *line;
    char returnVal = 0;

    returnVal = getLine(&line);
    printf("%s", line);

    free(line);

    system("pause");
    return 0;
}

char getLine(char **line) {
    unsigned int lengthAdder = 1, counter = 0, size = 0;
    char charRead = 0;

    *line = malloc(lengthAdder);
    while((charRead = getc(stdin)) != EOF && charRead != '\n')
    {
        *line[counter++] = charRead;
        *line = realloc(*line, counter);
    }

    *line[counter] = '\0';

    return charRead;
}

Thank you for any help in advance!

Upvotes: 1

Views: 2750

Answers (3)

Petr Baudis
Petr Baudis

Reputation: 1198

Your key problem is that line pointer value does not propagate out of the getLine() function. The solution is to pass pointer to the line pointer to the function as a parameter instead - calling it like getLine(&line); while the function would be defined as taking parameter char **line. In the function, on all places where you now work with line, you would work with *line instead, i.e. dereferencing the pointer to a pointer and working with the value of the variable in main() where the pointer leads. Hope this is not too confusing. :-) Try to draw it on a piece of paper.

(A tricky part - you must change line[counter] to (*line)[counter] because you first need to dereference the pointer to the string, and only then to access a specific character in the string.)

There is a couple of other problems with your code:

  • You use char as the type for charRead. However, the EOF constant cannot be represented using char, you need to use int - both as the type of charRead and return value of getLine(), so that you can actually distringuish between a newline and end of file.
  • You forgot to return the last char read from your getLine() function. :-)
  • You are reallocating the buffer after each character addition. This is not terribly efficient and therefore is a rather ugly programming practice. It is not too difficult to use another variable to track the amount of space allocated and then (i) start with allocating a reasonable chunk of memory, e.g. 64 bytes, so that ideally you will never reallocate (ii) enlarge the allocation only if you need to based on comparing the counter and your allocation size tracker. Two reallocation strategies are common - either doubling the size of the allocation or increasing the allocation by a fixed step.

Upvotes: 0

Pablo
Pablo

Reputation: 13580

The way you use realloc is not correct. If it returns NULL then the memory block will be lost.

It is better to use realloc in this way:

char *tmp;
...
tmp = realloc(line, counter);
if(tmp == NULL)
   ERROR, TRY TO SOLVE IT
line = tmp;

Upvotes: 0

user529758
user529758

Reputation:

You're assigning the result of malloc() to a local copy of line, so after the getLine() function returns it's not modified (albeit you think it is). What you have to do is either return it (as opposed to use an output parameter) or pass its address (pass it 'by reference'):

void getLine(char **line)
{
    *line = malloc(length);

    // etc.
}

and call it like this:

char *line;
getLine(&line);

Upvotes: 2

Related Questions