Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++ ja kahden char-taulukon yhdistäminen

Sivun loppuun

pake10 [18.06.2010 12:03:05]

#

Olen vielä ihan aloittelija C++-kielessä, ja yritän saada seuraavan koodin toimimaan:

#include <iostream>
#include <direct.h>

using namespace std;

int main() {

char drive[400] = _getdrive() + 0x40 + ":\\";
char path[400] = "Users\\xxx\\Desktop\\kansiox";

strcat(drive, path);

cout << drive << endl;

}

g++ -kääntäjä kuitenkin valittaa tästä virheestä

koodix.cpp:10: error: invalid initializer

Kysehän on varmasti ihan yksinkertaisesta asiasta, mutta miten tämän saisi toimimaan?

vehkis91 [18.06.2010 12:18:09]

#

EDIT: katoinki, että toi gerdrive() funktio palauttaa int-tyyppistä dataa, joten koodin vähän muutosta.

EDIT2: oli väärin päin yks juttu, korjattu

Voisi olla helpompaa käyttää stringiä.

#include <string>
#include <iostream>
#include <direct.h>

int main()
{
  std::string drive = itoa(_getdrive()) + 0x40 + ":\\";
  std::string path  = "Users\\xxx\\Desktop\\kansiox";

  drive += path;

  std::cout << drive << std::endl;

}

jos taas välttämättä haluat käyttää c-tyylistä, niin sitten näin (ainakin luulisin)

#include <iostream>
#include <direct.h>

