Question

I have an existing program where a message (for example, an email, or some other kind of message) will be coming into a program on stdin. I know stdin is a FILE* but I'm somewhat confused as to what other special characteristics it has. I'm currently trying to add a check to the program, and handle the message differently if it contains a particular line (say, the word "hello"). The problem is, I need to search through the file for that word, but I still need stdin to point to its original location later in the program. An outline of the structure is below:

Currently:

//actual message body is coming in on stdin
read_message(char type)
{

//checks and setup

if(type == 'm')
  {
    //when it reaches this point, nothing has touched stdin
        open_and_read(); //it will read from stdin
  }

//else, never open the message
}

I want to add another check, but where I have to search the message body. Like so:

//actual message body is coming in on stdin
read_message(char type)
{

//checks and setup

//new check
if(message_contains_hello())   //some function that reads through the message looking for the word hello
{
     other_functionality();
}

if(type == 'm')
  {
        //when it reaches this point, my new check may have modified stdin
    open_and_read(); //it will read from stdin
  }

//else, never open the message
}

The problem with this is that to search the message body, I have to touch the file pointer stdin. But, if I still need to open and read the message in the second if statement (if type = 'm'), stdin needs to point to the same place it was pointing at the start of the program. I tried creating a copy of the pointer but was only successful in creating a copy that would also modify stdin if modified itself.

I don't have a choice about how to pass the message - it has to stay on stdin. How can I access the actual body of a message coming in on stdin without modifying stdin itself? Basically, how can I read from it, and then have another function be able to read from the beginning of the message as well?

Was it helpful?

Solution

The short answer is that you can't. Once you read data from standard input, it's gone.

As such, your only real choice is to save what you read, and do the later processing on that rather than reading directly from standard input. If your later processing demands reading from a file, one possibility would be to structure this as two separate programs, with one acting as a filter for the other.

OTHER TIPS

In general, you can only read bytes from stdin once. There is no fseek() functionality. To solve this problem, you can read the bytes into a buffer in your program, look at the bytes, and then pass the buffer off to another function that actually does something with the rest of the data.

Depending on your program, you may need to only read some of the data on stdin, or you may need to read all of it into that buffer. Either way, you will probably have to modify the existing code in the program in some way.

I know stdin is a FILE* but I'm somewhat confused as to what other special characteristics it has.

Well, it's opened for reading. But it's not guaranteed to be seekable, so you'll want to read in its contents entirely, then handle the resulting string (or list of strings, or whatever).

You should use and take advantage of buffering (<stdio.h> provides buffered I/O, but see setbuf).

My suggestion is to read your stdin line by line, e.g. using getline. Once you've read an entire line, you can do some minimal look-ahead inside.

Perhaps you might read more about parsing techniques.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top