5

Hello guys I need a help. I want to read from stdin by 16 bytes. Every byte I convert into hexadecimal form. Is there a way I can use read() function to read NOT from the beginning, but for example from the second byte? Also how can I know if I have read the whole stdin? - This way I could call this function in a cycle until I have read the whole stdin

This is a function I made:

void getHexLine()
{

  int n = 16;
  char buffer[n];
  read(STDIN_FILENO, buffer, n);
  buffer[n]='\0';
  //printf("%08x", 0); hex number of first byte on line - not working yet
  putchar(' ');
  putchar(' ');
  //converting every byte into hexadecimal
  for (int i = 0;i < 16;i++ )
  {
    printf("%x", buffer[i]);
    putchar(' ');
    if (i == 7 || i == 15)
        putchar(' ');


  }
  printf("|%s|\n", buffer);
} 

The output should be like this but with an option to start from second byte for example.

[vcurda@localhost proj1]$ echo "Hello, world! This is my program." | ./proj1
48 65 6c 6c 6f 2c 20 77  6f 72 6c 64 21 20 54 68  |Hello, world! Th|
69 73 20 69 73 20 6d 79  20 70 72 6f 67 72 61 6d  |is is my program|

This is a school project so I cant use malloc, scanf and <string.h>. I would be really glad if I get some help and sorry for my not very understandable english.

Vojta Čurda
  • 51
  • 1
  • 2

2 Answers2

3

stdin is not seekable. You can read bytes in, but you can't rewind or fast forwards. EOF (-1) means end of input in stdin as with a regular file, but it's a bit of a looser concept if you are conducting an interactive dialogue with the user.

Basically stdin is line oriented, and it's best to use the pattern printf() prompt, enter whole line from user, printf() results if applicable and another prompt, read in whole line from user, and so on, at least at first until you get used to programming stdin.

To start from the second byte then becomes easy. Read in the whole line, then start from i = 1 instead of i = 0 as you parse it.

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
  • fseek will return EBADF if the stream is non-seekable. Otherwise it will do something which corresponds in some way to a seek, but if you know how to do that successfully on stdin you will post a different kind of question to stackoverflow. – Malcolm McLean Oct 15 '16 at 20:31
  • Seeks may succeed if stdin is a redirected regular file. But it is probably always good to assume that stdin isn't seekable. – Petr Skocik Oct 15 '16 at 20:38
  • 4
    If I run a program `./some_program < plain_file`, the standard input is seekable. If you said "Standard input is not necessarily seekable" then there'd be no quibbling — if it is a pipe, or terminal, then standard input is not seekable. But the blanket statement is incorrect. – Jonathan Leffler Oct 15 '16 at 20:56
  • Computers usually allow you to put various layers between the different components, which can have strange effects. – Malcolm McLean Oct 15 '16 at 21:20
  • 2
    Change "stdin is not seekable" to "a pipe, socket, or terminal are not seekable." This use of stdin is perfectly seekable: `./proj1 – Ian D. Allen Nov 06 '21 at 16:52
3

Is there a way I can use read() function to read NOT from the beginning, but for example from the second byte?

Most universally, you can simply ignore the read-in bytes you're not interested in.

Sometimes you will be able to lseek, e.g. if you run your program with a regular file set to its STDIN as in:

./a.out < /etc/passwd

but lseek will fail on STDINs that are terminals, pipes, character devices, or sockets.

how can I know if I have read the whole stdin?

read will return 0 at the end of the file.


Consult the manual pages for more information. Generally, you should check your return codes and account for short reads. Your function should probably return an int so that it has a way to communicate a possible IO error.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142