0

I want to make a program that accepts an arbitrary number of characters from user input, until "enter" is pressed, and stores them in a buffer.

Is there a way that to read characters from stdin without extracting them, count the characters, then allocate a buffer of precise size, finally copy the characters to the buffer.

Basically I do NOT want the way of using getc in loop and doubling the buffer size as it's running out.

EDIT: To make my intentions more clear, let me express my intuition. I imagine the stdin buffer the same as a file (which may or may not grow dynamically). So I should be able to seek to the end of it (representing the end of user input), counting the offset then rewind back. Something like

long const start = ftell(stdin);
fseek(stdin, 0, SEEK_END);
long const length = ftell(stdin) - start;
rewind(stdin);
sz ppeter
  • 1,698
  • 1
  • 9
  • 21
  • 1
    Is there a reason why you need to do it that way? – kaylum Jul 11 '20 at 08:02
  • 2
    POSIX has [`getline()`](https://www.man7.org/linux/man-pages/man3/getline.3.html) for reading lines of arbitrary length. – Shawn Jul 11 '20 at 08:19
  • 2
    `"Basically I do NOT want the way of using getc in loop and doubling the buffer size as it's running out."` -- Uh, Why? That is the basis for how all functions will handle it at a low-level. The low-level I/O provides a read buffer of `BUFSIZ` bytes. So it really matters not whether you use `fgetc`, `getc`, `fgets` or POSIX `getline`, other than a few difference in the initial allocated buffer size, that's the basis for how it is done. Even if you `mmap` the file, you still deal with the low-level read buffer. – David C. Rankin Jul 11 '20 at 09:00
  • `"Is there a way that to read characters from stdin without extracting them..."` it depends on whether the input is from a redirected file or not. If it is, `stdin` is seekable, otherwise not. – David C. Rankin Jul 11 '20 at 09:02
  • With the portable doubling approach, example performance is `868789 characters read in 0.003346 seconds.`, to an exactly sized buffer with 18 allocs beginning with 128-byte buffer. – David C. Rankin Jul 11 '20 at 09:27
  • so what can we do if you receive e.g. 1Gb of characters before you get the first newline ???? Why the doubling mechanism is so bad? why not to use a linear one, extending the buffer a fixed amount at each fillup? – Luis Colorado Jul 11 '20 at 23:33
  • Are you opposed to dynamically growing a buffer via doubling (which is basically what any such function would do internally or are you opposed to overallocating? You know you can use `realloc` to shrink an allocated buffer afterward, right? – jamesdlin Jul 12 '20 at 00:34

2 Answers2

0

The readline() command is supported on some systems, and can be added to those that don't support it.

From the man page:

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>

char *
readline (const char *prompt);

readline will read a line from the terminal and return it, using prompt as a prompt. If prompt is NULL or the empty string, no prompt is issued. The line returned is allocated with malloc(3); the caller must free it when finished. The line returned has the final newline removed, so only the text of the line remains.

r3mainer
  • 23,981
  • 3
  • 51
  • 88
0

So, from reading the comments and other responses, you don't like the solution of using readline because it's not standard. (well, it's not an ISO or ANSI standard, but it is pretty popular anyway)

You don't like the convention of doubling the buffer size (most probably the approach used by readline internally) but you don't specify why you don't like it. There are more approaches than doubling the buffer size, you can increment it a fixed amount for example, but I think you'll not be glad with that solution either.

What can we do then, if you receive 1Hb (One HexaByte, 1.0E18 bytes) of data before you receive the first newline character? How can we deal with that?

How can any standarization office define a way to deal with this, and specify a way to proceed correctly?

Do you actually believe you are asking the right question?

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31