Strona 1 z 1

[C++]Zamieszanie ze stringami typu char*

: 16 lis 2009, 22:13
autor: macer
Zacząłem przepisywać pewien algorytm z php, narazie mam tyle:

Kod: Zaznacz cały

#include <iostream>
#include <gd.h>
#include <cstring>
#include <cstdlib>
using namespace std;
int main(int argc,char* argv[])
{	
	FILE *in = fopen("plik.jpg","r");
	FILE *out = fopen("zakodowany.png","w");
	gdImagePtr image = gdImageCreateFromJpeg(in);

	char* tekst = "Hello coding world :-)";
	cout << strlen(tekst);
	
	
}
Problem w tym że przy uruchamianiu programu dostaję "Segmation fault".
Myślę że to przez to że jakoś źle deklaruje "tekst", może trzeba dodać "const", czy jeszcze coś innego.
Wie ktoś co na to poradzić?

PS nie mogę zadeklarować jako "string" bo wtedy nie działa "strlen(tekst)".

Odp: [C++]Zamieszanie ze stringami typu char*

: 16 lis 2009, 22:39
autor: pantich
PS nie mogę zadeklarować jako "string" bo wtedy nie działa "strlen(tekst)".
zamiast strlen możesz użyć metody size

Odp: [C++]Zamieszanie ze stringami typu char*

: 16 lis 2009, 22:51
autor: thalcave

Kod: Zaznacz cały

string text = "To jest moj tekst";

    cout << text.length() << endl;
działa - Pamiętaj stroing to klasa a nie typ zmiennej.

Poza tym w C++ wczytywanie/zapis do pliku odbywa się tak (tak mnie przynajmniej uczono) - szybciej de facto:

Kod: Zaznacz cały

#include <fstream>
[...]
ifstream in("plik_do_wczytania);
ofstream out("plikdozapisu");

string text;
in >> text;

out << text;

Odp: [C++]Zamieszanie ze stringami typu char*

: 16 lis 2009, 22:54
autor: beluosus
Eh... http://www.cplusplus.com/reference/stri ... ng/length/
i
http://www.cplusplus.com/reference/clib ... ng/strlen/
Jak widzisz, strlen jest dla C-stringów, a string ma swoją metodę.

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 00:26
autor: el.pescado

Kod: Zaznacz cały

$ g++ -g -Wall -o program program.cpp
$ gdb ./program
(gdb) run
i patrzysz gdzie program dokładnie się wysypuje...

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 05:32
autor: luzakwielki
macer pisze:Zacząłem przepisywać pewien algorytm z php, narazie mam tyle:

Kod: Zaznacz cały

#include <iostream>
#include <gd.h>
#include <cstring>
#include <cstdlib>
using namespace std;
int main(int argc,char* argv[])
{	
	FILE *in = fopen("plik.jpg","r");
	FILE *out = fopen("zakodowany.png","w");
	gdImagePtr image = gdImageCreateFromJpeg(in);

	char* tekst = "Hello coding world :-)";
	cout << strlen(tekst);
	
	
}
Problem w tym że przy uruchamianiu programu dostaję "Segmation fault".
Myślę że to przez to że jakoś źle deklaruje "tekst", może trzeba dodać "const", czy jeszcze coś innego.
Wie ktoś co na to poradzić?

PS nie mogę zadeklarować jako "string" bo wtedy nie działa "strlen(tekst)".
const char* wyrzuci Ci tylko ostrzeżenie z logów, ale problemu nie załatwi, bo to nie o to chodzi.
Błąd tu polega na tym, że plik.jpg nie istnieje, i się nie otworzył, a chcesz z niego czytać gdImageCreateFromJpeg (z pustego i Salomon nie naleje ;p). Następnym razem sprawdzaj czy plik który otwierasz istnieje:

Kod: Zaznacz cały

if(!in){printf("plik nie istnieje"); exit(0);}
else{
//wszystko ok można czytać z pliku
}

EDIT:
thalcave pisze:

Kod: Zaznacz cały

string text = "To jest moj tekst";

    cout << text.length() << endl;
działa - Pamiętaj stroing to klasa a nie typ zmiennej.

Poza tym w C++ wczytywanie/zapis do pliku odbywa się tak (tak mnie przynajmniej uczono) - szybciej de facto:
Działa - tylko po co w tym wypadku korzystać z std::string, skoro zupełnie nie w tym tkwi problem?

Czyli nie nauczono Cię, że C++ zawiera w sobie C, a funkcje, które pokazałeś spowalniają bardzo odczyt/zapis (jest stosowana synchronizacja) - można niby zmniejszyć różnicę przez wyłączenie synchronizacji wejścia/wyjścia (ios_base::sync_with_stdio(0);), ale dalej wydajność jest niższa niż w przypadku odpowiedników z C.
Swoją drogą nie da się użyć strumieni C++ w tym wypadku, bo biblioteka GD jest pisana w C i użyta funkcja wymaga uchwytu do pliku (FILE*)

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 07:55
autor: macer
Normalnie to bym skorzyształ z ifstream/ofstream, ale gd wymaga użycia FILE*.
Dzięki za rady, mogę pisać dalej ;-)

