Cod sursa(job #1346325)

Utilizator alexandru.eliseiAlexandru Elisei alexandru.elisei Data 18 februarie 2015 10:22:08
Problema Convertor Scor 50
Compilator c Status done
Runda rosedu_cdl_2015 Marime 4.03 kb
/*
 * Fisierul in format JSON este un vector cu elemente hash-uri.
 * Fiecare hash este format din perechi cheie:valoare.
 *
 * Parsez fiecare linie caracter cu caracter si stochez caracterele pe care le
 * intalnesc fie in stringul cu chei, fie in cel cu valori in functie de
 * caracterele delimitatoare intalnite pana atunci.
 *
 * La sfaristul fiecarui hash scriu cele doua stringuri in fisier.
 */

#include <stdio.h>
#include <ctype.h>

#define LG_MAX		1025		/* lungime maxima linie; 1024 + '\0' */
#define MAX_LINII	20128		/* numarul maxim de linii in fisier */
#define SEP_CV		':'		/* separa cheia de valoare */
#define SEP_EL		','		/* separa elementele hash-ului */
#define START_DATE	'['		/* inceputul datelor de citit */
#define STOP_DATE	']'		/* sfarsitul datelor de citit */
#define START_HASH	'{'		/* semnaleaza inceputul unui hash */
#define STOP_HASH	'}'		/* semnaleaza sfarsitul unui hash */

/* Masturbare intelectuala */
#undef END_OF_LINE
#define END_OF_LINE(a)	(((a) == EOF || (a) == '\n' || (a) == '\0') ? 1 : 0)
#undef EROARE
#define EROARE(s)	(fprintf(stderr, "\nEROARE - %s\n\n", (s)))

/* Sterge blankurile dintre valori si ghilimele */
char *jstrip(char *s);

struct flag {
	unsigned short citit_antet;
	unsigned short in_hash;
	unsigned short in_date;
	unsigned short in_cheie;
	unsigned short in_valoare;

};

int main(void)
{
	FILE *in, *out;
	char buflin[LG_MAX];		/* buffer citire linia curenta */
	char antet[LG_MAX] = "";	/* antetul cu cheile */
	char valori[LG_MAX] = "";	/* valorile de scris */
	unsigned short nr_linii;	/* numarul de linii citite */
	struct flag flags = {0};
	int i_antet, i_valori;		/* index antet si valori */
	int i;

	if ((in = fopen("convertor.in", "r")) == NULL) {
		EROARE("Fisierul convertor.in nu a putut fi deschis");
		return 1;
	}

	if ((out = fopen("convertor.out", "w")) == NULL) {
		EROARE("Fisierul convertor.out nu a putut fi scris");
		return 2;
	}

	nr_linii = 0;

	while (fgets(buflin, LG_MAX, in) != NULL) {
		if (++nr_linii > MAX_LINII) {
			EROARE("S-a depasit numarul maxim de linii");
			return 3;
		}
		for (i = 0; !(END_OF_LINE(buflin[i])); i++) {
			if (flags.in_date) {
				if (buflin[i] == STOP_DATE) {
					return 0;
					flags.in_date = 0;
				/* Citesc un hash */
				} else if (flags.in_hash) {
					/* Am intalnit terminatorul de hash */
					if (buflin[i] == STOP_HASH) {
						/* Scriu datele in fisier */
						if (flags.citit_antet == 0) {
							antet[i_antet] = '\0';
							jstrip(antet);
							fprintf(out, "%s\n", antet);
							flags.citit_antet = 1;
						}

						valori[i_valori++] = ',';
						valori[i_valori] = '\0';
						jstrip(valori);
						fprintf(out, "%s\n", valori);

						valori[0] = '\0';
						i_valori = 0;
						flags.in_hash = 0;
						flags.in_valoare = 0;
					/* Citesc o valoare */
					} else if (flags.in_valoare) {
						if (buflin[i] != SEP_EL)
							valori[i_valori++] = buflin[i];
						else {
							valori[i_valori++] = ',';
							flags.in_valoare = 0;
						}
					/* Incep sa citesc valoare */
					} else if (buflin[i] == SEP_CV) {
						if (flags.citit_antet == 0)
							antet[i_antet++] = ',';
						flags.in_valoare = 1;
					/* Citesc o cheie */
					} else if (flags.citit_antet == 0) {
						antet[i_antet++] = buflin[i]; 
					}

				/* Iterez pana gasesc un nou hash */
				} else if (buflin[i] == START_HASH) {
					i_antet = 0;	
					i_valori = 0;	
					flags.in_hash = 1;
				}
			/* Iterez pana gasesc inceputul unui hash */
			} else if (buflin[i] == START_DATE) {
				flags.in_date = 1;
			}
		}
	}

	EROARE("Date JSON incomplete sau inexistente");
	return 4;
}

/* Sterge blankurile dintre valori si ghilimele */
char *jstrip(char *s)
{
	int i, j;

	if (s == NULL)
		return NULL;

	j = 0;
	i = 0;
	while (s[i] != '\0') {
		/* Sterg blankurile de inceput */
		for (; isblank(s[i]); i++)
			;

		if (s[i] == '"') {
			++i;
			while (s[i] != '"')
				s[j++] = s[i++];
			/* Sterg blankurile dupa ghilimele */
			for (; s[i] != ','; i++)
				;
		} else {
			while (s[i] != ',')
				s[j++] = s[i++];
		}

		/* Copiez si virgula */
		s[j++] = s[i++];
	}

	s[j] = '\0';

	return s;
}