Tablica wskaźników na tablicę char

0

Witam.
Mam problem, z którym borykam się od jakiegoś czasu. Na zajęcia muszę napisać program, który będzie wyświetlał wszystkie grupy, wszystkich zalogowanych użytkowników. Zastrzeżeniem jest, aby funkcja zwróciła te grupy w tablicy stringów. Problem jest taki, że komórki zwracanej tablicy są wypełnione nazwą tylko jednej grupy. Sprawdzałem skrypt debuggerem linijka po linijce i do momentu przepisywania wartosci z tablica do tablica_nazw wszystko sie zgadza. W momencie wejścia programu do pętli, w której chcę wypisać nazwy tych grup (zaznaczyłem strzałkami), komórki tablica_nazw są wypełnione nazwą tylko jednej grupy.
Bardzo proszę o jakąś podpowiedź, bo za nic nie mogę zrozumieć w którym miejscu popełniłem błąd.
Pozdrawiam.

#include <grp.h>
#include<pwd.h>
#include<utmp.h>
#include<stdlib.h>
#include<stdio.h>
char ** nazwa_grupy(uid_t uid)
{
int ilosc;
gid_t grupa[1], *tablica;
char **tablica_nazw;
int i;

        ilosc=1;
        getgrouplist(getpwuid(uid)->pw_name, getpwuid(uid)->pw_gid, grupa, &ilosc);	//po wywolaniu funkcji w zmiennej ilosc znajdzie sie ilosc wszystkich grup uzytkownika

        tablica=malloc(ilosc*sizeof(gid_t));						//tablica na id wszystkich grup
        getgrouplist(getpwuid(uid)->pw_name, getpwuid(uid)->pw_gid, tablica, &ilosc);

	tablica_nazw=(char**)malloc(ilosc*sizeof(char*));				//tablica wskaznikow na tablice char
	for(i=0; i<ilosc; i++)	
		tablica_nazw[i]=(char*)malloc(sizeof(getgrgid(tablica[i])->gr_name));	
        for(i=0; i<ilosc; i++)
		tablica_nazw[i]=getgrgid(tablica[i])->gr_name;
	for(i=0; i<ilosc; i++)                     // <---------
		printf("%s", tablica_nazw[i]);  //<-----------
	printf("\n");
        free(tablica);
return tablica_nazw;
}

~EDIT
Wielkie dzięki za odpowiedź. Zastosowałem się do Twoich wskazówek. Kod, który umieściłem wyżej ma znajdować się w bibliotece, która jest dołączana do głównego programu. Funkcja wyświetla nazwy grup w bibliotece prawidłowo, ale w mainie, po wywołaniu znowu ten sam problem.
Poprawiony kod znajdujący się w pliku biblioteka.c:

#include"libbiblioteka.h"
#include <grp.h>
#include<pwd.h>
#include<utmp.h>
#include<stdlib.h>
#include<string.h>
char ** nazwa_grupy(uid_t uid)
{
int ilosc;
gid_t grupa[1], *tablica;
char **tablica_nazw;
int i;

        ilosc=1;
        getgrouplist(getpwuid(uid)->pw_name, getpwuid(uid)->pw_gid, grupa, &ilosc);	//ilosc=ilosc wszystkich grup
        tablica=malloc(ilosc*sizeof(gid_t));						//tablica na id wszystkich grup
        getgrouplist(getpwuid(uid)->pw_name, getpwuid(uid)->pw_gid, tablica, &ilosc);

	tablica_nazw=(char**)malloc(ilosc*sizeof(char*));				//tablica wskaznikow na tablice char
	for(i=0; i<ilosc; i++)	
	{
		tablica_nazw[i]=(char*)malloc(sizeof(strlen(getgrgid(tablica[i])->gr_name)+1));	
		strcpy(tablica_nazw[i],getgrgid(tablica[i])->gr_name);
	}
        free(tablica);
return tablica_nazw;
}

Kod znajdujący się w pliku main:

#include "libbiblioteka.h"
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <utmp.h>
#include<string.h>

int main(int argc, char* argv[])
{

struct utmp *wskaznik;
char **tablica, *nazwa;
int ilosc;
gid_t tab[1];
int i;


setutent();
for(;;)
{
	wskaznik=getutent();
	if(wskaznik==NULL)
		break;
	if(wskaznik->ut_type!=7)
		continue;
	ilosc=1;
	getgrouplist(wskaznik->ut_user, getpwnam(wskaznik->ut_user)->pw_gid, tab, &ilosc);
	tablica=nazwa_grupy(getpwnam(wskaznik->ut_user)->pw_uid);
	printf("%s :", wskaznik->ut_user);
	for(i=0; i<ilosc; i++)
		printf("%s ", tablica[i]);
	printf("\n");
	/*for(i=0; i<ilosc; i++)
		free(tablica[i]);
	free (tablica);*/
}

return 0;
}
1

Błędnie alokujesz pamięć na nazwy użytkowników -> użyj strlen() + 1. Błędnie potem kopiujesz te nazwy do tablicy -> użyj strcpy(). A jak zwrócisz wskaźnik na tablicę tablic, to przydałoby się jeszcze mieć informację o rozmiarze, bo jak potem zwolnisz tę pamięć?

    for (i = 0; i < ilosc; i++) 
        tablica_nazw[i] = malloc(strlen(getgrgid(tablica[i])->gr_name) + 1); 
    for (i = 0; i < ilosc; i++)
       strcpy(tablica_nazw[i], getgrgid(tablica[i])->gr_name);
0

Jest różnica pomiędzy tym co napisałem:

tablica_nazw[i]=malloc(strlen(getgrgid(tablica[i])->gr_name)+1); 

a tym, co przepisałeś:

tablica_nazw[i]=(char*)malloc(sizeof(strlen(getgrgid(tablica[i])->gr_name)+1)); 
0

Wielkie dzięki za pomoc. Wszystko działa jak należy.
Pozdrawiam:)

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