/* ==================================================
 * author: migf1
 * Mark (remove) duplicates from a table of strings
 * ==================================================
 */

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

#define MAXSTRINGS	100			/* μέγιστο πλήθος strings στον πίνακα */
#define STRSIZE		20+1			/* μέγιστο μέγεθος για κάθε string    */
#define DELETED_STRING	"*"

/* ----------------------------------------------------------------------------------
 * void strtable_dump( char stab[ MAXSTRINGS ][ STRSIZE ] );
 *
 *	Τύπωμα με τη σειρά όλων των strings του πίνακα stab, μέχρι να τελειώσει ο πίνακας
 *	ή μέχρι να βρεθεί κενό string ( κενά strings θεωρούνται όσα ο 1ος τους χαρακτήρας
 *	ισούται με '\0' )
 * ----------------------------------------------------------------------------------
 */
void strtable_dump( char stab[ MAXSTRINGS ][ STRSIZE ] )
{
	register int i;

	/* empty table */
	if ( *(stab[0]) == '\0' ) {
		puts("<empty>");
		return;
	}

	/* non-empty table */
	for (i=0; i < MAXSTRINGS && *(stab[i]) != '\0'; i++)
		puts( stab[i] );

	return;
}

/* ----------------------------------------------------------------------------------
 * void strtable_print( char stab[ MAXSTRINGS ][ STRSIZE ] );
 *
 *	Τύπωμα με τη σειρά όλων των strings του πίνακα stab που δεν έχουν μαρκαριστεί
 *	ως διαγραμμένα, μέχρι να τελειώσει ο πίνακας ή μέχρι να βρεθεί κενό string
 *	( κενά strings θεωρούνται όσα ο 1ος τους χαρακτήρας ισούται με '\0' )
 * ----------------------------------------------------------------------------------
 */
void strtable_print( char stab[ MAXSTRINGS ][ STRSIZE ] )
{
	register int i;

	/* empty table */
	if ( *(stab[0]) == '\0' || *(stab[0]) == DELETED_STRING[0] ) {
		puts("<empty>");
		return;
	}

	/* non-empty table */
	for (i=0; i < MAXSTRINGS && *(stab[i]) != '\0'; i++)
		if ( *(stab[i]) != DELETED_STRING[0] )
			puts( stab[i] );

	return;
}

/* ----------------------------------------------------------------------------------
 * int strtable_posfind( int pos, char stab[ MAXSTRINGS ][ STRSIZE ] );
 *
 * 	Αν το string που βρίσκεται στη θέση pos του πίνακα stab υπάρχει σε οποιαδήποτε
 *	από τις προηγούμενες θέσεις του πίνακα, η συνάρτηση ΕΠΙΣΤΡΕΦΕΙ τη θέση στην οποία
 *	βρέθηκε. Αν δεν βρεθεί ή αν η θέση pos περαστεί με αρνητική τιμή ή με τιμή
 * 	μεγαλύτερη της MAXSTRINGS-1 ή αν ο πίνακας είναι άδειος, τότε η συνάρτηση
 * 	ΕΠΙΣΤΡΕΦΕΙ την τιμή -1.
 *
 * 	ΣΗΜΕΙΩΣΗ:
 * 	Η αναζήτηση ξεκινάει από την αρχή του πίνακα και σταματάει είτε όταν βρεθεί η
 * 	1η εμφάνιση του string, είτε όταν φτάσουμε στην θέση pos, είτε όταν βρεθεί κενό
 *	string ( κενά strings είναι όσα ο 1ος τους χαρακτήρας ισούται με '\0' ).
 * ----------------------------------------------------------------------------------
 */
int strtable_posfind( int pos, char stab[ MAXSTRINGS ][ STRSIZE ] )
{
	register int i=0;

	/* sanity checks */
	if ( pos < 0 || pos > MAXSTRINGS-1 )
		return -1;

	for ( i=0; i < pos && *(stab[i]) != '\0'; i++ )
		if ( !strcmp( stab[ pos ], stab[i] ) )
			break;

	if ( i == pos || *(stab[i]) == '\0' )
		return -1;

	return i;
}

/* ----------------------------------------------------------------------------------
 * void strtable_markdups( char stab[ MAXSTRINGS ][ STRSIZE ] );
 *
 * 	Απαλοιφή τυχόν πολλαπλών εμφανίσεων ενός string μέσα σε πίνακα από strings.
 *	Στο τέλος το κάθε string εμφανίζεται ακριβώς μια φορά μέσα στον πίνακα, με
 *	τους "κλώνους" να έχουν πάρει την τιμή της σταθεράς: DELETED_STRING
 * ----------------------------------------------------------------------------------
 */
void strtable_markdups( char stab[ MAXSTRINGS ][ STRSIZE ] )
{
	register int i = 0;

	/* empty table */
	if ( (*stab[0]) == '\0' )
		return;

	/* non-empty table */
	for (i=0; i < MAXSTRINGS && *(stab[i]) != '\0'; i++)
	{
		if ( strtable_posfind( i, stab ) != -1 )	/* stab[i] already exists */
			strncpy( stab[ i ], DELETED_STRING, STRSIZE-1 );
	}

	return;
}

/* ------------------------------------------------------- */
int main( void )
{
	char strtable[ MAXSTRINGS][ STRSIZE ] = {
		"red", "blue", "green", "red", "yellow", "blue", "blue", "red", "green"
	};

	puts("Before:\n---------------------");
	strtable_dump( strtable );

	strtable_markdups( strtable );

	puts("\nAfter (raw):\n---------------------");
	strtable_dump( strtable );

	puts("\nAfter (interfaced):\n---------------------");
	strtable_print( strtable );

        return 0;
}
