Void* – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Void* – C / C++ – Fórum – Programujte.comVoid* – C / C++ – Fórum – Programujte.com

 

expoox0
Duch
12. 12. 2017   #1
-
0
-

Ahoj, potrebujem vypisat data ulozene vo void * ale neviem akeho su typu, teda mozu byt int, char alebo double. Viete mi prosim niekto poradit ako na to ?

Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
BDS+3
Věrný člen
12. 12. 2017   #2
-
0
-

#1 expoox
Nejprve musíš někde zjistit o jaký typ jde a jeho rozměr, no a pak to jen přetypuješ.

A jestli čekáš, že standardní typy se dají v C / C++ rozpoznat pomocí nějakých identifikátorů, tak nedají.

Nahlásit jako SPAM
IP: 185.69.69.–
W11 :)
KIIV
~ Moderátor
+43
God of flame
12. 12. 2017   #3
-
0
-

Vzdy tam musi byt nejaky zpusob, jak poznat, co je to za data. Bud podle kontextu (napriklad funkce pro porovnavani v qsortu, kde se taky se vsim pracuje jako s void*), nebo byvaji aspon nejake dalsi podrobnosti (ruzne volani ioctl a tak, kde se predava co presne posilame jako dalsi parametr)

Nahlásit jako SPAM
IP: 81.30.230.–
Program vždy dělá to co naprogramujete, ne to co chcete...
expoox0
Duch
13. 12. 2017   #4
-
0
-

Kedze s tym nerobim ziadne operacie tak som myslel ze najjednoduchsie bude ak s tym cely cas budem pracovat ako so stringom ale neviem to velmi zpojazdnit, viete mi poradit ako to spravne nacitat a vypisovat ? Pripadne neaky jednoduchsi sposo ako zistit datovy typ?

void *help;

scanf("%s",(char *)help); // toto hadze segfault

// ---------------

void *help;

scanf("%s",(char *)&help); 
printf("%s\n",(char*)help); // toto hadze segfault
Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
gna
~ Anonymní uživatel
1891 příspěvků
13. 12. 2017   #5
-
0
-

Jestli to máš takhle, tak je to jen definice proměnné, která není inicializovaná, takže je to 0, nebo "náhodná" hodnota/adresa. S tím nejde rozumně pracovat.

scanf načítá data ze standardního vstupu. První parametr určuje formát dat a další parametry určují, kam se mají data uložit. Když píšeš, že s ním neděláš žádné operace, tak proč se do něj pokoušíš ukládat?

Skutečný typ buď vždycky znáš, nebo ho nepotřebuješ znát. Ukaž přesně s čím pracuješ, takhle nejde poradit.

Nahlásit jako SPAM
IP: 213.211.51.–
expoox0
Duch
13. 12. 2017   #6
-
0
-

Mam implementovat FIFO frontu a funkcie pop a push, lenze cela fronta musi byt univerzalna co sa tyka datoveho typu a je predpisane aby tie funkcie pracovali s void*, vid rozsiahlejsi uryvok vrchneho prikladu:

typedef struct {
   int end;
   int size;
   void **list;
} queue_t;
...
queue_t* create_queue(int capacity){
	queue_t *sm = (queue_t*)malloc(sizeof(queue_t));

	sm->end = 0;
	sm->size = capacity;
	sm->list = malloc(sm->size*sizeof(void*));

	for (int i = 0; i < sm->size; i++)// to je uz len zufaly pokus spravit z toho 30znakovy string
		sm->list[i] = malloc(30);
	
	return sm;
}

bool push_to_queue(queue_t *queue, void *data){
	if (queue->end == queue->size)
		return false;
	queue->list[queue->end] = data;
	queue->end++;
	
	return true;
}
...

void *help;
queue_t *fronta;

...

if (c == 'a') {	
	scanf("%s",(char *)help);
	if (!push_to_queue(fronta,help))
		return 1;
}

...
Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
gna
~ Anonymní uživatel
1891 příspěvků
13. 12. 2017   #7
-
0
-

Aha, to je přesně ono. V implementaci té fronty nepotřebuješ vědět, co tam dáváš, ale zvenku při jejím použítí to víš a není problém ty ukazatele přetypovat.

char *help = malloc(30);
scanf("%29s", help);
if (!push_to_queue(fronta, (void*)help))
	chyba;
char *xx;
if (!pop_from_queue(fronta, (void**)&xx))
	chyba;
printf("%s\n", xx);

Podle toho, jaký používáš překladač by to mohlo fungovat i bez toho explicitního přetypování.

Nahlásit jako SPAM
IP: 213.211.51.–
KIIV
~ Moderátor
+43
God of flame
13. 12. 2017   #8
-
0
-

#7 gna
jeste nezapomenout na free(xx);

#6 expoox
no a pouziti te FIFO je zminovany kontext - obvykle se to pouziva jen s jednim typem. Pokud by jich melo byt vic, tak uz jedine pres strukturu, kde by byla zminka o spravnem typu a treba union.

Kazdopadne zlaty C++ :D Delat cokoliv "generickeho" v C je za trest. Samy neprimy volani (tady to jeste nebude, takovej qsort tim docela trpi), ztraty informaci o typech a dalsi saskarny

Nahlásit jako SPAM
IP: 81.30.230.–
Program vždy dělá to co naprogramujete, ne to co chcete...
expoox0
Duch
15. 12. 2017   #9
-
0
-

dobre, tak moja dufam ze posledna prosba, vyzera ze sa to sprava tak ako by malo az na jeden detail, pri volani mi funkcia pop vrati vzdy posldny prvok zoznamu, teda neviem ci je problem v nej alebo funkcia push prepise cely zoznam, pozeram na to uz druhy den a proste ja tam nevidim problem. Neaky napad ?

