rmmstn
rmmstn

Reputation: 25

How to rewind stdin after reaching EOF?

I want to write a program that counts the frequency of all characters in stdin. My code:

#include <stdio.h>

#define MAX 1024

int main()
{
    char c1, c2;
    int count[MAX], i = 0, unique = 1;
    char arr[MAX];

    c1 = fgetc(stdin); 
    while(c1  != EOF)
    {
        unsigned counter = 0;
        for(int j = 0; j < i; j++)
        {
            if(c1 == arr[j])
            {
                unique = 0;
                break;
            }
        }
        if(unique)
            arr[i] = c1;

        ungetc(c1, stdin); 
        c2 = fgetc(stdin); // a
        while (c2 != EOF)
        {
            if(arr[i] == c2)
            {
                counter++; // 2
                c2 = fgetc(stdin); //\n
            }
            else if(arr[i] != c2 && c2 != EOF)
            {
                //ungetc(c2, stdin);
                c2 = fgetc(stdin); // a EOF
            }
        }
        count[i] = counter;
        rewind(stdin);
        printf("%c: %d\n", arr[i], count[i]);
        c1 = fgetc(stdin); // a
        i++;
    }

    return 0;
}

For the input: anna the output is: a: 2, so it counts all appearances for the 1st character but then EOF is reached, and I can't count any of the other characters. rewind(stdin) doesn't seem the work. What can I do?

Upvotes: 1

Views: 454

Answers (1)

AKX
AKX

Reputation: 168986

You can't rewind a piped stream (such as stdin when it is e.g. redirected into your program or being entered on the keyboard) since there is no "tape of characters" to rewind, it's just a stream with no "memory" of what was entered before.

As elucidated in the comments, if you do redirect in a file (./myapp < data.txt), it can be rewound just fine.

However, you don't need to rewind the file to count the characters in it. As I commented,

Keep track of all characters (assuming ASCII) in an array of 256 unsigned ints, read through the stream, print them at the end.

#include <stdio.h>

int main() {
  int c;
  unsigned int counts[256] = {0};

  while ((c = fgetc(stdin)) != EOF) {
    counts[c]++;
  }
  for (int i = 0; i < 256; i++) {
    if (counts[i]) {
      printf("%c: %d\n", i, counts[i]);
    }
  }
  return 0;
}

As other commenters mention, you also need to use an int, not a char, for the retval of fgetc(), since EOF is -1.

Upvotes: 2

Related Questions