in the text file is recorded "table" in this format

1.name surname |2.9.1904 |48 89 53 67 

and the structure is

 struct people{ char name[NAME]; int age; int data[4];}; 

how to count name surname in name , 1904 in age , and I tried 48 89 53 67 in int data[4]

  fscanf(table, ".%s|", data[i].name); fscanf(table, ".%d ", &data[i].age); fscanf(table, "%2d %2d %2d %2d", &data[i].marks[0], &data[i].marks[1], &data[i].marks[2], &data[i].marks[3]); 

but goes rubbish. Yes, I know that you won't get that name, but what's wrong with this format?

  • so it’s possible to write a template to a fscanth as soon as I know, and then transfer all the variables into one line. That is, instead of 3 do 1 - Herrgott
  • @Herrgott but there are dozens of lines of this format and I need to ignore some records that are different each time, except to create additional variables - Govard Moh
  • you did not understand. I do not know si, but in the pros, as I recall, an unlimited number of arguments to scanf is passed. I meant that you can write one fscanf(table, "template", data[i].name, data[i].age, ...) and then there will be no "rubbish" at the output - Herrgott
  • @Herrgott yes, unlimited, but every time you need to write a new format because spaces and numbers that need to be ignored - Govard Moh
  • but if there is any common logic, then regex can be written. Or if it is a one-time processing, remove all spaces and tabs and lead to a general view - Herrgott

1 answer 1

scanf is quite a powerful thing in capable hands. Here is a working example (for input data)

 #include <stdio.h> int main(void) { int id; char name[100]; char surname[100]; int day, month, year; int data[4]; int x = scanf("%i . %s %s %*[ \t|]%i.%i.%i %*[ |] %i %i %i %i",&id, name, surname, &day, &month, &year, &data[0], &data[1], &data[2], &data[3]); printf("x = %d\n", x); // выведем, сколько распарсилось полей // и сами поля printf("id = %i\nname = %s\nsurname = %s\ndate %i %i %i\n", id, name, surname, day, month, year); printf("data = %i %i %i %i\n", data[0], data[1], data[2], data[3]); return 0; } 

The string "formatting" (or all the same "formatted reading"?) Is quite complicated, but simple. Let's break it into pieces

 `%i .` прочитать число и точку. Тут все просто и по документации. `%s %s` прочитать два слова. Слова разделяются пробелами. `%*[ \t|]` это странная строка, которая говорит, читай любыме символы в скобках (пробел, табуляция и палочка (пайп)) процент-звездочка в начале говорит "читай, но не вноси в переменную". `%i.%i.%i` тут все просто - прочитать 3 целых числа через точку. `%*[ \t|]` тут аналогично. `%i %i %i %i` здесь снова все просто - 4 целых числа. 

the construction with square brackets is a bit specific and earlier its compilers did not support. But gcc supports exactly, and vs seems to be the same. But you need to check.

  • Can it be "safer" (in terms of detecting errors in the format and continuing to parse) to read the file line by line and use sscanf? - avp
  • Can. But maybe this is a one-time task. I did there not for nothing that I deduced the number of fields. - KoVadim