views:

192

answers:

6

Hi,

I need to read in a formatted file that looks something like this.

Code: HARK

Name: Oscar

MRTE: Train

etc

At the moment my code looks like this.

FILE *file;
char unneeded[10];
char whitespace[2];
char actual[10];
file = fopen("scannertest.txt","r");
fscanf(file,"%s",unneeded); // this is the identifier and the colon (code:)
fscanf(file,"%[ ]",whitespace); // this takes in the white space after the colon.
fscanf(file,"%s",actual); // this is the value I actually need.
/**
* Do stuff with the actual variable
**/
fclose(file);

This way works for me but I don't think writing three fscanf()'s for each line in the text file is the best way to do it, especially as I will be doing it in a loop later.

I tried doing it like this:

fscanf(file, "%s %[ ] %s",unneeded,whitespace,real);

However this gave me weird symbols when I tried printing the output.

Any help is appreciated.

Thanks

A: 

If you are looking for ways to speed up your code, you could read in your entire file, or a buffer of the file. Reading an entire block at a time would be faster than reading in data as you need it.

You can then use sscanf on the buffer you read.

Brian R. Bondy
i tried using sscanf on a fgets() I had it like this.fgets(line,20,file);sscanf(line,"%s %[ ] %s,unneeded,whitespace,actual);But this still gave me the same problem, weird symbols going into the variables.
David Morris
Sounds more like you're overflowing a buffer if you're seeing strange symbols. Be very sure to check the return value of sscanf , so you know it actually read something.
nos
+3  A: 

The %s scanf specifier already ignores spaces. If you do

scanf("%s%s", unneeded, actual)

and the input is "Code: HARK", unneeded will have "Code:" and actual will have "HARK".

Warning: scanf is a troublesome function (it's "difficult" to use safely). If you want more safety, specify the maximum number of characters (remember the zero terminator) you are willing to accept into each string

scanf("%9s%9s", unneeded, actual); /* arrays defined with 10 elements */

The best is to use fgets followed by sscanf.

Edit after reading a comment to another answer

And remember to *always* check the return value of scanf.

chk = scanf("%9s%9s", unneeded, actual);
if (chk != 2) /* error reading data */;
pmg
Thanks a lot. Problem solved :)
David Morris
+1  A: 

In C, the file functions use buffered I/O. This means that fscanf won't be hitting the disk with each call so the performance loss of using 3 calls instead of 1 should be negligible.

However, the best thing to do is get your program working and then if it's too slow measure where the performance bottlenecks are and fix those first. It's not worth it trying to guess what sections of code will cause performance issues.

Whisty
A: 

I'm a sick person who misses coding in C every now and then. I wrote out something that appears to work:

Contents of test.txt

Code: HARK
Name: Oscar
MRTE: Train

Contents of text.c

#include <stdio.h>

#define MAX_LEN 256

int main(void)
{
  FILE *file;
  char str_buf[MAX_LEN + 1]; // One extra byte needed
                             // for the null character
  char unneeded[MAX_LEN+1];
  char actual[MAX_LEN+1];


  file = fopen("test.txt","r");

  while(fgets(str_buf, MAX_LEN + 1, file) != NULL)
  {
    sscanf(str_buf, "%s%s", unneeded, actual);
    printf("unneeded: %s\n", unneeded);
    printf("actual: %s\n", actual);
  }

  return 0;
}

Output of compiled code:

unneeded: Code:
actual: HARK
unneeded: Name:
actual: Oscar
unneeded: MRTE:
actual: Train
jeremyosborne
+1  A: 

Your code doesn't work because

fscanf(file,"%s",unneeded);
fscanf(file,"%[ ]",whitespace);
fscanf(file,"%s",actual);

does not do the same thing as

fscanf(file,"%s %[ ] %s", unneeded, whitespace, actual);

it is functionally equivalent

fscanf(file,"%s%[ ]%s", unneeded, whitespace, actual); // No spaces in fmt string

HTH

A: 

Thanks for all the pointers everyone, I've solved my problem now and have even managed to improve it :)

David Morris