0

I want to directly push a character array into the standard input stream stdin, but cannot think of a syntax that works. The closest I can think of is

freopen("input.txt", "r", stdin);

which reads the contents from a file "input.txt" into the FILE pointer stdin. But I don't like this approach because 1) it relies on creating an additional file, 2) I have to worry about creating one file for each of such requests, which can turn into a ton of txt files in a folder just for this simple purpose of assigning some character array to stdin.

Is there a better, more elegant way of doing this?

Tong Zhao
  • 91
  • 7
  • 4
    Might be better to redesign your code such that it's not hard-coded to read from stdin, but a custom-provided file descriptor. – iBug Jan 06 '23 at 19:28
  • @iBug thank you for your suggestion. In my case, I am deliberately doing this to test a program that involves user input. Basically, I want to exhaust all possible user inputs to bash the program. Do you think there is a better alternative for my task? – Tong Zhao Jan 06 '23 at 19:32
  • Investigate how much pushback you can do in your environment with `ungetc()`. Some systems (IIRC, the older Unix systems like Solaris, HP-UX, AIX) have very limited pushback — the standard only guarantees one byte and they adhere to a limit close to that. Many modern systems (Linux, macOS) give you significant buffers — up to about 4 KiB under testing, and I didn't push it beyond that. See [`ungetc()` — number of bytes of pushback?](https://stackoverflow.com/q/7814816/15168) for the details (from a few years ago, but the test code is in my answer there). – Jonathan Leffler Jan 06 '23 at 19:32
  • 4
    If you want to test a program with user input, it's still a better idea to redirect stdin to a file or another controlled source *from the outside* (e.g. a shell script) than trying to fiddle `freopen` or `ungetc` or what have you. – iBug Jan 06 '23 at 19:39

1 Answers1

2

You're mistaken about this assumption:

which reads the contents from a file "input.txt" into the FILE pointer stdin.

This is not what freopen does! What this does is replacing the file/connection of stdin itself.

This might be a perfectly legitimate thing to do, specifically if your program isn't expecting to have its input being redirected by its creating process.

Within the C standard library you're somewhat limited in what you can do. But if you're allowed to use POSIX syscalls, then you could to the following:

  1. dup the file descriptor of stdin into a temporary.
  2. create an anonymous pipe using the pipe syscall.
  3. dup2 the reading end of the pipe over the stdin file descriptor.
  4. write the character array to the writing end of the pipe.
  5. restore stdin by dup2 the file descriptor saved in step 1) over stdin
  6. close the temporary file descriptor obtained in 1
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Thank you, I think you are right that my understanding of `freopen` was not entirely correct. I am fine with writing hypothetical inputs into an `input.txt` file and then pointing `stdin` to the file. However, this process only fulfills one program test for me. I need to perform dozens of such tests, and I wonder if there is a way to avoid dozens of separate text files lying in the test folder. Your second suggestion regarding POSIX is enticing but something new to me. I need to read up on that and then come back. I hope the learning curve isn't that steep. – Tong Zhao Jan 06 '23 at 19:48