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 ?
Fórum › C / C++
Void*
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)
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
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.
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;
}
...
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í.
#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
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);
......
}
Co zkusit krokovat v debuggeru?
hu
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
#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
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).
#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
#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.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
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