如何将TXT文件多行数据读取到结构体数组?指针问题求助
Fixing Your Student Data Reading Function
Let's break down the issues in your code and walk through the corrected version step by step. The main problems were unnecessary pointer usage in your struct, mismatched function prototypes, incorrect memory management, and missing function calls to populate your data array.
Key Issues Identified
- Unnecessary Pointers in Struct: Using
int*for fields likedanormatwas overcomplicating things—these are just integer values, not pointers to integers. This caused memory access errors since you weren't allocating memory for each pointer. - Mismatched Function Prototypes: The
citanje1prototype in your header didn't match the definition, and the call inmainwas incorrect. We need to pass a pointer to your struct array so the allocation is visible inmain. - Incorrect Memory Handling: Your
citanje1function allocated memory but immediately freed it, so no data was returned tomain. Also, you were using a double pointer (U**) when a single pointer array (U*) was sufficient. - Missing Function Call: In case 3 of your switch statement, you declared
citanje1but never called it, leavingucenicias NULL and causing undefined behavior when trying to print. - Lack of Error Checking: No checks for file opening failures, memory allocation issues, or incomplete line reads made debugging hard.
Corrected Code
Header.h
#ifndef HEADER_H #define HEADER_H typedef struct ucenik{ char ime[10]; char prezime[10]; int dan; int mjesec; int godina; int mat; int hrv; int eng; int hidr; int fiz; int term; int oet; int tehmat; } U; void kreiranje(void); void dodavanje(); int brojanjelinija(); void citanje1(U **ucenici); #endif // HEADER_H
Source.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "Header.h" int main(void) { int opcija = 0; U *ucenici = NULL; while (opcija != 4) { printf("\nOdaberite opciju:\n"); printf("1. Stvaranje datoteke ucenici.txt\n"); printf("2. Upisivanje novog ucenika\n"); printf("3. Pregled ucenika\n"); printf("4. Izlaz iz programa\n"); printf("Unesite opciju: "); scanf("%d", &opcija); switch (opcija) { case 1: kreiranje(); break; case 2: dodavanje(); break; case 3: // Free existing memory to avoid leaks before reloading if (ucenici != NULL) { free(ucenici); ucenici = NULL; } // Call citanje1 to allocate and fill the array citanje1(&ucenici); int j = brojanjelinija(); if (ucenici != NULL && j > 0) { printf("\nPopis ucenika:\n"); for (int i = 0; i < j; i++) { printf("%d. %s %s | Datum: %d.%d.%d | Ocjene: %d, %d, %d, %d, %d, %d, %d, %d\n", i + 1, ucenici[i].ime, ucenici[i].prezime, ucenici[i].dan, ucenici[i].mjesec, ucenici[i].godina, ucenici[i].mat, ucenici[i].hrv, ucenici[i].eng, ucenici[i].hidr, ucenici[i].fiz, ucenici[i].term, ucenici[i].oet, ucenici[i].tehmat); } } else { printf("\nNema ucenika u datoteci ili datoteka ne postoji.\n"); } break; case 4: // Clean up memory before exiting if (ucenici != NULL) { free(ucenici); ucenici = NULL; } printf("\nIzlaz iz programa.\n"); break; default: printf("\nNeispravna opcija! Pokusajte ponovo.\n"); break; } } return 0; } void citanje1(U **ucenici) { FILE *pok = fopen("ucenici.txt", "r"); if (!pok) { perror("Greska pri otvaranju datoteke za citanje"); *ucenici = NULL; return; } int broj = brojanjelinija(); if (broj <= 0) { fclose(pok); *ucenici = NULL; return; } // Allocate array of U structs *ucenici = (U*)malloc(broj * sizeof(U)); if (!*ucenici) { perror("Greska pri alokaciji memorije"); fclose(pok); return; } // Read each line into the struct array for (int i = 0; i < broj; i++) { int result = fscanf(pok, "%s %s %d %d %d %d %d %d %d %d %d %d %d", (*ucenici)[i].ime, (*ucenici)[i].prezime, &(*ucenici)[i].dan, &(*ucenici)[i].mjesec, &(*ucenici)[i].godina, &(*ucenici)[i].mat, &(*ucenici)[i].hrv, &(*ucenici)[i].eng, &(*ucenici)[i].hidr, &(*ucenici)[i].fiz, &(*ucenici)[i].term, &(*ucenici)[i].oet, &(*ucenici)[i].tehmat); if (result != 13) { printf("Greska pri citanju %d. linije.\n", i + 1); free(*ucenici); *ucenici = NULL; fclose(pok); return; } } fclose(pok); } void kreiranje(void) { FILE *pok = fopen("ucenici.txt", "w"); if (!pok) { perror("Greska pri kreiranju datoteke"); return; } printf("Datoteka ucenici.txt je uspjesno kreirana.\n"); fclose(pok); } void dodavanje() { FILE *pok = fopen("ucenici.txt", "a"); if (!pok) { perror("Greska pri otvaranju datoteke za dodavanje"); return; } U novi; printf("\nUnesite podatke za novog ucenika:\n"); printf("Ime: "); scanf("%s", novi.ime); printf("Prezime: "); scanf("%s", novi.prezime); printf("Datum rodenja (dan mjesec godina): "); scanf("%d %d %d", &novi.dan, &novi.mjesec, &novi.godina); printf("Ocjene (matematika hrvatski engleski hidraulika fizika termodinamika OET tehnička matematika): "); scanf("%d %d %d %d %d %d %d %d", &novi.mat, &novi.hrv, &novi.eng, &novi.hidr, &novi.fiz, &novi.term, &novi.oet, &novi.tehmat); fprintf(pok, "%s %s %d %d %d %d %d %d %d %d %d %d %d\n", novi.ime, novi.prezime, novi.dan, novi.mjesec, novi.godina, novi.mat, novi.hrv, novi.eng, novi.hidr, novi.fiz, novi.term, novi.oet, novi.tehmat); printf("Ucenik je uspjesno dodan u datoteku.\n"); fclose(pok); } int brojanjelinija() { FILE *pok = fopen("ucenici.txt", "r"); if (!pok) { return 0; } int count = 0; char buffer[256]; while (fgets(buffer, sizeof(buffer), pok) != NULL) { // Skip empty lines if (strlen(buffer) > 1 || (strlen(buffer) == 1 && buffer[0] != '\n')) { count++; } } fclose(pok); return count; }
Key Changes Explained
- Struct Simplification: Replaced all
int*fields with regularintto store direct values, eliminating unnecessary pointer management. - Proper Memory Allocation:
citanje1now takes aU**parameter to allocate the struct array and make it accessible inmain. Memory is freed inmainwhen reloading data or exiting to avoid leaks. - Error Handling: Added checks for file opening, memory allocation, and line reading failures to make the program robust and easier to debug.
- Complete I/O Functions: Implemented
kreiranje,dodavanje, andbrojanjelinijawith proper file handling to ensure the program works end-to-end.
内容的提问来源于stack exchange,提问作者Inglorious Sloth
相关产品推荐
相关产品推荐

