Dodanie danych osoby do struktury kończy się błędem - dlaczego?

0

Witajcie, mój problem dotyczy tego:

Mam taką strukturę:

		struct osoba
{
	char nazwisko[30];
	char imie[30];
	int wiek;
	int plec;
	int wzrost;
	osoba * nastepna_instancja;
};

później chcę dodać do niej osoby:

printf("\nPodaj imie i nazwisko osoby.\n<(wpisz: imie<spacja>nazwisko)");
		scanf("%s %s", &object.imie, &object.nazwisko);
		printf("\nWiek osoby:");
		scanf("%d", &object.wiek);
		printf("\nWspaniale! Napisz jakiej jest plci?\n\n1 - mezczyzna\n0 - kobieta\n");
		scanf("%d", &object.plec);
		printf("\nSwietnie!\nOstatnim elementem w bazie danych jest wzrost:");
		scanf("%d", &object.wzrost);
		system("cls");
		printf("\nSprawdzmy..\nDo bazy danych zostanie dodana osoba o imieniu %s, nazwisku %s, wieku %d lat, plci %d(1-M,0-K) i wzroscie %d cm.", object.imie, object.nazwisko, object.wiek, object.plec, object.wzrost);
		
		//Alokujemy pamięć (p oznacza pointer (wskaźnik))
		char *pimie;
		char *pnazwisko;
		int *pwiek;
		int *pplec;
		int *pwzrost;
		pimie = (char*)malloc(sizeof(*pimie)*strlen(object.imie));
		*pimie = object.imie;
		printf("Hello world! Object.imie=%s", *pimie);
		break;

Błąd typu: error C2440: '=' : cannot convert from 'char [30]' to 'char'

(błąd znajduje się w tej linijce :
*pimie = object.imie;)

0

takie cos powinno zadzialac

pimie = &object.imie[0]; 
0

Ale to wtedy będzie tylko jedna literka, a ja chce wszystkie z object.imie

0

nie bedzie jedna literka...
do WSKAZNIKA wpisuje ADRES pierwszego elementu tablicy (wiec mozesz sie nim poruszac jak po tablicy)

Ty co robisz to do WARTOSCI WSKAZNIKA chcesz przypisac TABLICE. To nie ma sensu

3
fasadin napisał(a):

takie cos powinno zadzialac

pimie = &object.imie[0]; 

To nie przejdzie. On chce skopiować tekst, a nie tylko wskaźnikiem wskazać na obcą tablicę.

strcpy(pimie, object.imie);
0

ale pimie to tylko wskaznik na ktory nic nie pokazuje. Nie ma zaalokowanej pamieci. Nie mozesz uzywac tak strcpy.

EDIT nvm, widze ze on alokuje tam pamiec, wiec masz racje ;)

0

Ja chyba naprawdę nie jestem w stanie pojąć wskaźników...

Spójrzcie na to:

	case 2: //dynamiczna alockacja pamięci
		wsk = (int*)malloc(sizeof(int)*20);
		wsk[0]=1;
		wsk[9]=3;
		wsk[21]=2;
		printf("Wsk[0]= %d\nWsk[9]= %d\n wsk[21]= %d", wsk[0], wsk[9], wsk[21]);
		break;

I czemu niby jak zaalokowałem 20 intów to mogę wywołać tablicę wskaźnika[21]? (wiem, że się liczy od 0, [20] też się wywoływało)

0

Bo kompilator nie sprawdza ile zaalokowałes, po prostu po wpisaniu tab[21] robi *(tab+21) i jego nie obchodzi czy dereferencja wywoła naruszenie ochrony pamięci czy nie. To twój problem.

0

wsk[21] oznacza tylko "to co jest w miejscu oddalonym o 21 pól (rozmiar pola odpowiada typowi wskaźnika) od miejsca wskazanego przez wskaźnik wsk".
Równoważny zapis to *(wsk + 21).
Nie ma żadnego mechanizmu, który by zabraniał wpisać tam bzdurne liczby, bo wskaźnik nie wie ile pamięci "należy" do niego, on tylko wskazuje na początek. Jeśli masz szczęście to dostaniesz błąd gdy będziesz mazać po pamięci zajętej przez coś innego, a jak masz pecha to tamta pamięć będzie bezpańska i błąd przejdzie niezauważony.

