You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

  1. Unnecessary Pointers in Struct: Using int* for fields like dan or mat was 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.
  2. Mismatched Function Prototypes: The citanje1 prototype in your header didn't match the definition, and the call in main was incorrect. We need to pass a pointer to your struct array so the allocation is visible in main.
  3. Incorrect Memory Handling: Your citanje1 function allocated memory but immediately freed it, so no data was returned to main. Also, you were using a double pointer (U**) when a single pointer array (U*) was sufficient.
  4. Missing Function Call: In case 3 of your switch statement, you declared citanje1 but never called it, leaving ucenici as NULL and causing undefined behavior when trying to print.
  5. 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 regular int to store direct values, eliminating unnecessary pointer management.
  • Proper Memory Allocation: citanje1 now takes a U** parameter to allocate the struct array and make it accessible in main. Memory is freed in main when 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, and brojanjelinija with proper file handling to ensure the program works end-to-end.

内容的提问来源于stack exchange,提问作者Inglorious Sloth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:26:03