queue_t* create_queue(int capacity){
	queue_t * x = (queue_t *)malloc(sizeof(queue_t));
		
	x->list = malloc(capacity*sizeof(void*));
	x->size = capacity;
	x->count = 0;

	return x;
}

bool push_to_queue(queue_t *queue, void *data){
	if (queue->count == queue->size)
		return 0;
	
	queue->list[queue->count++] = data;
	return 1;
}

void* pop_from_queue(queue_t *queue){
	if (!queue->count)
		return NULL;

	void *x = queue->list[0];			// mozno malloc

	for (int i = 0; i < queue->count - 1; i++) {
		queue->list[i] = queue->list[i+1];
	}
	
	queue->list[queue->count-1] = NULL;
	queue->count--;

	return x;
}
.....

int main (void) {
	int size,help;
	char c;
	char in[30];
	void *x;

	scanf("%i",&size);
	queue_t *queue = create_queue(size);

	while (scanf("%c",&c) != -1) {
		if (c == 'a') {
			scanf("%29s",in);
			if (!push_to_queue(queue,(void*)in)) {
				delete_queue(queue);
				return 1;
			}
		} else if (c == 'r') {
			x = pop_from_queue(queue);
			if (x == NULL)
				printf("NULL\n");
			else
				printf("%s\n", (char*)x);

......
}
Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
15. 12. 2017   #10
-
0
-

Co zkusit krokovat v debuggeru?

hu

Nahlásit jako SPAM
IP: 195.178.67.–
expoox0
Duch
15. 12. 2017   #11
-
0
-

#10 hlucheucho
to nikam neviedlo, problem je asi v tom ze sa mi neak prepisuje to pole a v tom mi krokovanie nepomoze

Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
15. 12. 2017   #12
-
0
-

queue->list[queue->count++] = data;

do fronty kopíruješ jen ukazatel na data. To, si myslím, je nešikovné.

Krokování by pomohlo. Hlavně se podívat, kam data pokládáš, kolik je pak prvků v poli a pak se podívat, odkud data vybíráš a jak probíhá přesun prvků v poli po výběru.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
expoox0
Duch
15. 12. 2017   #13
-
0
-

#12 hlucheucho

queue->list[queue->count++] = data;

do fronty kopíruješ jen ukazatel na data. To, si myslím, je nešikovné.

chapem ze toto je presne ten problem co tam nastava len neviem ako ho opravit, ako mam do voidu* ukladat hodnotu, nie ukazatel ?

prave som zistil ze funkcie s referencnym mainom funguju spravbe takze uz fakt netusim co s tym

Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
gna
~ Anonymní uživatel
1891 příspěvků
15. 12. 2017   #14
-
0
-

Načítáš data do toho pole in. Do fronty vkládáš ukazatel na to pole. Takže všechny položky fronty jsou stejný ukazatel na to pole. A v něm je to, co jsi do něj naposledy načetl.

Můžeš vytvořit kopii, kterou budeš vkládat do té fronty -- strdup(in). A po vytažení ji uvolníš -- free(x).

Nahlásit jako SPAM
IP: 213.211.51.–
expoox0
Duch
15. 12. 2017   #15
-
0
-

#14 gna
vdaka za pomoc ale som uz tak vymlety z tejto primitvnej ulohy nad ktorou sedim vyse dva dni ze mam chut sa obesit (neviem uz ani ako, kde mam spravit kopiu, strdup mi nefunguje a ja ma nervy v haji) takze asi kaslite na mna, ale dik za snahu

Nahlásit jako SPAM
IP: 2001:718:2:72::4d...–
KIIV
~ Moderátor
+43
God of flame
15. 12. 2017   #16
-
0
-

#15 expoox
Da se rici, ze to i jakz takz funguje:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct
{
   int end;
   int size;
   int count;
   void **list;
} queue_t;


queue_t* create_queue(int capacity)
{
	queue_t * x = (queue_t *)malloc(sizeof(queue_t));
		
	x->list = malloc(capacity*sizeof(void*));
	x->size = capacity;
	x->count = 0;

	return x;
}

bool push_to_queue(queue_t *queue, void *data){
	if (queue->count == queue->size)
		return 0;
	
	queue->list[queue->count++] = data;
	return 1;
}

void* pop_from_queue(queue_t *queue){
	if (!queue->count)
		return NULL;

	void *x = queue->list[0];

	for (int i = 0; i < queue->count - 1; i++) {
		queue->list[i] = queue->list[i+1];
	}
	
	queue->list[queue->count-1] = NULL;
	queue->count--;

	return x;
}

void print(queue_t * q)
{
	printf("Q Element (pointers): ");
	for (int i = 0; i < q->count; ++i)
	{
		printf("0x%p ", q->list[i]);
	}
	printf("\n");
}

int main (void) {
	queue_t * queue = create_queue(10);

	do
	{
		print(queue);
	}
	while (push_to_queue(queue, strdup("testovaci retezec")));

	char* str;
	while ((str = (char*)pop_from_queue(queue)) != NULL)
	{
		printf("Retezec je: %s\n", str);
		free(str);
	}

    free(queue);
}

Vybirani prvku je sice dost neefektivni a bylo by to vyhodnejsi udelat jako kruhovy buffer, ale jinak pohoda.

Nahlásit jako SPAM
IP: 81.30.230.–
Program vždy dělá to co naprogramujete, ne to co chcete...
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, 22 hostů

Podobná vlákna

(void) — založil liborb

Void* na byte[] v C# — založil Radek Chalupa

Void * alebo delegate z c# — založil Miro1701

Public void PredstavSe() — založil Montezo

Typedef void* ve VB.NET — založil Štefan Kakaš

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ý