(C++) Převod const unsigned char * na string – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama

(C++) Převod const unsigned char *  na string – C / C++ – Fórum – Programujte.com(C++) Převod const unsigned char * na string – C / C++ – Fórum – Programujte.com

 

Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
14. 5. 2017   #1
-
0
-

Ahoj, potřebuju převést const unsigned char * proměnnou na string, ale nic co jsem zkoušel nefunguje. Buď se to ani nezkompiluje a pokud náhodou ano, tak to hodí Segmentation fault (core dumped). :(

Díky moc za jakoukoliv radu.

Nahlásit jako SPAM
IP: 109.81.208.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
Reklama
Reklama
KIIV
~ Moderátor
+42
God of flame
15. 5. 2017   #2
-
0
-

#1 richard.zavodny
nejake ukazky kodu nejsou?

Musi fungovat, snad jen pokud bys tomu hazel null pointer.

Pripadne to poustej v debuggeru, bude aspon ukazovat, co v promennych zrovna je

Nahlásit jako SPAM
IP: 213.220.205.–
Program vždy dělá to co naprogramujete, ne to co chcete...
15. 5. 2017   #3
-
0
-

Aha, tak problém nebude v převodu, ale v něčem jiném (pole?). Tady je kód, aby jste pochopil/i, o co se snažím.
 

if(rc == SQLITE_DONE || rc == SQLITE_ROW) {
        while(rc == SQLITE_ROW) {
            int rowCount = 0;
            int columnCount = sqlite3_column_count(statement);

            for(int i = 0; i < columnCount; i++){
                string returnData[rowCount] = {(const char*)(sqlite3_column_text(statement, i))};

                cout << returnData[rowCount][columnCount] << "\n";
            }

            rc = sqlite3_step(statement);
            rowCount++;
        }

        cout << "yes" << "\n";
    } else {
        cout << "no" << "\n";
    }
Nahlásit jako SPAM
IP: 109.81.208.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
gna
~ Anonymní uživatel
277 příspěvků
15. 5. 2017   #4
-
0
-

   

string returnData[rowCount]                            // tohle je pole stringů,
 = {(const char*)(sqlite3_column_text(statement, i))}; // ve kterém inicializuješ první string hodnotou sloupce

cout <<
        returnData[rowCount]                           // tímhle získáš string z pole
                                                       //   teda vlastně ne, když je ten index mimo rozsah toho pole
                            [columnCount]              // a tímhle znak z toho stringu
                                                       //   teda kdyby to byl platný index v platném stringu.
                                          << "\n";

Věci, které jsi dělal už stokrát! Nečaruj, přemýšlej. 

for (int i = 0; i < columnCount; i++) {
	cout << sqlite3_column_text(statement, i) << "\n";
}
Nahlásit jako SPAM
IP: 213.211.51.–
KIIV
~ Moderátor
+42
God of flame
15. 5. 2017   #5
-
0
-

Souhlas s gna. Kazdopadne jako zacatecnik bys mel psat jeste komentare "co si myslis, ze by to melo delat", protoze z toho kodu je to pomerne hodne nepochopitelne.

Jako jo, evidentne se tam snazis vypsat jednotlive sloupce. Ale opravdu silenym zpusobem a bez pochopeni, jak vlastne funguji pole, natoz dvourozmerne.

Nahlásit jako SPAM
IP: 212.47.3.–
Program vždy dělá to co naprogramujete, ne to co chcete...
15. 5. 2017   #6
-
0
-

Ták, problém vyřešen. Ano, komentáře bych psát měl, na toto jsem hodně líný. Jestli je i nějaký elegantnější způsob, sem s ním, rád se přiučím. :) Co se týče dvourozměrných polí, tak o ty jsem "štřejchnul" v PHP. Nějak moc jsem je nepotřeboval, takže jsem je asi úplně nepochopil. V C++ jsem nový. Učím se ho metodou pokus, omyl cca. 5 měsíců a ještě k tomu na praktickém příkladu, takže jsem dá se říci přeskočil teorii a něco mi asi uteklo.

