Dopasowanie zmiennej

0

Witam, mój problem polega na tym, że z otworzonego pliku "kalosze.txt" muszę za pomocą unii dopasować odpowiednią zmienną, tak że np dla 0 jest to tekst, dla 1 int, a 2 zmiennoprzecinkowa. W pliku txt mam:

0 kolor zolty

gdzie:
0 oznacza że będzie to zmienna tekstowa zolty, po czym program odczyta następną linijkę gdzie pierwsza cyfra oznacza format tekstu i przyporządkuje jej odpowiednia zmienną. Napisałem taki fragment kodu i dalej nie wiem jak to połączyć.

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

typedef struct {
     int dataType;
     char dataName[25];

        union
        {
            int intValue;
            float floatValue;
            char textValue;
            char charValue;
    }dataValue;
 } data;


int main()
{
    int i;
    int cnt;
    data tab[3];
    FILE *plik;
    char nazwa[10],ch;
    printf("Podaj nazwe pliku, ktory chcesz otworzyc: ");
    gets(nazwa);
    plik=fopen(nazwa,"r");
    if ((plik=fopen(nazwa, "r"))==NULL){
     perror("Zla nazwa pliku! ");
     exit(1);
    }


switch(tab[0].dataType)
    {
    case 0:
        scanf("%s", tab[0].dataValue.textValue);
        break;
    case 1:
        scanf("%d", &tab[0].dataValue.intValue);
        break;
    case 2:
        scanf("%f", &tab[0].dataValue.floatValue);
        break;
    case 3:
        scanf("%s", tab[0].dataValue.charValue);
        break;
    }



fclose(plik);
    return 0;} 
1

Proszę (nie testowane):

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


typedef enum {
  STRING  = 0,
  INTEGER = 1,
  FLOAT   = 2
} entry_type;

typedef struct {
  char *name;
  entry_type type;
  union {
    char *as_string;
    int as_integer;
    float as_float;
  } value;
} entry;

entry *entry_new(const char *name, entry_type type)
{
  entry *self = malloc(sizeof(entry));
  if (!self) {
    // błąd
    return NULL;
  }

  self->name = malloc(strlen(name) + 1);
  strcpy(self->name, name);

  self->type = type;
  if (self->type == STRING) {
    self->value.as_string = NULL;
  }

  return self;
}

entry *entry_sets(entry *self, const char *value)
{
  assert(self != NULL);

  self->value.as_string = malloc(strlen(value) + 1);
  strcpy(self->value.as_string, value);
  return self;
}

entry *entry_seti(entry *self, int value)
{
  assert(self != NULL);

  self->value.as_integer = value;
  return self;
}

entry *entry_setf(entry *self, int value)
{
  assert(self != NULL);

  self->value.as_float = value;
  return self;
}

void entry_free(entry *self)
{
  assert(self != NULL);

  free(self->name);
  if (self->type == STRING && self->value.as_string != NULL) {
    free(self->value.as_string);
  }

  free(self);
}


int main(int argc, char **argv)
{
  FILE *f = fopen("test.txt", "r");
  if (!f) {
    // błąd
    return 1;
  }

  entry_type type;
  char name[40];
  union {
    char as_string[80];
    int as_integer;
    float as_float;
  } tmp;

  char *line  = NULL;
  size_t dump = 0;
  ssize_t n   = 0;
  while ((n = getline(&line, &dump, f)) != -1) {
    fscanf(f, "%d", &type);
    fscanf(f, "%s", name);

    entry *node = entry_new(name, type);

    switch (node->type) {
      case STRING: 
        fscanf(f, "%s", tmp.as_string);
        entry_sets(node, tmp.as_string);
        break;

      case INTEGER:
        fscanf(f, "%d", &tmp.as_integer);
        entry_seti(node, tmp.as_integer);
        break;

      case FLOAT:
        fscanf(f, "%f", &tmp.as_float);
        entry_setf(node, tmp.as_float);
        break;

      default:
        // błąd
        break;
    }

    // test
    printf("%s (%d)\n", node->name, node->type);
    switch (node->type) {
      case STRING: 
        printf("-> %s\n", node->value.as_string);
        break;

      case INTEGER:
        printf("-> %d\n", node->value.as_integer);
        break;

      case FLOAT:
        printf("-> %f\n\n", node->value.as_float);
        break;
    }

    // tutaj możesz zapisywać swoje do tablicy utworzonej dynamicznie
    // lub coś w ten deseń
    entry_free(node);
  }

  fclose(f);
  return 0;
}
0

Dziękuję, na pewno się przyda. :)

W kodzie kompilator wyrzuca błąd undefined reference to `getline'.
Będę opierał się na Twoim kodzie by dokończyć mój, więc myślę że poradzę sobie z tym problem. :)
Dziękuje i pozdrawiam.

0

Radzę poczekać jeszcze na opinie innych bardziej doświadczonych użytkowników, może znajdą oni jakieś bardziej optymalne rozwiązanie :).

0

opierając się lekko na rozwiązaniu @kamilwxx jeszcze tak używając void*

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

typedef enum { INTEGER, STRING } data_type;

typedef struct {
	data_type type;
	char *tostring;
	union {
		int as_integer;
		char *as_string;
	} data;
} mtype;

mtype mtype_get(const void *data, data_type t) {
	static mtype ret;
	ret.type = t;
	int *idata;
	char *sdata;
	switch(t) {
	case INTEGER:
		idata = (int*)data;
		ret.data.as_integer = (*idata);
		ret.tostring = malloc(16 * sizeof(char));
		sprintf(ret.tostring,"%d",*idata);
		break;
	case STRING:
		sdata = (char*)data;
		ret.data.as_string = strdup(sdata);
		ret.tostring = ret.data.as_string;
		break;
	}
	return ret;
}

void mtype_free(mtype *m) {
	free(m->tostring);
	m->tostring = NULL;
}

int main(void) {
	mtype arr[2];
	size_t i, arr_size = sizeof(arr)/sizeof(arr[0]);
	int num = 5;
	arr[0] = mtype_get(&num,INTEGER);
	arr[1] = mtype_get(&"jakis tam tekst",STRING);
	for(i=0;i<arr_size;++i) {
		printf("%s\n",arr[i].tostring);
		mtype_free(&arr[i]);
	}
	return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1