1

Тема: Обробка двійкового файлу

Умова:(Фрагмент коду був готовий)

Прихований текст

Наступна програма дозволяє відредагувати k-й за порядком запис в базі — ввести інші оцінки.(Те що я повинен зробити)Вдосконалити наведену в даному розділі програму обробки списку студентів так, щоб вона коректно обробляла можливі помилки. Вдосконалити програму так, щоб вона дозволяла додавати до списку нових студентів.

#include "pch.h"
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define FNAME_LEN 80
#define SURNAME_LEN 20

typedef struct teg_student
{
    char surname[SURNAME_LEN];
    int prog_theor;
    int prog_lab;
}tstudent;

int main()
{
    char  fileName[FNAME_LEN];
    FILE *f;
    tstudent s;
    int k, r, x;
    printf("File of database?\n");
    gets_s(fileName);
    f = fopen(fileName, "r+");
    if (f == NULL)
    {
        fprintf(stderr, "Cannot be opened" );
        fclose(f);
        return  -1;
    }
    while (1) 
    {
        printf("Record number (-1 exit):\n ");
        scanf("%i", &k);
        if (k == -1)
        {
            break;
        }
        r = fseek(f, (long)k * sizeof(tstudent), SEEK_SET);
        fread(&s, sizeof(tstudent), 1, f);
        printf("Old record in the database\n");
        printf("%c %i %i", s.surname, s.prog_theor, s.prog_lab);
        printf("\nEnter the corrected marks: ");
        scanf("%i %i",&(s.prog_theor), &(s.prog_lab));
        fseek(f, (long)k * sizeof(tstudent), SEEK_SET);
        fwrite(&s, sizeof(tstudent), 1, f);
        printf("Add new record? 0 - yes, 1 - no\n");
        scanf("%i", &x);
        if (x == 0)
        {
            fseek(f, 0L, SEEK_END);
            printf("\nSurname: prog_theor: prog_lab:\n");
            scanf("%c %i %i", &(s.surname), &(s.prog_theor), &(s.prog_lab));
            fwrite(&s, sizeof(tstudent), 1, f);
        }
    }
    fclose(f);
    return 0;
}

Після додавання одного запису зразу зациклюється вивід одних і тих самих рядків. Старий запис бази виводиться непогано крім прізвища(вивело просто "х"), але я не впевнений чи воно взагалі є в двійковому файлі, бо на його орієнтовному місці пробіли.
Результат:
File of database?
in.dat
Record number (-1 exit):
1
Old record in the database
x 8 5
Enter the corrected marks: 4 5
Add new record? 0 - yes, 1 - no
0

Surname: prog_theor: prog_lab:
wrarr 6 7
Record number (-1 exit):
Old record in the database
x 4 5
Enter the corrected marks: Add new record? 0 - yes, 1 - no

Surname: prog_theor: prog_lab:
Record number (-1 exit):
Old record in the database
x 4 5
Enter the corrected marks: Add new record? 0 - yes, 1 - no

Surname: prog_theor: prog_lab:
Record number (-1 exit):

---------------------і так декілька раз---------------------------

2 Востаннє редагувалося Betterthanyou (24.04.2020 20:35:33)

Re: Обробка двійкового файлу

Це не двійковий файл, а текстовий відкривається

f = fopen(fileName, "r+");

fopen - http://www.cplusplus.com/reference/cstdio/fopen/

With the mode specifiers above the file is open as a text file. In order to open a file as a binary file, a "b" character has to be included in the mode string. This additional "b" character can either be appended at the end of the string (thus making the following compound modes: "rb", "wb", "ab", "r+b", "w+b", "a+b") or be inserted between the letter and the "+" sign for the mixed modes ("rb+", "wb+", "ab+").

Ось приклад відкриття двійкового файлу

fopen("path.bin","rb");

Ось приклад роботи з двійковим файлом
https://www.programiz.com/c-programming … put-output

#include <stdio.h>
#include <stdlib.h>

struct threeNum
{
   int n1, n2, n3;
};

int main()
{
   int n;
   struct threeNum num;
   FILE *fptr;

   if ((fptr = fopen("C:\\program.bin","wb")) == NULL){
       printf("Error! opening file");

       // Program exits if the file pointer returns NULL.
       exit(1);
   }

   for(n = 1; n < 5; ++n)
   {
      num.n1 = n;
      num.n2 = 5*n;
      num.n3 = 5*n + 1;
      fwrite(&num, sizeof(struct threeNum), 1, fptr); 
   }
   fclose(fptr); 
  
   return 0;
}
Подякували: grinyuk309, leofun012

3 Востаннє редагувалося koala (24.04.2020 21:09:40)

Re: Обробка двійкового файлу

Цикл, наскільки я бачу, у вас рівно один - while(1), і він містить scanf. Якщо програма не зупиняється на scanf - це означає, що попередній scanf не зміг прочитати те, що його просили, і потік (stdin) перебуває у стані помилки. Всі наступні запити до нього пропускаються, поки цей стан не скинути (clearerr).
Подивимося, що саме могло викликати збій.

grinyuk309 написав:
Add new record? 0 - yes, 1 - no
0

Тут все вводиться і ніби правильно.

grinyuk309 написав:
Record number (-1 exit):
Old record in the database

А тут вже іде збій, запит не відбувається.
Між ними лише

grinyuk309 написав:
Surname: prog_theor: prog_lab:
wrarr 6 7

Схоже, саме цей рядок і призвів до збою. Дивимося:

grinyuk309 написав:
scanf("%c %i %i", &(s.surname), &(s.prog_theor), &(s.prog_lab));

Отже, "%c %i %i". Символ, число, число. А ви що вводите? 6 символів ("wrarr ") перед числом. Причому ця помилка у вас уже далеко не вперше. Що саме вам заважає взяти підручник і розібратися, що таке символ, а що таке стрічка? Якщо щось не зрозуміло, можете тут питати.

Подякували: grinyuk309, leofun012

4

Re: Обробка двійкового файлу

koala написав:

Що саме вам заважає взяти підручник і розібратися, що таке символ, а що таке стрічка? Якщо щось не зрозуміло, можете тут питати.

Мені заважає каша в голові і невпевненість в своїх знаннях. Вчитись самостійно складно. Я вже запам'ятаю різницю між символом і стрічкою до кінця життя.