... und das zeigt wieder, dass du das gesammte Konzept der CStrings nicht verstanden hast.
Wenn du einen CString speichern willst, dann hast du einen hinreichend großen Speicherblock (d.h. einen Bereich im Speicher, der groß genug ist und dir zur Benutzung zur Verfügung steht) und einen Zeiger auf das erste Element im String (==> char *).
Da du aber nur den Anfang kennst ist es doch irgendwie einleuchtend, dass du das Ende irgendwie markieren musst. Dazu dient das 0-Zeichen (ASCII 0x00). Gibst du also beispielsweise einen String aus, so fängst du beim Anfang an und gibst Zeichen für Zeichen aus, bis du das 0-Zeichen erreicht hast, welches dir also das Ende signalisiert.

Willst du mehrere Strings speichern, so benötigst du wieder einen hinreichend großen Abschnitt im Speicher und eine Menge an Zeigern, die jeweils auf das erste Zeichen der verschiedenen Strings zeigen.
Wenn du dir dabei viele Aufrufe zu malloc() sparen willst, dann reservierst du gleich einen großen Block im Speicher und fängst an diesen zu beschreiben.
Der erste String kommt dann gleich an den Anfang von dem Block. Der zweite landet hinter dem ersten (präziser: hinter dem 0-Zeichen vom ersten, da man später ja noch wissen will, wo der erste CString aufhört). Der dritte landet dann hinter dem zweiten usw.

Jetzt bleibt nur noch das Problem sich zu merken, wo nun welcher String ist.
Hier kam jetzt bei mir die LinkedList ins Spiel, weil ja zusätzlich zu den Namen auch die Gruppe verwaltet werden sollte...
Natürlich könnte man es auch so lösen:
Code:
const unsigned int NAME_MAX_LENGTH = 30;
const unsigned int NAMES_MAX_COUNT = 50;

char names_buff[NAMES_MAX_COUNT * NAME_MAX_LENGTH];
struct
{
    unsigned int group;
    char *name;
} names[NAMES_MAX_COUNT];
names_buff würde dann die Namen enthalten (Name1\x00Name2\x00Name3\x00...) und names würde dann jeweils den Zeiger auf das erste Zeichen in einem Namen und dessen Gruppe enthalten.

names[i-1].name wäre dann der Name des i-ten Spielers und names[i-1].group der Index seiner Gruppe.