Tablica jako argument, zwracanie jej, powiększanie.

0

Witam. Chciałbym zrobić dla dowolnego typu tablic funkcję, która dodaje na koniec tablicy (zwiększa ją o jeden) jakąś wartość, intową, charową itd. Napisałem takie coś:

//Funkcja poszerzajaca tablice i dodajaca nowa wart. na koniec
template <typename TArray, typename TValue>
TArray * Add_to_array(TArray * array, TValue value, int n)
{
	TArray * tmp = new TArray[n+1];
	TArray * new_array = new TArray[n+1];
	
	for(int i=0; i<n; i++)
	{
		tmp[i] = array[i];
		delete [] array[i];
	}
	
	for(int i=0; i<=n; i++)
	{
		new_array[i] = tmp[i];
		if(i<n) delete [] tmp[i];
	}
	return new_array;
}

//oraz jej wywolanie
char * Arr_file_names;
//tu jakas petelka jest, zmienia sie wartosc Folder->d_name i chce dodac ja na koniec tablicy
Arr_file_names = Add_to_array(&Arr_file_names, Folder->d_name, i);

Jednak wypluwa mi błąd który dotyczy przypisania przy wywołaniu chyba

modules/file_loader.h:29:70: error: cannot convert ‘char**’ to ‘char*’ in assignment
  1. Co jest nie tak? Czy ta funkcja ma prawo działać?
  2. Czy moje usuwanie jest poprawne?
0

&Arr_file_names jest typu char ** a szablon jest taki:

TArray * Add_to_array(TArray * array, TValue value, int n)

Dopasowanie jest takie: Tarray = char bo "jedna gwiazdka się zgadza". Druga zostaje i tym sposobem funkcja zwraca char **, które próbujesz przypisać do char *. Rozwiązanie: wywal &.

To nie koniec Twoich problemów. Cała ta funkcja jest jakaś dziwna i moim zdaniem bez sensu. Wygląda jak byś chciał operować na dwuwymiarowych tablicach, tudzież ogólnie na wskaźnikach do wskaźników, ale w obecnym kształcie wywołujesz delete na elemencie tablicy, który jest char. Czemu to ma służyć?

Najpierw określ co to ma robić konkretnie. Powiększać tablicę jednowymiarową? Dwu? Po co dwa parametry szablonu? Po co delete na wartości?

Najprostsza możliwa funkcja, która rozszerza tablicę o jeden i doda nową wartość, była by chyba taka:

#include <algorithm>
 
// ...

template <typename T>
T *add_to_array(T *tab, T value, size_t n) {
  T *new_tab = new T[n + 1];
 
  std::copy(tab, tab + n, new_tab);
  new_tab[n] = value;
 
  delete [] tab;
 
  return new_tab;
}

Ogólnie jednak nie musisz zajmować się konstruowaniem takich rzeczy - zainteresuj się klasą std::vector.

0

Zamieniłem jak napisałeś, ale wywala błąd

 
mateusz@mateusz-pc:~/Studia/C++/Projekt 1$ g++ main.cpp -o main
In file included from main.cpp:8:0:
functions/functions.h: In function ‘TArray* Add_to_array(TArray*, TValue, int) [with TArray = char, TValue = char*]’:
modules/file_loader.h:29:69:   instantiated from here
functions/functions.h:22:2: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
mateusz@mateusz-pc:~/Studia/C++/Projekt 1$ 
template <typename TArray, typename TValue>
TArray * Add_to_array(TArray * array, TValue value, int n)
{
	TArray * new_array = new TArray[n+1];
	
	copy(array, array+n, new_array);
	new_array[n+1] = value;
	
	delete [] array;
	
	return new_array;
}

char * Arr_file_names;
Arr_file_names = Add_to_array(Arr_file_names, Folder->d_name, i);

Wiem że chodzi o tą linijkę

new_array[n+1] = value;

No ale przeciez przypisuje charowa wartosc do charowej tablicy wiec wtf?

1

Co to jest Folder->d_name? Jak widać jest typu char *. Jak chciałbyś mieć tablicę char * Arr_file_names, która zwiera elementy char *? Taka tablica zawiera elementy char czyli pojedyncze znaki. Tablica char * to char ** i taka funkcja tego nie obsłuży.

0

Folder->d_name to nazwy plikow w katalogu. Jak witac nie sa to pojedyncze znaki bo gdy wyswietlam te pliki w petli

                     char * Arr_file_names;
			while(Folder = readdir(dir))
			{
				if(Folder->d_type != is_folder && Folder->d_name != "." && Folder->d_name != "..")
				{					
					cout<<Folder->d_name<<endl;
					Arr_file_names = Add_to_array(Arr_file_names, Folder->d_name, i);					
					i++;
				}	
			}

to działa bardzo dobrze i wyświetla, więc chce te nazwy przypisać do tablicy.

//edit 1 Dałem tam * przed value w tej funkcji niby sie kompiluje ale wywala jakis blad naruszenie pamieci oO
//edit 2 powyzszy blad wynika z tego delete [ ] array. Czyli cos nie tak z usuwaniem starej tablicy

1

Jeszcze raz.
char * jakas_nazwa -> wskaźnik na char, może być tablicą char tudzież napisem.

U Ciebie jest tak:
char * Arr_file_names -> jak wyżej.
Folder->d_type -> typ char * czyli jak wyżej.

Chcesz zrobić tak:

new_array[n+1] = value;

new_array -> char *
new_array[n+1] -> char
value -> char *

Robisz więc przypisanie char = char *, tego zrobić się nie da.

Arr_file_names powinno być typu char ** żeby móc przechowywać elementu typu char *. Ale wtedy funkcja dodająca musi być zupełnie inna.

0

To jest zbyt skomplikowane... co mam więc zrobić żeby zapisać te nazwy plików do tej tablicy dynamicznej? W sumie mógłbym je zliczyć i zrobić tablicę statyczną ale w ten sposób niczego się nie nauczę i jak znowu przyjdzie mi zrobić coś podobnego to lipa... Zrozumiałem mniej więcej to co napisałeś powyżej ale nie wiem jak mam to zamienić na działający kod :(

1

Wystarczy nauczyć się C++ a nie pisać w C z użyciem kompilatora C++.

Obsługa napisów o dowolnej długości: std::string.
Przechowywanie wielu elementów bez martwienia się o rozmiar: np. std::vector.

0

No właśnie chodzi o to że ja dopiero C++ zaczynam - miałem C do tej pory. Niestety nie mogę używać stringów ponieważ argumenty wymagają taki a nie inny typ (funkcja readdir zwraca chary i nic na to nie poradzę). O <vectorze> czytałem i jest to fajne narzędzie które użyje zamiast tego dynamicznego alokowania. Problemem są tylko te typy i gwiazdki.

Oczywiście to poniżej nie działa ;/ Mógłbyś po prostu napisać co mam zmienić żeby to działało, gdzie gwiazdkę wstawić, co zmienić? Muszę to oddać w przyszłym tyg. a mam jeszcze kupę roboty, niczego się nie nauczę jeśli będę losowo wstaiał gwiazdki, a tak bym stopniowo rozkmninił...pzdr

template <typename TArray, typename TValue>
TArray * Add_to_array(vector <TArray*> array, TValue value, int n)
{
	vector <TArray> new_array[n+1];
	
	copy(array, array+n, new_array);
	new_array[n] = value;
	cout<<new_array[n];
	//delete [] array;
	return new_array;
}
vector <char> Arr_file_names;
while(Folder = readdir(dir))
{
   if(Folder->d_type != is_folder && Folder->d_name != "." && Folder->d_name != "..")
    {	
	if(i%3==0) cout<<"\n";
					
					//cout<<"{"<<i+1<<"} "<<Folder->d_name<<"  ";
					Arr_file_names = Add_to_array(Arr_file_names, Folder->d_name, i);					
					i++;
				}	
			}
1

Możesz. Przecież std::string ma konstruktor przyjmujący char *. Po prostu zaznajom się z obiema klasami, poćwicz. Jeżeli masz zamiar pisać w C++ jest to praktycznie obowiązkowa wiedza.

Co do Twojego edita. Jeżeli użyjesz tych klas to całe to dodawanie nie jest potrzebne, wszystko za Ciebie robi std::vector.

Mniej więcej będzie to tak, zauważ, że stringi w stylu C (char *) należy porównywać za pomocą strcmp z <cstring>

std::vector<std::string> arr_file_names;

while (folder = readdir(dir)) {
   if(Folder->d_type != is_folder &&
      strcmp(Folder->d_name, ".") != 0 &&
      strcmp(Folder->d_name, "..") != 0) {

      arr_file_names.push_back(Folder->d_name);
  }
}
0

Rozwiazalem to w ten sposob, faktycznie duzo wygodniejsze! Prawie jak w PHP. ;]

                                       vector <string> Arr_file_names;
					string file_name(Folder->d_name);
					Arr_file_names.push_back(file_name);

Dzięki bardzo!

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