0

I have a terrible problem with my code. I am saving some data by:

void savetofile()
{
  fprintf(savefile, "%d\n", run); // here are 1 or 2 characters
  fprintf(savefile, "%d\n", gender); // 1 character
  fprintf(savefile, "%s\n", name); // here is string, max 20 characters
  fprintf(savefile, "%d\n", points1); // between 1 and 3 characters
  fprintf(savefile, "%d\n", points2); // between 1 and 3 characters
}

How can I read them after saving? Can I somehow specific line with:

fscanf(savefile, "%d", &gender);

to read specificaly line 2?

Maybe when I save data to file as that:

void savetofile()
{
  fprintf(savefile, "%d ", run); // here are 1 or 2 characters
  fprintf(savefile, "%d ", gender); // 1 character
  fprintf(savefile, "%s ", name); // here is string, max 20 characters
  fprintf(savefile, "%d ", points1); // between 1 and 3 characters
  fprintf(savefile, "%d ", points2); // between 1 and 3 characters
}

It will be easier to read?

Piyin
  • 1,823
  • 1
  • 16
  • 23
  • If you printed 5 lines to the file, you should read those 5 lines from that file, using the same format that you used to write each line. – FredK Nov 29 '17 at 22:12
  • 1
    1) Use the first `void savetofile()` 2) post examples of your output. 3) post the definitions of your variables. – chux - Reinstate Monica Nov 29 '17 at 22:14
  • 1
    Is `gender` really an `int` (or do you intend to store it as an `int`), or is it a `char`? Consider using `fgets()` to read lines of input from the file, and `sscanf()` to parse each line. – ad absurdum Nov 29 '17 at 22:14
  • Tip: when writing a name, recall some names have spaces in them. So write with sentinels like `fprintf(savefile, "<%s>\n", name);`. Then reading is easier to detect mal-formed data. – chux - Reinstate Monica Nov 29 '17 at 22:19
  • @chux output is: 1 1 Barbara 100 50 – Shanduur Nov 29 '17 at 23:02
  • 1
    Your main issue is to specify your file format. Once that is done, coding the parser is common practice, and you'll find many books about parsing (and compiling: most compiler books are studying parsing techniques in a first part) – Basile Starynkevitch Nov 29 '17 at 23:44

2 Answers2

1

There are many ways to solves this - each with strengths and weaknesses.

How about a single line with "tags", markers in the file to indicate data ID?

void savetofile(int run, int gender, char *name, int points1, int points2) {
  fprintf(savefile, "r:%d g:%d n:\"%s\" p1:%d p2:%d\n", 
    run, gender, name, points1, points2);
}

// return 1: success, EOF:no more 0:problem data
int readfile(int &run, int &gender, char *name, int *points1, int *points2) {
  char buf[100];  // Size: 2x longest expected line
  if (fgets(buf, sizeof buf, savefile) == NULL) return EOF;
  if (sscanf(buf, "r:%2d g:%1d n:\"%19[^\"]\" p1:%3d p2:%3d", 
    &run, &gender, name, &points1, &points2) != 5) return 0;
  return 1;
}

All sorts of other improvements possible, especially additional error checking, but the above is to realize some ideas.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

fscanf don't know and don't care about lines since the end-of-line marker (e.g. the newline character) is considered as some space character. In particular, spaces, tabs, newlines in the fscanf format control strings play the same role (skipping space-like characters) and are handled likewise by fscanf when occurring as input.

If you care about a specific line, you should read line by line your input file. Use getline like here (or fgets) to read lines. In other words, if you care about lines, you need to do a sequential read.

You could parse your file twice, and remember (e.g. in some dynamically allocated array) all the offsets of line starts in the first pass (use ftell and later fseek in your second pass; direct access is only possible to some byte offset, not to some line number).

Once you have read some line, you could use common parsing techniques (notably sscanf with %n, or your recursive descent parser) to parse it.

Be sure to specify on paper the syntax of your textual file format, e.g. in EBNF notation. The role of newlines is your choice (you could consider them as spaces, by using lexing and parsing techniques on the entire file, or you could process line by line by reading each line and parsing that line).

BTW, your use case would rather suggest some other approaches. E.g. using databases (perhaps Sqlite), using indexed files à la gdbm, encoding your data in some textual format like JSON, XML, or YAML (for which you'll find many libraries).

Notice that most books about compilers (notably the Dragon Book) starts with an explanation of various parsing techniques. You should read that part.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547