No, každopádně tady je funkční kód, který dělá přesně to co chci: 

if(rc == SQLITE_DONE || rc == SQLITE_ROW) {
        while(rc == SQLITE_ROW) {
            int rowCount = 1;
            int columnCount = sqlite3_column_count(statement);
            string returnData[rowCount][columnCount];

            for(int i = 0; i < columnCount; i++) {
                returnData[rowCount-1][i] = (const char*)(sqlite3_column_text(statement, i));

                cout << returnData[rowCount-1][i] << "\n";
            }

            cout << "\n";
            
            rc = sqlite3_step(statement);
            rowCount++;
        }

        cout << "yes" << "\n";
    } else {
        cout << "no" << "\n";
    }


Každopádně díky moc. :)

Nahlásit jako SPAM
IP: 109.81.208.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
KIIV
~ Moderátor
+42
God of flame
15. 5. 2017   #7
-
0
-

Nu moc sis nepomohl, jakmile ti to vrati vic jak jeden radek, tak ses zase mimo pole :D Nicmene nastesti si tu inkrementovanou hodnotu nepamatujes, takze ses stale na prvnim radku.

Projdeme si tvoje reseni:

        while(rc == SQLITE_ROW) {
            
            // pocet radek nastavis na 1 (v kazdem kole)
            int rowCount = 1;

            // pocet sloupcu si alespon zjistis:
            int columnCount = sqlite3_column_count(statement);

            // zahadne definujes dvourozmerne pole o jednom radku a sloupce jsou spravne
            string returnData[rowCount][columnCount];

            // jedine co tu dava jakz takz smysl:
            for(int i = 0; i < columnCount; i++) {

                // pro prvni radek dejme tomu funguje (ostatne ted je kazda iterace while prvni radek :D),
                // ale proc je to potreba ukladat do pole, kdyz jen vypisujes aktualni polozku?
                returnData[rowCount-1][i] = (const char*)(sqlite3_column_text(statement, i));

                // proc radeji nepouzijes reseni co tu nahodil gna?
                // Tady na toto neni potreba ani extra promenna, operator<< umi vypsat i const char* 
                cout << returnData[rowCount-1][i] << "\n";

            }

            cout << "\n";
            
            rc = sqlite3_step(statement);
            
            // A toto by zpusobilo pad. Tedy kdyby sis pamatoval v dalsim kole inkrementovanou hodnotu.
            // Nastesti platnost teto promenne hned pote skonci a zacinas s cistym stitem znovu od 1:
            rowCount++;
        }

A ted trosku vylepsene (podle gna):

        while(rc == SQLITE_ROW) {
            // toto je jedina promenna co se hodi, zjisteni jeji hodnoty
            // muze byt narocne, tudiz je lepsi mit to mimo podminku cyklu
            int columnCount = sqlite3_column_count(statement);
            
            for(int i = 0; i < columnCount; i++) {
                 // rovnou to hodim do coutu, jelikoz to stejne nikde nepouzivas
                 // a cout zvlada vypsat i C retezce
                 cout << sqlite3_column_text(statement, i) << "\n";
            }
            cout << "\n";

            rc = sqlite3_step(statement);
        }
Nahlásit jako SPAM
IP: 213.220.205.–
Program vždy dělá to co naprogramujete, ne to co chcete...
15. 5. 2017   #8
-
0
-

#7 KIIV
Pardon, já zapomněl dodat jeden důležitý fakt, a to ten, že si tu returnData proměnnou chci vrátit zpět do funkce, ze které ji volám (referencí). Teď si to vypisuji jen "pro oko", abych viděl jestli ta proměná něco vrací. :)

Nahlásit jako SPAM
IP: 109.81.208.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
KIIV
~ Moderátor
+42
God of flame
15. 5. 2017   #9
-
0
-

#8 richard.zavodny
tak to tim spise musis udelat poradne (ted z toho nevymlatis nic jineho nez posledni radek). A hlavne budes muset pouzit spis neco jako vector (kterej se alespon zkopiruje, pokud ho vratis z funkce). Urcite nemuzes vratit ukazatel na to pole, jelikoz s koncem existence funkce prestane existovat i to pole.

Nahlásit jako SPAM
IP: 213.220.205.–
Program vždy dělá to co naprogramujete, ne to co chcete...
MilanL0
Návštěvník
18. 5. 2017   #10
-
0
-

#8 richard.zavodny
v Delphi jsem tohle řešil přes vlastní typ T2DArrayString = array of array of string; předáván jako 'var' argument funkci, ve funkci pak lze změnit oba rozměry pole pomocí length pro řádky (lze postupně přidávat každou řádkou z DB zvětšit length o 1) a poté pro sloupce, dokonce mám dojem, že šlo pro každou řádku nastavit jiný počet sloupců.

V C++ moc nedělám, ale vypadalo by to asi takto: 

//ve volající funkci definovat pole: 
string **Data;

// **Data předávat v argumentu funkce
// nastavení počtu řádků - již ve funkci

Data = new string*[rowCount];	// rowCount z DB - první rozměr = počet řádek před smyčkou řádek, 
		// v případě přidávání po jedné by bylo třeba udělat reSize funkci,
		// kde vytvoříš nové větší pole a původní do něj zkopíruješ, 
		// poté původní smažeš a přiřadíš mu referenci nového.

int Radek = 0;	// čítač řádek

// Smyčka procházení řádků
{
	// Před smyčkou sloupců definuješ pomocné pole
	string *Radka = new string[columnCount];

	// FOR smyčka na sloupce pak
	{
		Radka[i] = (const char*)(sqlite3_column_text(statement, i));
	}
	Data[Radek] = Radka;      // pole sloupců do druhého rozměru pole Data
	Delete [] Radka;
	Radek++;
}

inspiraci jsem čerpal zde http://stackoverflow.com/questions/16001803/pointer-to-pointer-dynamic-two-dimensional-array

Nahlásit jako SPAM
IP: 91.139.9.–
KIIV
~ Moderátor
+42
God of flame
18. 5. 2017   #11
-
0
-

#10 MilanL
Ten  delete [] Radka; tam nedava smysl. Radka je alokovane pole a timto ho zlikvidujes a v Data[Radek] mas neplatny pointer.

Daleko lepsi je pouzit vector<vector<string>>. Nebude se resit alokace a dealokace, presuny to zvlada taky samo.

Nahlásit jako SPAM
IP: 212.47.3.–
Program vždy dělá to co naprogramujete, ne to co chcete...
MilanL0
Návštěvník
19. 5. 2017   #12
-
0
-

#11 KIIV

no psal jsem, že v C++ toho moc nedělám, pokud mi string *Radka=new string[columnCount]; alokuje vždy novej pointer tak tam samozřejmě delete být nemusí, vlastně ted mi došlo že v těch polích jsou Ukazatele (reference) a ne data. a že ta řádka Data[Radek]=Radka neznamená zkopírování dat z pole do pole, ale předání ukazatele Radka do pole ukazatelů v Data.

Ten Vector mi připadá hodně podobný tomu mému řešení, navíc to je lépe obalený typ než to pole ukazatelů.

Mě celkem jde zpětná analýza jen u některých typů jazyků (C++, OOP PHP a pod) mě matou některé ty tečkové, <<, >> , :: a typové konvence.

Nahlásit jako SPAM
IP: 185.112.167.–
19. 5. 2017   #13
-
0
-

#10 MilanL
Díky za opdověď, bohužel z tvého "kódu" nechápu absolutně nic, zkrátka je v tom chaos.

#9 KIIV
Pole bych si měl umět vrátit, když jsem schopný vrátit si proměnnou, nebo se mýlím? Já si ve volající funkci definuji proměnnou, pošlu ji v parametru funkce a potom ji pomocí reference vrátím (nastavím novou hodnotu) a dále jsem schopný s ní pracovat, i když funkce již "zanikne".

