0

I wanted to write a program in C that will accept a line of any length from stdin and display it or apply any function to that string. For this to work I will need a String (char []) with dynamic length.

This is how I did it:

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

int main(int argc, char **argv){


    char *line;
    line = malloc(10);
    line[0] = '\0';

    char *str = malloc(10);

    fprintf(stdout, "Please enter your line:\n");

    while(fgets(str, 10, stdin)){

        //check for line break
        if(str[strlen(str)-1] == '\n'){
            str[strlen(str) - 1] = '\0';
            strcat(line, str);
            break;
        }

        strcat(line, str);

        line = realloc(line, strlen(line) + 10);
        str = realloc(str, strlen(str) + 10);
    }

    fprintf(stderr, "you entered %s\n", line);

    //just for testing
    /*
    fprintf(stderr, "\n str= %s \n", str );
    fprintf(stderr, "\n line= %s \n", line);
    */

    free(line);
    free(str);
    exit(EXIT_SUCCESS);
}

However, this looks awful. I need two char arrays. In char *str I will write input from stdin and concatenate it to char *line. str will only hold up to 10Bytes of chars and because of that I need to concatenate everything to line.

Is there a cleaner way to save the output from stdin in this case and apply some function on it? Am I doing this wrong? Can it be done without malloc and realloc?

7
  • 3
    You don't need to realloc(str), you never read more than 10 bytes at a time, you can just define str as char str[10]. Commented Apr 7, 2019 at 21:54
  • And then you've created a pretty typical C function. Usually you would make str be a power of 2, like 1024, or BUFSIZE because CPU's like that. Commented Apr 7, 2019 at 21:56
  • "will accept a line of any length from stdin " --> how about something more resilient to a hacker exploitation like "will accept a line of any length from stdin up to 1Mbyte"? Commented Apr 7, 2019 at 22:01
  • @chux The C library implementation and/or kernel will already handle that for you. If anyone tries to input an extremely long string the process will be shut down because of an out of memory error (realloc will return NULL). Commented Apr 7, 2019 at 22:03
  • Nothing awful-looking about it. In C you have to manage your own memory. If you don't know how much you need until runtime you have to dynamically allocate it as you are. You should also check the return values of malloc and realloc in case they fail. Commented Apr 7, 2019 at 22:04

1 Answer 1

1

This an example. You need to add the malloc & realloc result checking (I did not for the sake of simplicity)

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

#define CHUNK   32 

char *readline(void)
{
    size_t csize = CHUNK;
    size_t cpos = 0;
    char *str = malloc(CHUNK);
    int ch;
    while((ch = fgetc(stdin)) != '\n' && ch != '\r')
    {
        str[cpos++] = ch;
        if(cpos == csize)
        {
            csize += CHUNK;
            str = realloc(str, csize);
        }
    }
    str[cpos] = 0;
    return str;
}

int main()
{
    printf("\n%s\n", readline());

    return 0;
}

working example: https://onlinegdb.com/Sk9r4gOYV

You should also free the allocated memory when not needed anymore.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.