开发者

Is there a more efficient way of reading a formatted file in C than I have done?

开发者 https://www.devze.com 2022-12-13 17:26 出处:网络
I need to read in a formatted file that looks something like this. Code: HARK Name: Oscar MRTE: Train etc

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 writi开发者_运维知识库ng 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.


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 */;


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.


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


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.


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
0

精彩评论

暂无评论...
验证码 换一张
取 消