Čtení vstupu pro více zadaných prvků najednou – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Čtení vstupu pro více zadaných prvků najednou – C / C++ – Fórum – Programujte.comČtení vstupu pro více zadaných prvků najednou – C / C++ – Fórum – Programujte.com

 

Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #1
-
0
-

Zdravím,

řeším úlohu kde mám najít průnik množin a mám trchu dilema s načtením.

Výsledné řešení by mělo vypadat takto:

Zadejte pocet prvku mnoziny A:
5
Zadejte prvky mnoziny A:
1 3 7 9 4
Zadejte pocet prvku mnoziny B:
6
Zadejte prvky mnoziny B:
15 1 4 99 3 17
Prunik mnozin:
{1, 3, 4}

Z první informace mám velikost pro pole, do kterého tu množinu vložím ale nevím jakým způsobem jsem schopný načíst tu řadu prvků do pole.

Řešení které mě napadlo::

načíst, řádek jako string, projít ho a vysekat z něj jednotlivé stringy čísel a ty pak převést na čísla

- asi bych to tím vyřešil ale příjde mi, že jsem spíš obešel myšlenku toho co bych se tím měl naučit ... můžete mi poradit jak bych to udělat?

můj kod vypadá takto:

int nacteni()
{
    int velikostA, velikostB;
    cout << "Zadejte pocet prvku mnoziny A:" << endl;
    cin >> velikostA;
    if(!imputERR)
    {
        cout << "Zadejte prvky mnoziny A:" << endl;
        int mnozinaA[velikostA];
        for(int i=0; i<sizeof(mnozinaA)/sizeof(mnozinaA[0]); i++)
        {
		//Zde bych potřeboval nějakým způsobem projít vstup
        }
    }
}
Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #2
-
0
-

Prvky jsou číslo mezera číslo mezera. Takže musíš v cyklu vždy přečíst číslo, pak přečíst mezeru (tu "zahodit"), cyklus ukončit když za posledním číslem nebo mezerou nic není. Možná je jednodušší načíst vstup do std::string a pak rozebrat, u C-čkového řetězce to velice dobře uměla funkce sscanf. Načtená čísla skládej do vektoru. V podstatě není třeba znát velikost množin. Velikost množiny je pak počet prvků ve vektoru.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #3
-
0
-

#2 hlucheucho
Mohl by si ukázat jak bych si to přes sscanf načetl, já jsem zatím využíval jen cin a tak s ní nemám zkušenosti.

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #4
-
0
-

Jsem zkoušel s cin číst čísla s mezerou 

string vstup;

cout << "zadej" << endl;
cin >> vstup;

když zadám čísla oddělená mezerou, načte jen první. Což vede k myšlence číst po jednotlivých číslech takto: 

	cout << "zadej" << endl;
	do {
		cin >> cislo;
		pocet++;
	} while (pocet != 5);  //nacte 5 cisel

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #5
-
0
-

A hned jsem narazil na další problém týkající se předávaní polí ... toto je věc co mi v C++ stále uniká ... 

takto vypadá můj kod

int testA[] = {1,3,7,9,4};
int testB[] = {15,1,4,99,3,17};

int main()
{
    prunik(testA,testB);
    return 0;
}

int prunik(int mnozinaA[],int mnozinaB[])
{
    cout << sizeof(mnozinaA)/sizeof(mnozinaA[0]) << endl;
    cout << sizeof(mnozinaB)/sizeof(mnozinaB[0]) << endl;
    cout << sizeof(testA)/sizeof(testA[0]) << endl;
    cout << sizeof(testB)/sizeof(testB[0]) << endl;
    return 0;
}

a takto vypadá výstup:

1
1
5
6

Můžete mi někdo objasnit WHY??? Nerozumím proč to tak je, z mého pohledu to nedává smysl. Prosím co mi uniká?

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #6
-
0
-

Funkci kromě ukazatele musíš předat i velikost pole, jinak neví, kde pole končí

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #7
-
0
-

#4 hlucheucho
to není problém ... na toto využiješ funkci getline

 getline(cin, vstup);

nacte celý řádek ... to jsem schopný udělat ale tato cesta se mi zdá podivně trnitá, proto se právě ptám jak jinak to zrobit

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #8
-
0
-

Zbytečný číst celý řádek, když jdou číst jednotlivá čísla přímo jako int. Jinak mnozinaA je ukazatel a tak sizeof(mnozinaA) vrátí velikost ukazatele, pravděpodobně 4.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #9
-
0
-

#6 hlucheucho
no a když nechci předat ukazatel ale celé pole ... ? jak to udělat?

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #10
-
0
-

Pokud chceš funkci předat pole, musíš předat ukazatel a velikost. Jinak si lze usnadnit práci tím, že místo pole použiješ vector, pak by mělo stačit funkci předat ukazatel na vector

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #11
-
0
-

