16-bo‘lim
Fayllar bilan ishlash
fopen rejimlari, matn va ikkilik fayllar, satr bo'yicha o'qish, fprintf va fscanf, xatolarni boshqarish va fayl ichida harakatlanish.
Ushbu bo‘lim mundarijasi
Dastur tugagach, xotiradagi ma'lumot yo'qoladi. Uni saqlab qolish uchun fayl kerak.
Fayl ochish va yopish #
FILE *fayl = fopen("malumot.txt", "r");
if (fayl == NULL) {
/* fayl ochilmadi */
}
fclose(fayl);
| Rejim | Ma'nosi | Fayl yo'q bo'lsa | Mavjud bo'lsa |
|---|---|---|---|
"r" | O'qish | NULL qaytaradi | ochadi |
"w" | Yozish | yaratadi | butunlay o'chiradi |
"a" | Oxiriga qo'shish | yaratadi | oxiriga yozadi |
"r+" | O'qish va yozish | NULL qaytaradi | ochadi |
"w+" | O'qish va yozish | yaratadi | o'chiradi |
"a+" | O'qish va qo'shish | yaratadi | oxiriga yozadi |
"rb" | Ikkilik o'qish | NULL | ochadi |
"wb" | Ikkilik yozish | yaratadi | o'chiradi |
"w" rejimi faylni o'chiradiFILE *f = fopen("muhim.txt", "w"); /* mavjud mazmun YO'QOLDI */
Bu eng ko'p uchraydigan halokatli xato. Mavjud faylga qo'shmoqchi
bo'lsangiz - "a" ishlating.
Faylga yozish #
#include <stdio.h>
int main(void) {
FILE *fayl = fopen("talabalar.txt", "w");
if (fayl == NULL) {
fprintf(stderr, "Faylni ochib bo'lmadi\n");
return 1;
}
fprintf(fayl, "Husanboy Qodirov 25 4.60\n");
fprintf(fayl, "Malika Yusupova 21 4.90\n");
fprintf(fayl, "Nodira Sobirova 24 4.30\n");
fclose(fayl);
printf("Fayl yozildi.\n");
return 0;
}
Fayl yozildi.
fprintf - printf ning fayl variantiprintf("Salom\n"); /* ekranga */
fprintf(stdout, "Salom\n"); /* xuddi shu narsa */
fprintf(stderr, "Xato!\n"); /* xatolar oqimiga */
fprintf(fayl, "Salom\n"); /* faylga */
Xato xabarlarini doim stderr ga yozing. Shunda ular alohida
yo'naltirilishi mumkin:
./dastur > natija.txt 2> xatolar.txt
Fayldan o'qish #
#include <stdio.h>
int main(void) {
FILE *yozish = fopen("sonlar.txt", "w");
if (yozish == NULL) {
return 1;
}
for (int i = 1; i <= 5; i++) {
fprintf(yozish, "%d\n", i * 11);
}
fclose(yozish);
FILE *oqish = fopen("sonlar.txt", "r");
if (oqish == NULL) {
fprintf(stderr, "Fayl topilmadi\n");
return 1;
}
int son;
int yigindi = 0;
while (fscanf(oqish, "%d", &son) == 1) {
printf("O'qildi: %d\n", son);
yigindi += son;
}
fclose(oqish);
printf("Yig'indi: %d\n", yigindi);
return 0;
}
O'qildi: 11
O'qildi: 22
O'qildi: 33
O'qildi: 44
O'qildi: 55
Yig'indi: 165
fscanf natijasini tekshiringwhile (fscanf(fayl, "%d", &son) == 1) { ... }
fscanf muvaffaqiyatli o'qilgan qiymatlar sonini qaytaradi. Fayl
tugaganda yoki format mos kelmaganda bu son kamayadi va sikl to'xtaydi.
while (!feof(fayl)) yozmang - bu klassik xato. feof fayl oxiriga
yetilgandan keyin rost bo'ladi, shuning uchun oxirgi element ikki
marta qayta ishlanadi.
Satr bo'yicha o'qish #
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *yozish = fopen("shaharlar.txt", "w");
if (yozish == NULL) {
return 1;
}
fprintf(yozish, "Namangan\nToshkent\nSamarqand\nBuxoro\n");
fclose(yozish);
FILE *oqish = fopen("shaharlar.txt", "r");
if (oqish == NULL) {
return 1;
}
char qator[256];
int raqam = 1;
while (fgets(qator, sizeof(qator), oqish) != NULL) {
qator[strcspn(qator, "\n")] = '\0'; /* qator oxirini kesamiz */
printf("%d. %s (%zu harf)\n", raqam++, qator, strlen(qator));
}
fclose(oqish);
return 0;
}
1. Namangan (8 harf)
2. Toshkent (8 harf)
3. Samarqand (9 harf)
4. Buxoro (6 harf)
fgets - fayl o'qishning eng ishonchli usulifgets bufer hajmini biladi va undan oshib ketmaydi. Har bir qatorni
alohida o'qib, keyin uni tahlil qilish - eng xavfsiz yondashuv.
Uzun qator bufergacha sig'masa, fgets uni bo'lib o'qiydi va keyingi
chaqiruvda davomini beradi.
Strukturalarni faylga saqlash #
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char ism[40];
int yosh;
double baho;
} Talaba;
int saqla(const char *fayl_nomi, const Talaba guruh[], int soni) {
FILE *f = fopen(fayl_nomi, "w");
if (f == NULL) {
return 0;
}
for (int i = 0; i < soni; i++) {
fprintf(f, "%s;%d;%.2f\n", guruh[i].ism, guruh[i].yosh, guruh[i].baho);
}
fclose(f);
return 1;
}
int yukla(const char *fayl_nomi, Talaba guruh[], int maks) {
FILE *f = fopen(fayl_nomi, "r");
if (f == NULL) {
return 0;
}
char qator[200];
int soni = 0;
while (soni < maks && fgets(qator, sizeof(qator), f) != NULL) {
qator[strcspn(qator, "\n")] = '\0';
char *ism = strtok(qator, ";");
char *yosh = strtok(NULL, ";");
char *baho = strtok(NULL, ";");
if (ism == NULL || yosh == NULL || baho == NULL) {
continue; /* buzilgan qatorni o'tkazamiz */
}
strncpy(guruh[soni].ism, ism, sizeof(guruh[soni].ism) - 1);
guruh[soni].ism[sizeof(guruh[soni].ism) - 1] = '\0';
guruh[soni].yosh = atoi(yosh);
guruh[soni].baho = atof(baho);
soni++;
}
fclose(f);
return soni;
}
int main(void) {
Talaba asl[] = {
{"Husanboy Qodirov", 25, 4.60},
{"Malika Yusupova", 21, 4.90},
{"Nodira Sobirova", 24, 4.30}
};
if (!saqla("guruh.csv", asl, 3)) {
fprintf(stderr, "Saqlab bo'lmadi\n");
return 1;
}
Talaba yuklangan[10];
int soni = yukla("guruh.csv", yuklangan, 10);
printf("%d ta yozuv yuklandi:\n", soni);
for (int i = 0; i < soni; i++) {
printf(" %-18s %3d %.2f\n",
yuklangan[i].ism, yuklangan[i].yosh, yuklangan[i].baho);
}
return 0;
}
3 ta yozuv yuklandi:
Husanboy Qodirov 25 4.60
Malika Yusupova 21 4.90
Nodira Sobirova 24 4.30
Bu misolda uchta sarlavha ishlatilgan:
| Sarlavha | Nima uchun |
|---|---|
stdio.h | fopen, fprintf, fgets |
stdlib.h | atoi, atof |
string.h | strtok, strncpy, strcspn |
stdlib.h ni unutsangiz, atoi noto'g'ri talqin qilinadi va natija
kutilmagan bo'ladi. -Wall bayrog'i bu haqda ogohlantiradi - shuning
uchun ogohlantirishlarni hech qachon e'tiborsiz qoldirmang.
strtok asl satrni buzadistrtok ajratuvchi belgilar o'rniga '\0' yozadi. Ya'ni u satrni
o'zgartiradi.
Shuning uchun uni doimiy satrga qo'llab bo'lmaydi:
strtok("a;b;c", ";"); /* QULAYDI: literal o'zgartirib bo'lmaydi */
Bizning misolda qator - o'zgaruvchan massiv, shuning uchun xavfsiz.
Ikkilik fayllar #
#include <stdio.h>
typedef struct {
char ism[40];
int yosh;
double baho;
} Talaba;
int main(void) {
Talaba asl[] = {
{"Husanboy Qodirov", 25, 4.60},
{"Malika Yusupova", 21, 4.90}
};
FILE *yozish = fopen("guruh.bin", "wb");
if (yozish == NULL) {
return 1;
}
fwrite(asl, sizeof(Talaba), 2, yozish);
fclose(yozish);
Talaba yuklangan[2];
FILE *oqish = fopen("guruh.bin", "rb");
if (oqish == NULL) {
return 1;
}
size_t oqilgan = fread(yuklangan, sizeof(Talaba), 2, oqish);
fclose(oqish);
printf("%zu ta yozuv o'qildi:\n", oqilgan);
for (size_t i = 0; i < oqilgan; i++) {
printf(" %-18s %3d %.2f\n",
yuklangan[i].ism, yuklangan[i].yosh, yuklangan[i].baho);
}
return 0;
}
2 ta yozuv o'qildi:
Husanboy Qodirov 25 4.60
Malika Yusupova 21 4.90
fwrite strukturani xotiradagi ko'rinishi bilan yozadi - padding
bilan birga.
Shuning uchun bir kompyuterda yozilgan fayl boshqasida noto'g'ri o'qilishi mumkin:
- turli baytlar tartibi (endianness);
- turli tekislash qoidalari;
- turli
inthajmi.
Fayl boshqa tizimga ko'chishi kerak bo'lsa - matn formatidan (CSV, JSON) foydalaning.
Shuningdek, strukturada ko'rsatkich bo'lsa, uni fwrite bilan
saqlab bo'lmaydi: manzil boshqa ishga tushirishda ma'nosiz bo'ladi.
Fayl ichida harakatlanish #
#include <stdio.h>
int main(void) {
FILE *f = fopen("alifbo.txt", "w+");
if (f == NULL) {
return 1;
}
fputs("ABCDEFGHIJ", f);
fseek(f, 0, SEEK_SET); /* boshiga */
printf("Birinchi belgi : %c\n", (char) fgetc(f));
fseek(f, 4, SEEK_SET); /* boshidan 4 bayt */
printf("5-belgi : %c\n", (char) fgetc(f));
fseek(f, -2, SEEK_END); /* oxiridan 2 bayt orqaga */
printf("Oxiridan 2-si : %c\n", (char) fgetc(f));
fseek(f, 0, SEEK_END);
printf("Fayl hajmi : %ld bayt\n", ftell(f));
fclose(f);
return 0;
}
Birinchi belgi : A
5-belgi : E
Oxiridan 2-si : I
Fayl hajmi : 10 bayt
| Funksiya | Nima qiladi |
|---|---|
fseek(f, siljish, boshlanish) | Ko'rsatkichni ko'chiradi |
ftell(f) | Joriy o'rinni qaytaradi |
rewind(f) | Boshiga qaytaradi |
SEEK_SET | Fayl boshi |
SEEK_CUR | Joriy o'rin |
SEEK_END | Fayl oxiri |
Fayl hajmini aniqlash #
#include <stdio.h>
long fayl_hajmi(const char *nom) {
FILE *f = fopen(nom, "rb");
if (f == NULL) {
return -1;
}
fseek(f, 0, SEEK_END);
long hajm = ftell(f);
fclose(f);
return hajm;
}
int main(void) {
FILE *f = fopen("sinov.txt", "w");
if (f == NULL) {
return 1;
}
fputs("Salom, dunyo!", f);
fclose(f);
long hajm = fayl_hajmi("sinov.txt");
if (hajm >= 0) {
printf("Fayl hajmi: %ld bayt\n", hajm);
} else {
printf("Faylni ochib bo'lmadi\n");
}
return 0;
}
Fayl hajmi: 13 bayt
Xatolarni to'g'ri boshqarish #
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(void) {
FILE *f = fopen("mavjud_emas_12345.txt", "r");
if (f == NULL) {
fprintf(stderr, "Xato: %s\n", strerror(errno));
printf("Fayl ochilmadi - dastur davom etadi\n");
return 0;
}
fclose(f);
return 0;
}
Xato: No such file or directory
Fayl ochilmadi - dastur davom etadi
errno va strerrorStandart funksiya xato qilganda errno global o'zgaruvchisiga xato
kodini yozadi. strerror uni o'qishli matnga aylantiradi:
Xato: No such file or directory
perror esa buni bir qadamda qiladi:
if (f == NULL) {
perror("mavjud_emas.txt");
}
Natija: mavjud_emas.txt: No such file or directory
fclose ni unutmangHar bir fopen uchun bitta fclose bo'lishi kerak. Aks holda:
- yozilgan ma'lumot buferda qolib ketishi mumkin;
- operatsion tizim resursi band bo'lib qoladi;
- ko'p fayl ochsangiz, chegaraga yetasiz.
Ayniqsa erta qaytishlarda ehtiyot bo'ling:
FILE *f = fopen("a.txt", "r");
if (f == NULL) return 1;
if (biror_shart) {
return 1; /* XATO: fayl yopilmadi */
}
fclose(f);
To'g'ri yo'l - qaytishdan oldin yopish:
if (biror_shart) {
fclose(f);
return 1;
}
Faylni satrma-satr nusxalash #
#include <stdio.h>
int nusxala(const char *manba, const char *maqsad) {
FILE *m = fopen(manba, "rb");
if (m == NULL) {
return 0;
}
FILE *n = fopen(maqsad, "wb");
if (n == NULL) {
fclose(m);
return 0;
}
char bufer[4096];
size_t oqilgan;
while ((oqilgan = fread(bufer, 1, sizeof(bufer), m)) > 0) {
if (fwrite(bufer, 1, oqilgan, n) != oqilgan) {
fclose(m);
fclose(n);
return 0;
}
}
fclose(m);
fclose(n);
return 1;
}
int main(void) {
FILE *f = fopen("asl.txt", "w");
if (f == NULL) {
return 1;
}
fputs("Bu fayl nusxalanadi.\nIkkinchi qator.\n", f);
fclose(f);
if (nusxala("asl.txt", "nusxa.txt")) {
printf("Nusxalandi.\n");
FILE *tekshir = fopen("nusxa.txt", "r");
char qator[100];
while (fgets(qator, sizeof(qator), tekshir) != NULL) {
printf(" %s", qator);
}
fclose(tekshir);
}
return 0;
}
Nusxalandi.
Bu fayl nusxalanadi.
Ikkinchi qator.
- Faylga o'z ismingizni yozing va uni qayta o'qing.
"w"rejimida mavjud faylni ochib, mazmuni yo'qolishini ko'ring."a"rejimi bilan faylga qo'shimcha qatorlar qo'shing.- Fayldagi qatorlar sonini hisoblang.
- Fayldagi so'zlar sonini hisoblang.
- CSV formatida talabalar ro'yxatini saqlang va yuklang.
strtokbilan CSV qatorini bo'laklarga ajrating.- Strukturani ikkilik faylga saqlang va o'qing.
fseekvaftellbilan fayl hajmini aniqlang.- Faylni nusxalovchi dastur yozing (buferli o'qish bilan).
Xulosa #
fopenfayl ochadi,fcloseyopadi - har biriga juft kerak.fopennatijasini doimNULLga tekshiring."w"rejimi mavjud faylni o'chiradi - qo'shish uchun"a".fprintf/fscanf- matn bilan,fwrite/fread- ikkilik bilan.fscanfnatijasini tekshiring;while (!feof(f))yozmang.fgetseng ishonchli o'qish usuli - bufer hajmini biladi.strtokasl satrni o'zgartiradi.- Ikkilik fayl ko'chma emas - boshqa tizimda buzilishi mumkin.
fseekvaftellbilan fayl ichida harakatlanish mumkin.- Xato sababini
strerror(errno)yokiperrorberadi. - Erta qaytishlarda faylni yopishni unutmang.
Keyingi bo'limda preprotsessor va ko'p faylli loyihalarni ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.