Nahlásit jako SPAM
IP: 89.24.189.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
19. 5. 2017   #14
-
0
-

Mám databázovou funkci:

void db(string *data, string databaseName, char *databaseStatement) {
    sqlite3 *db;
    sqlite3_stmt *statement;
    int rc;

    rc = sqlite3_open(databaseName.c_str(), &db);

    rc = sqlite3_prepare_v2(db, databaseStatement, -1, &statement, 0);

    rc = sqlite3_step(statement);

    if(rc == SQLITE_DONE || rc == SQLITE_ROW) {
        int rowCount = 1;

        while(rc == SQLITE_ROW) {
            int columnCount = sqlite3_column_count(statement);
            string returnData[rowCount][columnCount];

            for(int i = 0; i < columnCount; i++) {
                returnData[rowCount-1][i] = (const char*)(sqlite3_column_text(statement, i));
                
                cout << returnData[rowCount-1][i] << "\n";
            }

            rc = sqlite3_step(statement);
            rowCount++;
        }

        cout << "yes" << "\n";
    } else {
        cout << "no" << "\n";
    }

    sqlite3_finalize(statement);

    sqlite3_close(db);
}


A toto je hlavní funkce:

int main() {
	string dataReturn;

    	db(&dataReturn, "test.db", "SELECT * FROM test");

        return 0;
}


V prvním parametru předávám prázdnou proměnnou data, v té chci později vrátit pole s daty z databáze. Takhle mám postavené všechny funkce, které něco vrací a chtěl bych se toho pokud možno držet. :)

Nahlásit jako SPAM
IP: 89.24.189.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
KIIV
~ Moderátor
+42
God of flame
20. 5. 2017   #15
-
0
-

#14 richard.zavodny
ma to jen nekolik hacku:

string dataReturn;

Je JEDEN kontejnerovy objekt typu string. Zduraznuji ten jeden. Muzes do toho nacpat prave jeden retezec.

A zase dokola az do zblbnuti:

        int rowCount = 1;  // aspon je to uz mimo while

        while(rc == SQLITE_ROW) {

            int columnCount = sqlite3_column_count(statement);

            // TOTO JE LOKALNI PROMENNA!!!!! Jakmile skonci jeji platnost (na konci kazdeho kola while!),
            // tak se neda spolehnout na ty data! Natoz je nekam vracet z funkce
            string returnData[rowCount][columnCount]; 

            for(int i = 0; i < columnCount; i++) {
                returnData[rowCount-1][i] = (const char*)(sqlite3_column_text(statement, i));
                
                cout << returnData[rowCount-1][i] << "\n";
            }

            rc = sqlite3_step(statement);
            rowCount++;
        }

Par pveci, co o predavani parametru v C/C++ evidentne netusis:

  1.  jednoduche datove typy (vcetne pointeru) a objekty se vzdy predavaji hodnotou.
    - Muzes zmenit kam ukazuje pointer, ktery sis predal do funkce, ale venku je to stale ten puvodni.
    - Zmenit muzes jen data, na ktere se odkazuje.
  2. Pole je vlastne jen pointer s informaci o poctu polozek.
    - Pole se NIKDY NEPREDAVA HODNOTOU, vzdy jen tim POINTEREM, tudiz ve funkci uz neznas rozmer.
    - Pokud chces referenci, musis pouzit referenci a jeste pridat i spravny rozmer pole (pripadne pouzit template, kde se z toho da i rozmer rovnou vytahnout). Nicmene u statickeho pole stejne NEZMENIS JEHO UMISTENI!!!!

Nahlásit jako SPAM
IP: 93.91.151.–
Program vždy dělá to co naprogramujete, ne to co chcete...
MilanL0
Návštěvník
20. 5. 2017   #16
-
0
-

#14 richard.zavodny

