struktury i wskaźniki

0

Witam!
Taki kod najpierw zarzucę:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
void pobierz_dane(struct dane *wsk);

struct wyniki_badan {
        int cisnienie;
        int masa;
};  

struct dane {
        char *imie_nazw;
        long int  PESEL;
        struct wyniki_badan wyn;
};

int main(void) {
    int i;  
    int ln;

    struct dane osoba[4];

    /*dane wczytywać w funkcji dla każego oddzielnie - funkcja wczytuje dane jednego pacj */

    for (i=0; i<4; i++) {
        pobierz_dane(&osoba[i]);
    }

    printf("\n======================================\n");
    printf("%s", osoba[i].imie_nazw);
    for (i=0; i<4; i++) {
        printf("Imie i nazwisko pacjenta %d: %s\n", i+1, osoba[i].imie_nazw);
        printf("Pesel: %d\n", osoba[i].PESEL);
        printf("Masa: %d\n", osoba[i].wyn.masa);
        printf("Cisnienie: %d\n", osoba[i].wyn.cisnienie);
        printf("\n\n");
    }

    scanf("%d", &ln);
    return 0;
}

void pobierz_dane(struct dane *wsk) {
    char temp[81];
    int rozmiar;
    int licznik = 0;
    char pesel[11];
    char cisnienie[5];
    char masa[5];

    puts("Podaj imie i nazwisko: ");
    gets(temp);

    wsk->imie_nazw = (char*)malloc(strlen(temp) * sizeof(char));
    strcpy(wsk->imie_nazw, temp);

    puts("PESEL: ");
    gets(pesel);

    wsk->PESEL = atoi(pesel);

    puts("Cisnienie: ");
    gets(cisnienie);

    wsk->wyn.cisnienie = atoi(cisnienie);

    puts("Masa: ");
    gets(masa);

    wsk->wyn.masa = atoi(masa);
} 

Program ma pobierać dane 4rech osób. Jednak coś nie tak mam przy wskaźniku na char *imie_nazw, który jest w strukturze. Jako, że się dopiero uczę liczę na Waszą pomoc. Kompilator wywala błąd podczas próby wyświetlenia, coś w deseń: "Access violation reading location". W debugerze znalazłem informacje "bad ptr". Pytanie, jak poprawnie się dobrać wskaźnikiem do tego elementu?
Z góry dzięki za pomoc ;)

0
wsk->imie_nazw = (char*)malloc(strlen(temp) * sizeof(char));
wsk->imie_nazw = (char*)malloc(strlen(temp)+1);

potrzeba jednego więcej bajtu na kończący znak \0.
ponadto sizeof(char) jest zdefiniowany w standardzie jako zawsze równy 1.

możesz też dać na sztywno rozmiar c-stringa

struct dane {
                char imie_nazw[256]; // max 255 znaków + '\0'
                long int  PESEL;
                struct wyniki_badan wyn;
};

i wtedy bez malloc. w ten sposób nie musisz potem pamiętać o free.

0

Zapomniałem napisać, że musi być malloc - takie założenie.
Zmieniłem wiersz z malloc na taki jaki mi napisałeś. Dorzuciłem jeszcze free o którym zapomniałem. I dalej nie działa, więc gdzie jest jeszcze źle?

0

przenieś prototyp void pobierz_dane poniżej struct wyniki_badan i struct dane

0

Zrobione, ale bez większych zmian. Dalej błąd podczas wyświetlania.

0
einTier13 napisał(a)

Zrobione, ale bez większych zmian. Dalej błąd podczas wyświetlania.

Może:

wsk->imie_nazw = (char*)malloc(((strlen(temp) + 1) * sizeof(char));
Azarien napisał(a)

ponadto sizeof(char) jest zdefiniowany w standardzie jako zawsze równy 1.

To w C++. W C o ile się nie mylę char ma rozmiar równy typowi int i zwykle wynosi on 4 bajty. Możemy w C np. do typu char zapisać coś takiego:

char a = 'ABCD';

takie przypisanie jest ok i kompilator nie zgłosi błędu, ale tak naprawdę zapisze się tylko ta ostatnia litera.

0
wsk->imie_nazw = (char*)malloc((strlen(temp) + 1) * sizeof(char);

Co to ma robić? Chyba zapomniałeś o jeszcze jednym nawiasie:

wsk->imie_nazw = (char*)malloc(((strlen(temp) +1) * sizeof(char));

Oczywiście, nie jest zawsze równy 1. Wszystko zależy, dlatego daje się operator sizeof().

char a = 'ABCD'; == char a = 'D'; == char a = ('A', 'B', 'C', 'D');
0

Dalej mi nie działa - ten sam błąd. Co będzie źle w dalszym ciągu?

0
printf("%s", osoba[i].imie_nazw);

Skąd to wziąłeś? Od razu się na tym wywali. Masz już jedno takie w pętli, i tam ma być.

Pesel ma 11 cyfr, więc tablica znaków do wczytania powinna mieć długość przynajmniej 12 (przy wczytywaniu musisz zawsze zmieścić dodatkowy znak \0). W dodatku przy konwersji atoi, 11 cyfr nie zmieści się w int. Wygodniej byłoby przetrzymywać pesel w 11-elementowej tablicy znaków, zamiast zamieniać na liczbę.

Deklarację pobierz_dane powinieneś przenieść poniżej definicji struktury dane, albo strukturę zadeklarować wyżej.

Zamiast wczytywać ciśnienie i masę jako ciągi znaków, możesz przecież od razu użyć scanf("%d", &wsk->wyn.masa) (oczywiście z walidacją). To samo z ciśnieniem. Ponadto używanie gets jest niebezpieczne (możesz wylecieć poza tablicę, lepiej użyć fgets z ograniczeniem ilości znaków).

0

Oczywiście, nie jest zawsze równy 1. Wszystko zależy, dlatego daje się operator sizeof().

akurat przy char to nie zależy. zarówno w C jak i C++ sizeof(char) wynosi na pewno 1.

różnica jest przy sizeof('a'): w C++ zwróci sizeof(char), w C zwróci sizeof(int).

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0