ehm ... trochu bych potřeboval objasnit zmatek, který mám teď v hlavě ... 

takže ... dejme tomu že mám funkci na načtení pole ... 

to pole vytvořím v té funkci a chci ho předat dále ... 

takže ... před to pole nejde ale předám ukazatel a velikost toho pole 

(jsem zmateny bo v jave by to pole po skonceni funce zaniklo)

a dále s ním musím pracovat už jen přes ukazatel?

Nahlásit jako SPAM
IP: 78.108.147.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #12
-
0
-

tak teď už jsem selhal při basic kompilaci ...  

int prunik(int mnozinaA[],int sizeA, int mnozinaB[], int sizeB);

int mnozinaA[] = {1,3,7,9,4};
int mnozinaB[] = {15,1,4,99,3,17};
int sizeA, sizeB;
int main()
{

    sizeA = sizeof(mnozinaA)/sizeof(mnozinaA[0]);
    sizeB = sizeof(mnozinaB)/sizeof(mnozinaB[0]);
    prunik(mnozinaA, sizeA, mnozinaB, sizeB);
    return 0;
}

takto jsem to přepsal podle tvé rady a z kompilátoru mi vylezla tato chyba ... 

undefined reference to `prunik(int*, int, int*, int)'

musí mi stále unikat nějaké základní pravidlo jinak už nevím ... 

Nahlásit jako SPAM
IP: 78.108.147.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #13
-
0
-

a co znamená int* nebo int** mi taky uniká

Nahlásit jako SPAM
IP: 78.108.147.–
Satik0
Stálý člen
27. 11. 2014   #14
-
0
-

#13 Petr
To jsou základy, hvězdička znamená ukazatel, pole se v C předávají tak, že předáš ukazatel na první prvek a v dalším parametru velikost pole.

Nahlásit jako SPAM
IP: 86.49.188.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #15
-
0
-

ano to jsem vyčetl ale není mi jasné co to vlastně představuje ... 

když mám 

int mojepole[5];

tak ukazatel na to pole je přece mojepole, proč ta hvezdička?

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #16
-
0
-

Pokud chceš ve funkci vytvořit pole a to pak předat volajícímu, vznikne problém. Každá proměnná uvnitř funkce zaniká při návratu funkce. Takže  

int* NovePole()
{
  int pole[5] = {5,4,3,2,1};
  return pole;
}

je sice syntakticky správně a přeloží se bez chyb, ale za běhu programu dojde k zásahu do paměti, která ti nepatří. Z jakého důvodu: při volání funkce se alokuje paměť pro pole, toto se inicializuje. Při návratu funkce se paměť pro pole uvolní a předá se návratová hodnota - již neplatný ukazatel na pole. Řeší se to tak, že funkci předáš ukazatel a velikost již vytvořeného pole, funkce do něj zapíše a např. vrátí počet úspěšně zapsaných prvků pole. Druhá možnost je uvnitř funkce dynamicky alokovat pole např. pomocí malloc a předat takto získaný ukazatel. Opět ale potřebuješ mít i informaci o velikosti pole. Pak také musíš pamatovat na uvolnění takto alokované paměti.

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:941e:ff...–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #17
-
0
-

#16 hlucheucho
Už asi z části rozumím, právě ta práce z pamětí je pro úplně nová a proto v tom tak plavu.

napsal jsem teto kod:

int prunik(int mnozinaA[],int sizeA, int mnozinaB[], int sizeB)
{
    int prunikMaxSIZE;
    int prunikRealSIZE = 0;
    
    if(sizeA < sizeB) prunikMaxSIZE = sizeA;
    else prunikMaxSIZE = sizeB;
    
    int prunik[prunikMaxSIZE];
    for(int i=0; i<sizeA; i++)
    {
        for(int j=0; j<sizeB; j++)
        {
            if(mnozinaA[i]==mnozinaB[j])
            {
                prunik[prunikRealSIZE] = mnozinaA[i];
                prunikRealSIZE++;
            }
        }
    }
    return prunikRealSIZE;
}

Jakmile ta funkce skončí pole prunik zmizí a je pro mě ztraceno, Takže pokud bych ho pole chtěl nějakým způsobem z té funkce vytáhnout musím si tu pamnět "natvdo" zaalokovat?

Nebo je působ jak to pole z té funkce vrátím i s jeho velikostí?

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #18
-
0
-

nejjednodušší je pole vytvořit u volajícího, tedy mimo funkci a funkci předat ukazatel a velikost. Funkce do takového pole zapíše a hodnoty v něm zůstanou i po jejím návratu 

void funkce(int* ukpole, int velikost)
{
  for (int i = 0; i < velikost, i++)  ukpole[i] = i;
}

a použití 

pole[10];

funkce(pole, 10);

Pokud pole vytvoříš jako class, vytvoříš konstruktor, kopírovací konstruktor a destruktor, tak by návratovou hodnotou funkce mohla být přímo tato class.

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:941e:ff...–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #19
-
0
-

rozumím tomu jak to myslíš ale nejsem ale když neznám velikost nejsem schopen to pole dopředu vytvořit ... leda bych to pole tvořil dynamicky

Nahlásit jako SPAM
IP: 78.108.147.–
Satik0
Stálý člen
27. 11. 2014   #20
-
0
-

#19 Petr
Pokud neznáš velikost předem, tak

  • vytvoř ho tak velký, aby jsi tam měl nějakou rezervu a třeba ho i většinu nevyužil
  • nepoužij pole, ale třeba Vector

Nahlásit jako SPAM
IP: 86.49.188.–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #21
-
0
-

My si asi úplně nerozumíme :) 

vytvořit ho staticky velké je easy, s tím co si napsal plně souhlasím a bude to tak i fungovat ale pokud bych to tak udělal nesplním zadání a nedostanu body ... 

řeším terazky jinou úlohu bez práce s poli ... jak to dopíšu vrátím k polím pokusím se to nudělat dynamicky

Nahlásit jako SPAM
IP: 78.108.147.–
27. 11. 2014   #22
-
0
-

Alokovat pole, realokovat pole pokud je malé.... Proto ti radíme vector. Tyhle věci si vector dělá sám, navíc ti vložené prvky spočítá. Vector je šablona pole, které si samo alokuje a realokuje paměť a eviduje velikost alokované paměti a počet uložených prvků. Má přetížený operátor [], takže se s ním pracuje stejně jako s běžným polem.

Možná by se ta úloha dala udělat tak, že si šablonu zkopíruješ a přejmenuješ. Tím bude bodování učiněno zadost a použiješ vector s minimem úsilí. Akorát musíš vědět, jak šablonu napsat, jak to funguje.

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:941e:ff...–
Petr
~ Anonymní uživatel
746 příspěvků
27. 11. 2014   #23
-
0
-

aha s vektorem nemám zkušenosti mohl by si ukázat příklad využití vektoru, který bych pro to mohl použit?

Nahlásit jako SPAM
IP: 78.108.147.–
ondrej39+1
Věrný člen
27. 11. 2014   #25
-
0
-

#17 Petr
Samozřejmě, že ti zmizí. Podívej se, co ti funkce vrací - vrací ti integer - celé číslo. Pokud chceš vrátit pole, je třeba vrátit ukazatel na něj.

EDIT: Jinak jak píše hu, pole se v c++ nedají vytváře způsobem, jakým ty chceš (tj. uživatel zadá velikost a vytvoří se pole o dané velikosti, tedy velikost bude na stacku proměnná - na heapu to jde), ale doporučené vektory toto umějí.

Proměnná velikost pole na heapu (+ částečné plnění a tisk obsahu):

#include <iostream>

int main()
{
	setlocale(LC_ALL, "");

	int velikostPoleA, velikostPoleB; // definice proměnné, aby uživatel mohl zadat velikost polí

	std::cout << "Zadejte počet prvků první množiny: ";
	std::cin >> velikostPoleA; // uživatel zadává velikost prvního pole
	std::cout << std::endl;

	int * poleA = new int[velikostPoleA+1]; // tvorba prvního pole o zadané velikosti; přidáváme jedničku kvůli zarážce	

	std::cout << "Zadejte počet prvků druhé množiny: ";
	std::cin >> velikostPoleB; // uživatel zadává velikost druhého pole
	std::cout << std::endl;		

	int * poleB = new int[velikostPoleB+1]; // tvorba druhého pole o zadané velikosti; přidáváme jedničku kvůli zarážce	

	// naplnění pole daty
	std::cout << "Zadejte " << velikostPoleA  << " čísel:" << std::endl;
	for (int i = 0; i < velikostPoleA; i++)
	{
		int zadavaneCislo;
		std::cout << i + 1 << ". číslo: ";
		std::cin >> zadavaneCislo;
		*(poleA + i) = zadavaneCislo;
	}

	// tisk pole
	for (int i = 0; i < velikostPoleA; i++)
	{
		if (i == velikostPoleA-1)
			std::cout << *(poleA + i) << std::endl;
		else
		std::cout << *(poleA + i) << ", ";
	}

	// další část programu

	delete[] poleA; // mazání prvního pole
	delete[] poleB; // mazání druhého pole
}
Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
ondrej39+1
Věrný člen
28. 11. 2014   #26
-
0
-

Tak jsem zjistil, že není třeba tvořit pole o 1 větší (jak tam přidávám tu jedničku), to +1 ve velikosti tedy můžeš oddělat.

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×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, 113 hostů

Moderátoři diskuze

 

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