Tablica Dynamiczna Stringów (cała struktura)

0

Witam
Na potrzeby swojego programu potrzebuję strukturę kilku tablic dynamicznych, ale jako że jestem początkującym programistą C++ nie mam pojęcia co i czemu mi nie działa.

typedef struct sFileList {
    int size;
    String *fileName;
    String *filePath;
    String *fileExt;
} fileList;

void arrStr_Create( String *arr, int size ) {
    // W domyśle zawsze będzie 0
    arr = new String[size];
}

void arrStr_Add( String *arr, int size, String var ) {
    String *newArr = new String[ size+1 ];
    for ( int i=0; i<size; i++ ) {
        newArr[i] = arr[i];
    }
    newArr[size] = var;

    arr = new String[ size+1 ];
    for ( int i=0; i<=size; i++ ) {
        arr[i] = newArr[i];
    }    
}

String arrStr_Get( String *arr, int size, int index ) {
    if ( index < size || index >= size ) { return ""; }
    return arr[index];
}

void arrStr_Delete( String *arr, int size, int index ) {
    String *newArr = new String[ size-1 ];
    int n = 0;
    for ( int i=0; i<size; i++ ) {
        if ( i != index ) {
            newArr[n] = arr[i];
            n++;
        }
    }
    newArr[size] = var;

    arr = new String[ size-1 ];
    for ( int i=0; i<=size; i++ ) {
        arr[i] = newArr[i];
    }
}  

void newFileList( fileList *FL ) {
        FL->size = 0;
        arrStr_Create( FL->fileName, FL->size );
        arrStr_Create( FL->filePath, FL->size );
        arrStr_Create( FL->fileExt, FL->size );
}

void addFileList( fileList *FL, String file ) {
    arrStr_Add( FL->fileName, FL->size, ExtractFileName( file ) );
    arrStr_Add( FL->filePath, FL->size, ExtractFilePath( file ) );
    arrStr_Add( FL->fileExt, FL->size, ExtractFileExt( file ) );
    FL->size++;
}

void removeFileList( fileList *FL, int index ) {
    arrStr_Delete( FL->fileName, FL->size, index );
    arrStr_Delete( FL->filePath, FL->size, index );
    arrStr_Delete( FL->fileExt, FL->size, index );
    FL->size--;
}

Niektórzy pomyślą że niepotrzebnie tworzę tablicę tego, tego i tego... ale chciałbym zrobić odtwarzacz który zawiera listę plików aktualnie grającą, i listę którą można wyświetlić i edytować (funkcje przesuwania plików w liście dojdą później), na razie chcę zrobić podstawy. Wszystko buduję w RAD Studio C++Builder.
I nie wiadomo jakie znajdę przykłady w sieci, chciałbym żeby to mniej więcej tak wyglądało, ale program mi cięgle wyrzuca błędy pamięci przy takim kodzie.

1

uzyj gotowych narzedzi np std::vector
druga rzecza ze nie powinno sie uzywac ze wskaznikow (nagich) masz od tego smart pointery

1
chkam napisał(a):

Witam
Na potrzeby swojego programu potrzebuję strukturę kilku tablic dynamicznych, ale jako że jestem początkującym programistą C++ nie mam pojęcia co i czemu mi nie działa.

Użyj jakiegoś kontenera z biblioteki standardowej np. std::vector.

chkam napisał(a):
typedef struct sFileList {
    int size;
    String *fileName;
    String *filePath;
    String *fileExt;
} fileList;

void arrStr_Create( String *arr, int size ) {
    // W domyśle zawsze będzie 0
    arr = new String[size];
}

void arrStr_Add( String *arr, int size, String var ) {
    String *newArr = new String[ size+1 ];
    for ( int i=0; i<size; i++ ) {
        newArr[i] = arr[i];
    }
    newArr[size] = var;

    arr = new String[ size+1 ];
    for ( int i=0; i<=size; i++ ) {
        arr[i] = newArr[i];
    }    
}

String arrStr_Get( String *arr, int size, int index ) {
    if ( index < size || index >= size ) { return ""; }
    return arr[index];
}

void arrStr_Delete( String *arr, int size, int index ) {
    String *newArr = new String[ size-1 ];
    int n = 0;
    for ( int i=0; i<size; i++ ) {
        if ( i != index ) {
            newArr[n] = arr[i];
            n++;
        }
    }
    newArr[size] = var;

    arr = new String[ size-1 ];
    for ( int i=0; i<=size; i++ ) {
        arr[i] = newArr[i];
    }
}  

void newFileList( fileList *FL ) {
        FL->size = 0;
        arrStr_Create( FL->fileName, FL->size );
        arrStr_Create( FL->filePath, FL->size );
        arrStr_Create( FL->fileExt, FL->size );
}

void addFileList( fileList *FL, String file ) {
    arrStr_Add( FL->fileName, FL->size, ExtractFileName( file ) );
    arrStr_Add( FL->filePath, FL->size, ExtractFilePath( file ) );
    arrStr_Add( FL->fileExt, FL->size, ExtractFileExt( file ) );
    FL->size++;
}

void removeFileList( fileList *FL, int index ) {
    arrStr_Delete( FL->fileName, FL->size, index );
    arrStr_Delete( FL->filePath, FL->size, index );
    arrStr_Delete( FL->fileExt, FL->size, index );
    FL->size--;
}

Twój poomysł jest ogólnie OK - poza tym że przypomina bardziej C niż C++. Kilka rad:

  • Twój arrStr_Create to powinien być konstruktor klasy, tam alokujesz pamięć
  • W destruktorze klasy powinieneś zwolnić pamięc którą zaalokowałeś w arrStr_Create.
  • Klasa String to std::string (chociaż prawdopodobnie jest to klasa z C++Buildera którego używasz)
  • arrStr_Add, arrStr_Delete itd to powinny być metody klasy sFileList - wtedy nie potrzebujesz wskaźnika na twoją strukturę jako pierwszy argument. To zapewni ci kompilator w postaci zmiennej this która odnosi się do obiektu na którym wywołujesz daną metodę.
chkam napisał(a):

Niektórzy pomyślą że niepotrzebnie tworzę tablicę tego, tego i tego... ale chciałbym zrobić odtwarzacz który zawiera listę plików aktualnie grającą, i listę którą można wyświetlić i edytować (funkcje przesuwania plików w liście dojdą później), na razie chcę zrobić podstawy. Wszystko buduję w RAD Studio C++Builder.
I nie wiadomo jakie znajdę przykłady w sieci, chciałbym żeby to mniej więcej tak wyglądało, ale program mi cięgle wyrzuca błędy pamięci przy takim kodzie.

Tak, niepotrzebnie. Można poznać u ciebie naleciałości z C ale w C++ nie musisz wynajdywać koła na nowo. Jak wyżej wspomniałem masz do dyspozycji całą biblioteke standardową a w szczególności kontenery które ci się przydadzą.

2
  • Klasa String to std::string (chociaż prawdopodobnie jest to klasa z C++Buildera którego używasz)

String to builderowy String, i sam w sobie jest ok, ale String sam zarządza własną pamięcią, więc nie rozumiem po co te wskaźniki i new wszędzie.

0

Nie chodzi mi o *String jako string ilości znaków [ 'a', 'b', 'c' ] tylko o tablice Stringów [ 'teskt1', 'tekst2', 'tekst3' ]

2
chkam napisał(a):

Nie chodzi mi o *String jako string ilości znaków [ 'a', 'b', 'c' ] tylko o tablice Stringów [ 'teskt1', 'tekst2', 'tekst3' ]

Jeśli tak, to zamiast robić ręcznie taką tablice zrób std::vector<String>

0

Dziękuję wszystkim za pomoc, rozwiązałem problem dzięki Klasom i wbudowanemu obiektowi TStrings / TStringList.

class TfileList {
		int         size;
		TStrings	*fileName;
		TStrings	*filePath;
		TStrings	*fileExt;
	public:
		TfileList();
		void		add( String fName, String fPath, String fExt );
		String		getName( int index );
		String		getPath( int index );
		String		getExt( int index );
		int         getLength();
		void		remove( int index );
};

TfileList::TfileList() {
	this->size = 0;
	this->fileName		= new TStringList;
	this->filePath		= new TStringList;
	this->fileExt		= new TStringList;
}
//---------------------------------------------------------------------------
void TfileList::add( String fName, String fPath, String fExt ) {
	this->size++;
	this->fileName->Add( fName );
	this->filePath->Add( fPath );
	this->fileExt->Add( fExt );
}
//---------------------------------------------------------------------------
String TfileList::getName( int index ) {
	if ( index >= 0 && index < this->size ) {
        return fileName->Strings[ index ];
	} else {
        return "";
    }
}
//---------------------------------------------------------------------------
String TfileList::getPath( int index ) {
	if ( index >= 0 && index < this->size ) {
		return filePath->Strings[ index ];
	} else {
        return "";
	}
}
//---------------------------------------------------------------------------
String TfileList::getExt( int index ) {
	if ( index >= 0 && index < this->size ) {
        return fileExt->Strings[ index ];
	} else {
        return "";
	}
}
//---------------------------------------------------------------------------
int TfileList::getLength() {
	return this->size;
}
//---------------------------------------------------------------------------
void TfileList::remove( int index ) {
	if ( index >= 0 && index < size ) {
		this->size--;
		this->fileName->Delete( index );
		this->filePath->Delete( index );
		this->fileExt->Delete( index );
	}
}
1

Zapomniałeś o destruktorze w klasie TfileList który zwolniłby dynamicznie zaalokowaną pamięć:

TfileList::~TfileList() {
  delete fileName;
  delete filePath;
  delete fileExt;
}

bez tego będziesz miał wycieki pamięci.

Wygląda też na to że mógłbyś mieć jedną klasę:

class Tfile {
  String fileName;
  String filePath;
  String fileExt;
};

I listę np. TList która przechowuje elementy tej klasy. Jeśli masz dostęp do biblioteki standardowej to std::vector<Tfile> lub std::list<Tfile>. Dzięki temu zamiast robić trzy operację dodania/usunięcia elementu za każdym będziesz robić tylko jedną. Licznik size również byłby niepotrzebny, ponieważ licznik będzie wewnątrz w/w kontenerów.

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