EDIT:
el.pescado: dzięki za podpowiedź z debugerem, napewno mi się to kiedyś przyda ;-)

EDIT:
el.pescado, czemu dałeś opcja -g przy kompilowaniu?

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 08:04
autor: luzakwielki
macer pisze:el.pescado, czemu dałeś opcja -g przy kompilowaniu?
Żeby binarka zawierała informacje dla debuggera.

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 16:39
autor: mikolajs

Kod: Zaznacz cały

char* tekst = "Hello coding world :-)";
	cout << strlen(tekst);
Czyli nie nauczono Cię, że C++ zawiera w sobie C, a funkcje, które pokazałeś spowalniają bardzo odczyt/zapis (jest stosowana synchronizacja) - można niby zmniejszyć różnicę przez wyłączenie synchronizacji wejścia/wyjścia (ios_base::sync_with_stdio(0), ale dalej wydajność jest niższa niż w przypadku odpowiedników z C.
W większości przypadków to prawda. Tutaj jednak mamy strlen(), który musi policzyć ilość znaków w c stringu, podczas gdy string w momencie tworzenia zapisuje wartość ilości znaków (pewnie więc wychodzi na to samo :) ). Warto korzystać z udogodnień języka C++ w stosuku do C, a bezpośrednio z funkcji C korzystać w wyjątkowych wypadkach.
Jeżeli potrzebny jest c string to string ma metodę c_str().

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 22:42
autor: macer
@luzakwielki: o co ci chodziło z tą synchronizacją w pliku?

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 22:52
autor: el.pescado

Odp: [C++]Zamieszanie ze stringami typu char*

: 17 lis 2009, 23:08
autor: luzakwielki
macer pisze:@luzakwielki: o co ci chodziło z tą synchronizacją w pliku?
Wyjście/wejście w C++ ma standardowo włączoną synchronizacje.
mikolajs pisze:W większości przypadków to prawda. Tutaj jednak mamy strlen(), który musi policzyć ilość znaków w c stringu, podczas gdy string w momencie tworzenia zapisuje wartość ilości znaków (pewnie więc wychodzi na to samo :) ). Warto korzystać z udogodnień języka C++ w stosuku do C, a bezpośrednio z funkcji C korzystać w wyjątkowych wypadkach.
Jeżeli potrzebny jest c string to string ma metodę c_str().
Tak strlen wymaga przejścia przez tablice w poszukiwaniu pierwszego zera - co nie znaczy, że sobie nie możesz opakować w klasę c string i zapisywać potrzebne Ci informacje w konstruktorze.
Zgadzam się, że warto wykorzystywać zalety języka C++, ale jeśli potrzebujesz c string lepiej użyć tablicy znaków niż std::string::c_str(), bo jak pewnie dobrze wiesz, że w string nie jest przechowywany c string tylko osobno znaki, nie po kolei (każda litera ma wskaźnik na kolejną w kolejce) i musi zaalokować pamięć na nowego c stringa, i przepisać wszystko po jednej literce.