Poza tym w tym przypadku nie ma żadnej tablicy. Jest ciągły obszar pamięci i wskaźnik, który wskazuje na jego początek, nic więcej.

0
twonek napisał(a):

wsk[21] oznacza tylko "to co jest w miejscu oddalonym o 21 pól (rozmiar pola odpowiada typowi wskaźnika) od miejsca wskazanego przez wskaźnik wsk".

Równoważny zapis to *(wsk + 21)

Albo *(21 + wsk) a co za tym idzie 21[wsk]

:-)

0

Rozumiem, dziękuję. Teraz inny problem:

struct osoba
{
	char nazwisko[100];
	char imie[100];
	int wiek[4];
	int plec[2];
	int wzrost[4];
	osoba * nastepna_instancja;
};
	osoba * object = NULL;
		printf("Wybrales opcje numer 1:");
		while (menu_choose != 0)
		{
			osoba * nowy=(osoba*)malloc(sizeof(osoba));
			printf("\nPodaj imie i nazwisko osoby.\n<(wpisz: imie<spacja>nazwisko)");
		scanf("%s %s", (*nowy).imie, (*nowy).nazwisko);
		printf("\nWiek osoby:");
		scanf("%d", (*nowy).wiek);
		printf("\nWspaniale! Napisz jakiej jest plci?\n\n1 - mezczyzna\n0 - kobieta\n");
		scanf("%d", (*nowy).plec);
		printf("\nSwietnie!\nOstatnim elementem w bazie danych jest wzrost:");
		scanf("%d", (*nowy).wzrost);
		system("cls");

		(*nowy).nastepna_instancja=object;
		object=nowy;

		printf("\nSprawdzmy..\nDo bazy danych zostanie dodana osoba o\n imieniu %s,\n nazwisku %s,\n wieku %d lat,\n plci %d(1-M,0-K)\nwzroscie %d cm.\n", (*nowy).imie, (*nowy).nazwisko, (*nowy).wiek, (*nowy).plec, (*nowy).wzrost);
		printf("\n\nCzy dodac nastepnego uzytkownika? 1=tak, 0=nie");
		scanf("%d", &menu_choose);
		}

Czemu wiek, płeć i wzrost MUSZĄ być w tablicy by to działało? Czemu po wypisaniu zapisuje się coś takiego:

060c5cf952.png

@Edit
Rozumiem, że te int'y są adresami komórek, ale nie wartościami. Tyle, że nie wiem dlaczego skoro *wsk zwraca wartość wskaźnika, a nie adres.

0
rafek1241Advert napisał(a):

Czemu wiek, płeć i wzrost MUSZĄ być w tablicy by to działało?
Nie muszą i nie powinny.
scanf() jako argumenty poza pierwszym przyjmuje adresy, do których ma wpisać te dane.

struct osoba
{
    ...
    int wiek;
    ...
};
...
scanf("%d", &(*nowy).wiek);
// albo ładniejszy zapis
scanf("%d", &nowy->wiek);

Czemu po wypisaniu zapisuje się coś takiego:
Bo w Twoim przypadku wiek to nazwa tablicy, która niejawnie się konwertuje do adresu na pierwszy element tablicy. W tym przypadku żeby wyświetlić dobrą wartość trzeba wypisać pierwszy element tablicy, czyli

printf("%d", (*nowy).wiek[0]);

Rozumiem, że te int'y są adresami komórek, ale nie wartościami. Tyle, że nie wiem dlaczego skoro *wsk zwraca wartość wskaźnika, a nie adres.
nowy to wskaźnik na strukturę, (*nowy) daje tę strukturę, ale wewnątrz niej wiek jest tablicą, czyli się konwertuje do wskaźnika. Popatrz na ten przykład:

struct X
{
	int* wiek;	
};

int main() 
{
	struct X* foo = malloc(sizeof(struct X));
	(*foo).wiek = malloc(sizeof(int));
	*((*foo).wiek) = 5;
	printf("%d\n", *(foo->wiek) + 1);
	return 0;
}

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