to co řešíš je v podstatě dataset, osobně bych si na ty data nadefinoval třídu, potřebuješ z funkce vrátit 2 rozměrné pole včetně rozměrů (řádky X sloupce)

Nejsou náhodou v ROW=0 názvy sloupců?

#15 KIIV
zajímala by mě jedna věc, jak by se u 2D vectoru přidávali postupně ty řádky, sloupce bych věděl vector[I].push..., ale ten 1. rozměr mi není jasnej vector.push_back(vector<string>) ?

Zajímalo by mě i jak by to vypadalo s předáním toho 2d vektoru do funkce. Něco jsem zkoušel a nešlo mi to. Přes 2h jsem si s tím hrál s pomocí strýčka Googla a nic.

Nahlásit jako SPAM
IP: 185.112.167.–
KIIV
~ Moderátor
+42
God of flame
20. 5. 2017   #17
-
0
-

#16 MilanL
Neco takoveho:

#include <iostream>
#include <string>
#include <vector>

using Row  = std::vector<std::string>;
using Rows = std::vector<Row>;

Rows neco_dopln() {
    Rows vysledek;
    while (vysledek.size() < 6) {
        Row radek;
        for (int i = 0; i < 6; ++i) {
            // ja sqlite nemam, takze jen neco doplnim:
            radek.emplace_back(std::to_string((vysledek.size()+1)*1000 + i));

            //// v jeho pripade to bude:
            // radek.emplace_back(sqlite3_column_text(statement, i));
        }
        vysledek.emplace_back(std::move(radek)); // konkretne tady se chceme vyhnout kopii
    }
    return vysledek;
}

int main() {
    Rows radky = neco_dopln();

    // a vypis
    for (Row const & radek : radky) {
        std::cout << "| ";
        for (std::string const& polozka : radek) {
            std::cout << polozka << " | ";
        }
        std::cout << "\n";
    }
}

Vyhoda je, ze to muze mit libovolne dlouhe radky a vzdy jde zjistit, velikost radku i pocet radku. A hlavne se nemusi starat o uvolnovani pameti (pokud pamet alokuje)

Jo ten vypis se da i trosku zjednodusit (pomoci ostream_iterator z headeru <iterator>):

    for (Row const & radek : radky) {
        std::cout << "| ";
        std::copy(radek.begin(), radek.end(), std::ostream_iterator<std::string>(std::cout, " | "));
        std::cout << "\n";
    }

Da se to udelat i pro Rows. Jen se musi udelat pretizeni operatoru  <<  pro vypis Row.

Nahlásit jako SPAM
IP: 93.91.151.–
Program vždy dělá to co naprogramujete, ne to co chcete...
MilanL0
Návštěvník
20. 5. 2017   #18
-
0
-

#17 KIIV

dík, vypadá to s těma vektorama o dost jednodušeji, a je z toho vidět jak se ten první rozměr vytváří tím vkládáním druhého.

Můj fungující testík: 

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>

using namespace std;

vector<vector<string> > Napln()
{
	vector<vector<string> > data;

	srand(10);
	int rCount = 2 + rand() % 8;
	int cCount;

	for (int i = 0; i < rCount; i++)
	{
		vector<string> radka;
		cCount = 5 + rand() % 5;
		for (int j = 0; j < cCount; j++)
		{
			radka.emplace_back(to_string(1+rand()%9));
		}
		data.emplace_back(radka);
	}
	return data;
}

int main()
{
	vector<vector<string> > rData = Napln();

	for (int i = 0; i < rData.size(); i++)
	{
		for (int j = 0; j < rData[i].size(); j++)
		{
			cout << rData[i][j] << "\t";
		}
		cout << endl;
	}

	string vstup;
	cin >> vstup;  

    return 0;
}

Nahlásit jako SPAM
IP: 185.112.167.–
Zjistit počet nových příspěvků

Přidej příspěvek

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 80 hostů

Podobná vlákna

Const char v C — založil Halancik

Definice const char *[] — založil Remder

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032017 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý