Nie można zwiększyć tablicy typu string

0

Witam,

Próbując "zwiększyć" tablicę dynamiczną typu String program się kończy, ale gdy zmienię typ na int wszystko gra.

#include <iostream>
#include <string>

using namespace std;

void fill(string* wsk, int& size);
string *expandTable(string* logs, int &size);

int main()
{
  int size=5;
  int logNum = 5;
  int &s = size;
  string *logs = new string [s];
  cout << "Size: " << s << endl;
  fill(logs, s);
  logs = expandTable(logs, s);
  cout << "Size: " << s << endl;
  fill(logs, s);

return 0;
}

string *expandTable(string* logs, int& size){ 
  size *= 2;
  string *n_logs = new string [size];

  for (int i=0; i<size; i++){
    n_logs[i] = logs[i];
  }

  delete [] logs;
  return n_logs;
}

void fill(string* wsk, int& size){
  for (int i=0; i<size; i++){
    cin >> wsk[i];
  }
}

Dlaczego tak jest?

1

Wiesz, ze jest std::vector<T>?

0
stivens napisał(a):

Wiesz, ze jest std::vector<T>?

Tak, ale chcę to zrobić w ten sposób.

0

@Jul Bed:
Przeanalizuj moje komentarze.

	size *= 2; // ile wynosi size?
	string *n_logs = new string[size];

	for (int i = 0; i < size; i++) {
		n_logs[i] = logs[i]; // do jakich elementów chcesz się dostać?
	}
0
leto napisał(a):

@Jul Bed:
Przeanalizuj moje komentarze.

	size *= 2; // ile wynosi size?
	string *n_logs = new string[size];

	for (int i = 0; i < size; i++) {
		n_logs[i] = logs[i]; // do jakich elementów chcesz się dostać?
	}

Size zwiększany podwójnie. Jeżeli chodzi o pętle to to raczej nie ma znaczenia bo po prostu dany wskaźnik będzie pusty, prawda? Widziałem taki sposób w wielu programach mówiąc szczerze.

0

int *zwiekszTablice (int* w_wartosci, int *rozmiar)
{
	*rozmiar *= 2;
	int *w_nowe_wartosci = new int[ *rozmiar ];
	for ( int i = 0; i < *rozmiar; ++i )
	{
		w_nowe_wartosci[ i ] = w_wartosci[ i ];
	}
	delete [] w_wartosci;
	return w_nowe_wartosci;
}

Dosłowne ctrl+c, ctrl+v z pliku z ksiazki. Jak chcesz całe to tu jest źródło: ftp://ftp.helion.pl/przyklady/cppppo.zip (plik R14).

0

Jak nie dostajesz segfaulta tak o to wez odpal z sanitizerem
Jakos tak:

g++ -fsanitize=address
0
Jul Bed napisał(a):

int *zwiekszTablice (int* w_wartosci, int *rozmiar)
{
	*rozmiar *= 2;
	int *w_nowe_wartosci = new int[ *rozmiar ];
	for ( int i = 0; i < *rozmiar; ++i )
	{
		w_nowe_wartosci[ i ] = w_wartosci[ i ];
	}
	delete [] w_wartosci;
	return w_nowe_wartosci;
}

Jeśli tablicę w_wartosci zaalokowano z rozmiarem *rozmiar to mamy UB w pętli, bo użyty jest nowy powiększony rozmiar zamiast starego i wyjeżdżamy z indeksami poza tablicę w_wartosci.

1
Jul Bed napisał(a):
stivens napisał(a):

Wiesz, ze jest std::vector<T>?

Tak, ale chcę to zrobić w ten sposób.

C H O O O O O R E E E E E E E

Chcesz się czegoś nauczyć (bo na razie się anty-uczsz, jak uczenie się źle pływać, źle grać na instrumencie czy podobne rzeczy), to włóż w klasę wskaźnik i licznik, funkcje niech się staną metodami w klasie

A książkę wyrzuć i nie patrz, gdzie spada.

3

Ale ja to wiem xd Tylko sie zastanawiałem dlaczego na intach to działa a na stringach wywala program. - Jul Bed 3 minuty temu

int wybacza UB, jest mu "wszystko jedno" czy jest prawdziwa wartością, czy śmieciami z RAM.
Odmiennie std::string - tego nie wybaczy

Zrozum dobrze UB Udefined Behaviour brzmi tak łagodnie, ot panowie nie zdefiniowali jak coś działa ...
Uważam źle się stało, że urobiono tak łagodne pojęcie.

To jest po prostu BŁĄD, który może ujawni się natychmiast, może z opóźnieniem X instrukcji maszynowych (X 1 .. oo), a może obecna konfiguracja wiatrów i gwiazd powoduje, ze nie ujawni się.

Program który "działa" na nieprawidłowych obszarach pamięci, zapamiętaj, że NIE DZIAŁA (i tylko przez brak obserwacji, np wynotowania N pozycji do zeszytu i porównania z 2N potem) początkujący sami sobie udowadniają, że "działa")

0

A z tablicami statycznymi (nie wskaźnikami) można tak zrobić bez wycieku pamięci, czy to ten sam scenariusz? - Jul Bed 1 minuta temu

Przepakuj to do klasy jak już pisałem, wtedy opanujesz w dziecinnie łatwy sposób

4
Jul Bed napisał(a):

int *zwiekszTablice (int* w_wartosci, int *rozmiar)
{
	*rozmiar *= 2;
	int *w_nowe_wartosci = new int[ *rozmiar ];
	for ( int i = 0; i < *rozmiar; ++i )
	{
		w_nowe_wartosci[ i ] = w_wartosci[ i ];
	}
	delete [] w_wartosci;
	return w_nowe_wartosci;
}

Dosłowne ctrl+c, ctrl+v z pliku z ksiazki. Jak chcesz całe to tu jest źródło: ftp://ftp.helion.pl/przyklady/cppppo.zip (plik R14).

Jeśli to jest przykład nr 37 z rozdziału 14 to ciekawa sprawa, bo dogrzebałem się do angielskiej wersji w której kod wygląda tak:

int *growArray (int* p_values, int cur_size)
{
  int *p_new_values = new int[ cur_size * 2 ];
  for ( int i = 0; i < cur_size; ++i )
  {
    p_new_values[ i ] = p_values[ i ];
  }
  delete p_values;
  return p_new_values;
}
3

Z książek polecam :

  • A Tour of C++ - Bjarne Stroustrup
  • Effective Modern C++ - Scott Meyers

Nie wiem jak są przetłumaczone, więc polskich wersji nie będę polecał.
Tą którą masz lepiej odłożyć na półkę ...

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