Odp: [C++]Zamieszanie ze stringami typu char*

: 18 lis 2009, 17:42
autor: el.pescado
Zgadzam się, że warto wykorzystywać zalety języka C++, ale jeśli potrzebujesz c string lepiej użyć tablicy znaków niż std::string::c_str(), bo jak pewnie dobrze wiesz, że w string nie jest przechowywany c string tylko osobno znaki, nie po kolei (każda litera ma wskaźnik na kolejną w kolejce) i musi zaalokować pamięć na nowego c stringa, i przepisać wszystko po jednej literce.
Nie, std::string nie jest zaimplementowany jako lista wiązana. Obiekty tej klasy zawierają wskaźnik do tablicy znakowej. Zresztą, wystarczy zobaczyć sobie w źródłach:
/usr/include/c++/4.3.3/bits/basic_string.h:

Kod: Zaznacz cały

	_CharT* _M_p; // The actual data.
Tak więc, std::string wewnętrznie wykorzystuje tablicę znakową, a metoda c_str() po prostu zwraca wskaźnik do tej tablicy.

Odp: [C++]Zamieszanie ze stringami typu char*

: 18 lis 2009, 22:48
autor: luzakwielki
el.pescado pisze:Nie, std::string nie jest zaimplementowany jako lista wiązana. Obiekty tej klasy zawierają wskaźnik do tablicy znakowej. Zresztą, wystarczy zobaczyć sobie w źródłach:
/usr/include/c++/4.3.3/bits/basic_string.h:

Kod: Zaznacz cały

	_CharT* _M_p; // The actual data.
Tak więc, std::string wewnętrznie wykorzystuje tablicę znakową, a metoda c_str() po prostu zwraca wskaźnik do tej tablicy.
Tak tablica znaków jest - z tym, że nie są w kolejności jaka jest potrzebna... C string "tekst", w tablicy znaków w stringu może wyglądać tak "sektt", a osobno jest przechowywana lista ze wskaźnikiem do konkretnego chara i wskaźnikiem na kolejny element.

Odp: [C++]Zamieszanie ze stringami typu char*

: 18 lis 2009, 23:02
autor: el.pescado
Nie wiem czemu to miałoby służyć taka implementacja - a zajmowałaby od 9 do 17 razy więcej miejsca, zależnie od architektury.

std::string zawiera najzwyklejszą tablicę znaków. wystarczy spojrzeć na metodą c_str():

Kod: Zaznacz cały

      _CharT*
      _M_data() const
      { return  _M_dataplus._M_p; }

      const _CharT*
      c_str() const
      { return _M_data(); }

Odp: [C++]Zamieszanie ze stringami typu char*

: 19 lis 2009, 23:02
autor: mikolajs
Zgadzam się, że warto wykorzystywać zalety języka C++, ale jeśli potrzebujesz c string lepiej użyć tablicy znaków niż std::string::c_str(), bo jak pewnie dobrze wiesz, że w string nie jest przechowywany c string tylko osobno znaki, nie po kolei (każda litera ma wskaźnik na kolejną w kolejce) i musi zaalokować pamięć na nowego c stringa, i przepisać wszystko po jednej literce.
Klasa string jest stworzona do manipulacji. Jeżeli chcesz zmieniać string to jest to warto jej użyć, jeżeli tylko chcesz przekazać napis do metody to wystarczy const char*
Co prawda w wielu językach (Java, Scala, Python) stringi faktycznie opierają się na stałych napisach znakowych i nie stosuje się kontenera, ale nie opłaca się tego samodzielnie pisać w C++, wygodniej jest używać kontenerów.