To read a line, use fgets()
char buffer[100];
while (fgets, buffer, sizeof buffer, istream) != NULL) {
Then scan the line against the various formats, each ending with " %n".  "%n" records the scan position, if it got that far.  Additional tests could check for extraneous extras character starting at n.
  int num1, num2, num3;
  char last[sizeof buf];
  char first[sizeof buf];
  char code[sizeof buf];
  double rate;
  int n = 0;
  //               v..v..v..v...v..v..v spaces optional here
  sscanf(buffer, "i %d %s %s %lf %d %s %d %n",
    &num1, last, first, &rate, &num2, code, &num3, &n);
  if (n) {
    Handle_i();
    continue;
  }
  sscanf(buffer, "q %d %n", &num1, &n);
  if (n) {
    Handle_q();
    continue;
  }
  sscanf(buffer, "ra %d %n", &num1, &num2, &n);
  if (n) {
    Handle_ra();
    continue;
  }
  sscanf(buffer, "e %n", &n);
  if (n) {
    Handle_e();
    continue;
  }
  ...
  fail();
}
As each format begins with a unique letter pattern, the sscanf() will quickly exit on mis-match.
Alternative, code could parse out the initial letters for a slightly more efficient decision tree.  Suspect profiling will show little performance difference.  
As with any complex format, consider how one would maintain the code and it is bound to evolve.