int main()
{
  char drive[800];

  strcat(drive, itoa(_getdrive());
  strcat(drive, 0x40);
  strcat(drive, ":\\");
  strcat(drive, "Users\\xxx\\Desktop\\kansiox");

  std::cout << drive << std::endl;

}

pake10 [18.06.2010 13:05:04]

#

Eipä toiminut.

Luultavasti johtuu siitä, että itoa -funktio ei palauta mitään arvoa, vaan se pitää laittaa johonkin muuttujaan. Jotain tällaista yritin tehdä:

#include <string>
#include <iostream>
#include <direct.h>

int main()
{
  char buffer[400];
  itoa(_getdrive(), buffer, 10);
  char drive[400];
  strcat(drive, buffer);
  strcat(drive, 0x40);
  strcat(drive, ":\\");
  char path[400]  = "Users\\xxx\\Desktop\\kansiox";

  strcat(drive, path);

  std::cout << drive << std::endl;

}

mutta heittää virheen:

koodix.cpp:11: error: incompatible types in assignment of `int' to `char[400]'

Jostain englanninkieliseltä foorumilta luin, että _getdrive() palauttaa numeron ja se muuttuu kirjaimeksi lisäämällä tuohon tuo 0x40, ja niin se tekikin (kokeilin).

Metabolix [18.06.2010 13:31:37]

#

Voit käyttää sprintf-funktiota:

char teksti[400];
int luku = 10;
float liukuluku = 12.34;
char toinen_teksti[100] = "heippa!";

sprintf(teksti, "luku = %d, liukuluku = %f, teksti = '%s'.", luku, liukuluku, toinen_teksti);
std::cout << teksti << std::endl;

Muista huolehtia, että taulukko, johon teksti luodaan, on tarpeeksi iso!

Teuro [18.06.2010 13:41:53]

#

Virtapuskureiden avulla tuo voidaan tehdä aika helpolla. Luku ei muutu kirjaimeksi, vaan tuo on char tietotyypin ominaisuus, koska esimerkiksi iso A-kirjain on char(65), joten tämä koodi tekee luultavasti sen mitä haluat.

#include <string>
#include <iostream>
#include <sstream>
#include <direct.h>

int main() {
	std::stringstream os;

	//char drive = _getdrive() + ('A'-1);
	char drive = _getdrive() + 0x40;

	std::string path = "Users\\xxx\\Desktop\\kansiox";
	std::string tmp;

	os << drive << ":\\" << std::endl;
	os >> tmp;

	std::string final = tmp + path;

	std::cout << final << std::endl;

	return EXIT_SUCCESS;
}

Eli on ihan sama käytätkö _getdrive() + ('A'-1) tai 64 tai 0x40 aina pitäisi tulla sama lopputulos. Kyseessä tosin oli char taulukoiden yhdistäminen,joten tämä ei ole ihan tarkalleen vaatimusten mukainen tuotos, mutta toisaalta haluttiin käyttää c++ kieltä...

Metabolix [18.06.2010 13:51:13]

#

Teuron esimerkkiä voi valitettavasti hieman kritisoida: Miksi pitää luottaa char-magiaan, vaikka käytetään virtoja? Entä miksi virtaan tulostetaan turha rivinvaihto ja miksi teksti luetaan virrasta >>-operaattorilla? Alla on koodista parempi versio:

#include <string>
#include <iostream>
#include <sstream>
#include <direct.h>

int main() {
	std::ostringstream os; // huomaa lisätty o, pelkkä output.

	// Jos tämä tulee muualta, muuttuja on ok.
	// Muutenhan vakio kannattaisi tulostaa suoraan!
	std::string path = "Users\\xxx\\Desktop\\kansiox";

	// Muodostetaan virtaan suoraan koko teksti ilman char-kikkailuja.
	// Virrasta sen saa helposti takaisin str-funktiolla.
	os << _getdrive() << ":\\" << path;
	std::string final = os.str();

	std::cout << final << std::endl;
	return 0;
}

Teuro [18.06.2010 13:57:42]

#

Olet aivan oikeassa tuo oli aika pitkälti miettimättä kirjoitettu pätkä. Rivinvaihdon olen tottunut lukemaan virtaan aina, koska olen ymmärtänyt sen tekevän flush() kutsun samalla, jolloin virtaa voi käyttää myöhemminkin ja virrassa ei pitäisi olla mitään kamaa valmiina. tuo std::ostringstream oli tarkoitus kirjoittaa, mutta o unohtui alusta. Viimeinen virhe oli, että en jaksanut hakea tuota str() funktiota. Tiesin sen siis onnistuvan pelkällä std::string avulla.

Ainoa puuttuva osa taitaa olla tuo, ettei aseman kirjain tule tuosta vielä. Tällaisella char purkalla tuokin tulee oikein, mutta parempikin ratkaisu taitaa olla olemassa.

#include <string>
#include <iostream>
#include <sstream>
#include <direct.h>

int main() {
	std::ostringstream os;

	std::string path = "Users\\xxx\\Desktop\\kansiox";

	os << char(_getdrive() + 64) << ":\\" << path << std::endl;

	std::string final = os.str();

	std::cout << final << std::endl;

	return EXIT_SUCCESS;
}

Metabolix [18.06.2010 14:20:42]

#

Teuro kirjoitti:

Ainoa puuttuva osa taitaa olla tuo, ettei aseman kirjain tule tuosta vielä.

Kas, ajattelin, että haluttiin vain numero merkiksi (0 => '0'). Jos on tarkoitus tehdä muunnos kirjaimeksi, olisi joka tapauksessa järkevämpää käyttää edes tuota aiemmin pois kommentoimaasi tapaa 'A' + n - 1, josta on helpompi päätellä, mitä tapahtuu. Toinen vaihtoehto on valmiin tekstin ja indeksin käyttö:

char merkki = "_ABCDEFG"[_getdrive()];

Flush ei ole stringstreamien kanssa ainakaan tällaisessa tapauksessa tarpeen, ja nykyinen versiosi ainakin toimii tuolta osin väärin, nimittäin ruudulle päätyy kaksi rivinvaihtoa (stringstreamiin tulostettu ja myöhemmin suoraan coutiin tulostettu).

Teuro [18.06.2010 14:25:37]

#

Joo tuo 'A'-1+n on selkempi tapa taatusti. Voin olla tosiaan väärässä noissa virtapuskureissa, mutta jossakin projektissani käytin tuota virtaa ilman std::endl ja seuraavassa kohdassa virrassa oli edelleen hetki luettu ja muuttujaan sijoitettu data.

Tässä vielä versio, jossa ei ole virtapuskureita sen kummemmin kuin char muuttujaakaan.

#include <string>
#include <iostream>
#include <direct.h>

int main() {
	std::string asemat = "_ABCDEFG";
	std::string asema = asemat.substr(_getdrive(), 1);

	std::cout << asema + ":\\Users\\xxx\\Desktop\\kansiox" << std::endl;

	return EXIT_SUCCESS;
}

Joopa joo josko se olis sitten tässä?

pake10 [18.06.2010 14:58:36]

#

Toteutin sitten homman näin:

#include <iostream>
#include <direct.h>
#include <string>

using namespace std;

int main()
{
string abc[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
int drive = _getdrive();
string drive_letter = abc[drive - 1];

drive_letter += ":\\Users\\xxx\\kansiox";

cout << drive_letter << endl;
}

Teuro [18.06.2010 15:14:07]

#

Ei ole fiksua tehdä std::string-tyyppistä taulukkoa, koska se on jo taulukko itsessään (tavallaan). Eli tällainen toteutus on myös mahdollinen. std::asemat ensimmäinen alkio voi olla mikä tahansa, koska _getdrive() palauttaa 1-n paluuarvonaan. Tässä esimerkiksi se on tyhjä

#include <iostream>
#include <direct.h>
#include <string>

int main(){
	std::string asemat = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	std::cout << asemat.substr(_getdrive(), 1) + ":\\Users\\xxx\\kansiox" << std::endl;

	return EXIT_SUCCESS;
}

pake10 [18.06.2010 15:25:25]

#

Nyt tuli kuitenkin sellainen ongelma, että funktio, jossa tuota käytän hyväksyy vain charin parametrikseen.. Eli pitäisikö tuo jotenkin muuttaa chariksi?

Teuro [18.06.2010 15:28:36]

#

Tai sitten ekassa vaihessa käsket näin:

void funktio(const char* joku);

//muuttuja funktiolle
std::string muuttuja_funktiolle = "moi";

funktio(muuttuja_funktiolle.c_str());

Jatkossa voit muokata tuon funktion tukemaan std::string:ä

pake10 [18.06.2010 17:26:46]

#

Kiitos, koko homman sain toimimaan näin:

#include <iostream>
#include <direct.h>
#include <string>

int _chdir(const char* path);

int main()
{
    std::string drives = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    std::string drive = drives.substr(_getdrive(), 1);

	std::string location = drive + ":\\kansiox";

	if(_chdir(location.c_str()) != 0) {
	std::cout << "Kansiota ei ole olemassa." << std::endl;
	} else {
	std::cout << "Kansio on olemassa." << std::endl;
	}
}

Teuro [18.06.2010 17:36:37]

#

Niin siis _chdir(const char*); on tietenkin olemassa, joten sitä ei tarvitse erikseen esitellä. Toisaalta eihän siitä haittaakan liene. Tuo minun esimerkkini vain vaati tuon funktio-esittelyn kirjoittamisen, että vinkin lukija näkee miten funktiota kutsutaan.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta