Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

  • Απαντ. 36
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Δημοσ.

Παρακαλώ, αλλά τον κώδικα δεν στον έδωσα για να τον παρουσιάσεις για δικό σου. Στον έδωσα για να τον συγκρίνεις με τον δικό σου, και να διορθώσεις τον δικό σου.

 

Ο κώδικάς σου έχει σίγουρα λάθη διαχείρισης του λεγόμενου bad input, όπως διαπίστωσες "the hard-way" μετά την τελευταία παρατήρηση του bird. Η χρήση της gets() είναι εξορισμού πρόβλημά σε οποιονδήποτε κώδικα, για αυτό και καταργήθηκε από την γλώσσα στην αναθεώρηση C11, ενώ ήταν ήδη χαρακτηρισμένη ως "depreciated" (δηλαδή "προς κατάργηση") από την αναθεώρηση C99 (εδώ και 2 δεκαετίες δηλαδή).

 

Η χρήση της fgets() (ακολουθούμενη ή όχι από την sscanf(), ανάλογα το αναμενόμενο input) είναι η συνηθέστερη αντικατάσταση της gets(). Στον κώδικα που σου έδωσα, σου έχω γράψει την s_getsflushed() ως ασφαλή αντικατάσταση της gets(), και προφανώς μπορείς να την χρησιμοποιείς σε οποιοδήποτε πρόγραμμά σου (αν κι εφόσον εμπίπτει στην ύλη σας, αλλιώς fgets() με ή χωρίς sscanf()... ποτέ gets() ).

 

Ένα άλλο πρόβλημα στον κώδικά σου είναι πως ζητάς από τον χρήστη να ορίσει το μέγιστο μήκος του input που θα σου δώσει, το οποίο θεωρείται και είναι κακή πρακτική (bad practice). Σε συνδυασμό μάλιστα με την χρήση της gets() σου είναι αδύνατον να αντιδράσεις προγραμματιστικά στην περίπτωση που σου δώσει για input περισσότερους χαρακτήρες από ότι σου όρισε. Στην καλύτερη περίπτωση θα παραχθεί segmentation fault, και στην χειρότερη το πρόγραμμά σου θα χακαριστεί σε χρόνο ντε-τε, από όποιον το θελήσει.

 

Η καλή πρακτική είναι να ορίζεις εσύ μέσα στο πρόγραμμά σου το μέγιστο πλήθος χαρακτήρων που αναμένεις ως input, κι αν σου δώσει ο χρήστης παραπάνω να μην σκάει το πρόγραμμά σου (ιδανικά πρέπει να ειδοποιεί τον χρήστη ή μπορεί απλώς να κρατάει μόνο τους μέγιστους αναμενόμενους χαρακτήρες σιωπηλά και να συνεχίζει). Αυτό ακριβώς κάνει ο κώδικας που σου έδωσα, ορίζοντας ως μέγιστο αναμενόμενο πλήθος χαρακτήρων στην είσοδο τους (255+1) και χρησιμοποιώντας κατόπιν την s_getsflushed() για την ανάγνωση.

 

Αν ο κώδικας της s_getsflushed() είναι εκτός ύλης, τότε πρέπει να χρησιμοποιήσεις την fgets(). Είτε η μια είτε η άλλη παίρνουν ως όρισμα το αναμενόμενο μέγιστο πλήθος χαρακτήρων εισόδου, οπότε σε προστατεύουν από σκασίματα του προγράμματός σου. Επίσης, σε απελευθερώνουν από το να χρησιμοποιείς VLA για τον ορισμό του input, το οποίο πλέον δεν χρειάζεται να οριστεί δυναμικά.

 

Τέλος, σε ότι αφορά την ύλη που έχετε καλύψει, μια τέτοια άσκηση προϋποθέτει πως κατ' ελάχιστον έχετε καλύψει πίνακες χαρακτήρων, c-strings και ρουτίνες διαχείρισης των c-strings (είτε πρόκειται για το input/output τους, είτε για την διαχείρισή τους). Κανονικά θα έπρεπε να έχετε καλύψει και δείκτες, τουλάχιστον δείκτες χαρακτήρων και τη χρησιμότητά τους στη διαχείριση των c-strings, αλλά ξέρω πως δεν είναι καθόλου απίθανο να μην σας τους έχουν διδάξει ακόμα.

 

Με αυτά τα δεδομένα στο μυαλό μου,συν ότι έχετε μάθει και συναρτήσεις, σου έδωσα τον παραπάνω κώδικα ;)

 

 

εχουμε διδαχθει ολη την υλη,εμενα μου μενει να μαθω το κομματι των δομων και αρχειων απλα προσπαθησα να κατανοησω πριν τον αλγοριθμο και δεν μπορεσα πληρως..τωρα με αυτες τις δευκρινησεις ειμαι πλεον σε θεση να καταλαβω τι κανει..απο δω και περα θα αντικαθιστω την gets() ..Eυχαριστω για τις συμβουλες! Εχω μια ερωτηση,στον κωδικα μου διαβαζω 2 φορες:

 

 

 

 

scanf("%d",&meg);
while ( (c=getchar()) != '\n' && c!=EOF);

 

λογω προβληματος με το buffer επειδη εχει κρατησει \n, ή κατι τετοιο..πως μπορω να το αποφυγω αυτο γενικοτερα?

Δημοσ.

 

εχουμε διδαχθει ολη την υλη,εμενα μου μενει να μαθω το κομματι των δομων και αρχειων απλα προσπαθησα να κατανοησω πριν τον αλγοριθμο και δεν μπορεσα πληρως..τωρα με αυτες τις δευκρινησεις ειμαι πλεον σε θεση να καταλαβω τι κανει..απο δω και περα θα αντικαθιστω την gets() ..Eυχαριστω για τις συμβουλες! Εχω μια ερωτηση,στον κωδικα μου διαβαζω 2 φορες:

 

 

scanf("%d",&meg);
while ( (c=getchar()) != '\n' && c!=EOF);

 

λογω προβληματος με το buffer επειδη εχει κρατησει \n, ή κατι τετοιο..πως μπορω να το αποφυγω αυτο γενικοτερα?

 

Με το να χρησιμοποιείς μι ασυνάρτηση όπως την

char *s_getsflushed( char *s, size_t ssize )

που σου έδειξε ο migf1 :P

Δημοσ.

Με την s_getsflushed(). Ή με λίγο παραπάνω κόπο με την fgets(). Ρίξε μια ματιά κι εδώ: http://x-karagiannis.gr/prog/libs/content/misc/other/prompt_for/doc/html/index.html#LnBuf. Αν θες να κατεβάσεις την βιβλιοθήκη για να δεις τον κώδικα, μπορείς από εδώ: http://x-karagiannis.gr/prg/c-prog/c-misc/prompt-for-library/ (γιατί στην τεκμηρίωση έχω ξεχάσει το παλιό site).

Δημοσ.

 

εχουμε διδαχθει ολη την υλη,εμενα μου μενει να μαθω το κομματι των δομων και αρχειων

...

Εφόσον έχετε κάνει όλη την ύλη, ο κώδικας που σου έδωσα αρχικά θα έπρεπε λογικά να ήταν κατανοητός, μιας και δεν περιείχε ούτε δομές ούτε αρχεία.

 

Επειδή βρήκα λίγο χρόνο (περισσότερο για διάλειμμα, από το... πήξιμο) σου έγραψα κι άλλον κώδικα. Αυτή τη φορά τον έχω σπάσει σε συναρτήσεις, αλλά ως λογική ακολουθεί εκείνη του δικού σου κώδικα στην επεξεργασία των δεδομένων που διαβάζει.

 

Περισσότερο τον έγραψα ως σκελετό προγραμμάτων που λειτουργούν με μενού, που συνήθως λειτουργούν στο higher level με κλήσεις συναρτήσεων που αντιστοιχούν στις επιλογές των μενού, μέσα από switch. Επίσης δείχνει πως μπορείς να διαβάζεις strings και integers χωρίς να έχεις πρόβλημα με το line-buffer, με τις συναρτήσεις s_gets_flushed() και get_int(), αντίστοιχα.

 

Αυτή εδώ η s_get_flushed() διαφέρει από την προηγούμενη s_getsflushed() στο ότι σου επιστρέφει το πλήθος των χαρακτήρων που διάβασε επιτυχώς (εξαιρώντας το '\0'). Πάντως και η μια και η άλλη, κόβουν το '\n' από το τέλος των strings που διαβάζουν (αντίθετα δηλαδή από την fgets() η οποία το κρατάει, εκτός αν γίνει overflowed).

 

 

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXSIZ_INPUT	(255+1)		/* for storing user input */
#define SIZ_MORSECODE	(5+1)		/* size of any morse code in bytes (+1 for NUL) */
#define N_MORSECODES	10		/* # of supported morse codes */

enum {	/* Availabe menu selections */
	MS_INVALID	= -1,
	MS_EXIT		= 0,
	MS_DIG2MORSE,
	MS_MORSE2DIG
};

/* ----------------------------------------------------
 * Flush the stdin buffer.
 */
void flush_stdin( void )
{
	int c;
	while ( '\n' != (c=getchar()) && EOF != c )
		/* void */ ;
}

/* ----------------------------------------------------
 * Read a c-string from stdin, reject '\n' & flush any extra characters if needed.
 * Return the number of characters successfully read,
 * or 0 if the user pressed just an ENTER.
 */
size_t s_gets_flushed( char *s, size_t ssize )
{
	register int c;
	register size_t i;

	/* sanity checks */
	if ( !s || ssize < 1 ) {
		return 0;
	}

	/* read chars from stdin */
	for (i=0; i < ssize-1 && '\n' != (c=getchar()) && EOF != c; i++)
		s[i] = c;

	if ( s[i] && s[i] != '\n' )		/* ssize reached without '\n' ? */
		flush_stdin();			/* flush any remaining chars */

	s[i] = '\0';				/* NUL-terminate s */

	return i;
}

/* ----------------------------------------------------
 * Read an int from stdin & return it (return INT_MIN on error).
 */
int get_int( void )
{
	char input[MAXSIZ_INPUT] = {'\0'}, *tail = NULL;
	long int ret = 0;
	errno = 0;

	if ( 0 == s_gets_flushed(input, MAXSIZ_INPUT) )
		return INT_MIN;

	ret = strtol(input, &tail, 10);
	if ( 0 != errno
	|| ret > INT_MAX || ret < INT_MIN+1
	|| (0 == ret && *tail != '\0')
	)
		return INT_MIN;

	return (int)ret;
}

/* ----------------------------------------------------
 * Display the menu, get & return the user selection.
 */
int menu_selection( void )
{
	int ret = 0;

	for (;
	{
		puts( "\n" );
		puts( "MENOY EPILOWN" );
		puts( "-------------" );
		puts( "1: artithmos se kwdika Morse" );
		puts( "2: kwdikas Morse se arithmo" );
		puts( "0: eksodos" );
		printf( "> " );
		fflush(stdout);

		ret = get_int();
		if ( ret < 0 ) {
			puts( "invalid selection, try again" );
			continue;
		}
		break;
	}

	return ret;
}


/* ----------------------------------------------------
 * Read digits as chars from stdin, then convert & print them in-place as morse code.
 * Return 0 on error, 1 otherwise.
 */
int ms_dig2morse( char mo[N_MORSECODES][SIZ_MORSECODE] )
{
	int c = '\0';

	/* sanity check */
	if ( !mo ) {
		fputs( "*** internal error: invalid pointer\n", stderr );
		return 0;		/* false */
	}

	printf( "\nDwste arithmo gia metatroph se kwdika Morse: " );
	while ( '\n' != (c=getchar()) && EOF != c )
	{
		if ( !isdigit(c) ) {
			flush_stdin();
			puts( "<invalid>" );
			return 0;	/* false */
		}

		printf( "%s", mo[ c-'0'] );
		fflush(stdout);
	}
	putchar( '\n' );

	return 1;			/* true */
}

/* ----------------------------------------------------
 * Read morse code from stdin, then convert & print it as digits.
 * Return 0 on error, 1 otherwise.
 */
int ms_morse2digs( char mo[N_MORSECODES][SIZ_MORSECODE] )
{
	char input[MAXSIZ_INPUT] = {'\0'};
	int j = 0;
	size_t i = 0, nchars = 0;

	/* sanity check */
	if ( !mo ) {
		fputs( "*** internal error: invalid pointer\n", stderr );
		return 0;		/* false */
	}

	printf( "\nDwste kwdika Morse gia metatroph se arithmo: " );
	nchars = s_gets_flushed(input, MAXSIZ_INPUT);
	if ( nchars < SIZ_MORSECODE-1 ) {
		puts( "invalid input" );
		return 0;		/* false */
	}

	/* scan input by groups of SIZ_MORSECODE-1 consequtive chars */
	for (i=0; i < nchars; i += SIZ_MORSECODE-1)
	{
		/* look for current group in mo[][] */
		for (j=0; j < N_MORSECODES; j++) {
			if ( 0 == memcmp(mo[j], &input[i], SIZ_MORSECODE-1) )
				break;
		}

		/* group not found? */
		if ( N_MORSECODES == j ) {
			puts( "<invalid>" );
			return 0;
		}

		/* group found */
		printf( "%d", j );
		fflush( stdout );
	}
	if ( i < N_MORSECODES )
		putchar( '\n' );

	return 1;
}

/* -------------------------------------- */
int main( void )
{
	int  ms = 0;				/* menu selection */
	char mo[N_MORSECODES][SIZ_MORSECODE]={	/* supported morse codes*/
		"-----",
		".----",
		"..---",
		"...--",
		"....-",
		".....",
		"-....",
		"--...",
		"---..",
		"----."
	};

	for (;
	{
		ms = menu_selection();
		if ( MS_EXIT == ms )
			break;

		switch ( ms )
		{
			case MS_DIG2MORSE:
				ms_dig2morse(mo);
				break;

			case MS_MORSE2DIG:
				ms_morse2digs(mo);
				break;

			default:
				/* impossible */
				break;
		}
	}

	exit( EXIT_SUCCESS );
}

 

Σε γενικές γραμμές, ο παραπάνω κώδικας είναι πιο κοντά σε production standards, παρόλο που τον έγραψα στο πόδι. Το ίδιο πράγμα σε... student standards μπορεί να είναι κάπως έτσι...

 

 

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXSIZ_INPUT	(255+1)		/* for storing user input */

/* ----------------------------------------------------
 * Read a c-string from stdin, reject '\n' & flushing any extra characters if needed.
 * Return the number of characters successfully read,
 * or 0 if the user pressed just an ENTER.
 */
size_t s_gets_flushed( char *s, size_t ssize )
{
	register int c;
	register size_t i;

	/* sanity checks */
	if ( !s || ssize < 1 ) {
		return 0;
	}

	/* read chars from stdin */
	for (i=0; i < ssize-1 && '\n' != (c=getchar()) && EOF != c; i++)
		s[i] = c;

	if ( s[i] && s[i] != '\n' ) {		/* ssize reached without '\n' ? */
		while ( '\n' != getchar() )	/* flush any remaining chars */
			/* void */ ;
	}
	s[i] = '\0';				/* NUL-terminate s */

	return i;
}

/* ----------------------------------------------------
 * Read an int from stdin & return it (return INT_MIN on error).
 */
int get_int( void )
{
	char input[MAXSIZ_INPUT] = {'\0'}, *tail = NULL;
	long int ret = 0;
	errno = 0;

	if ( 0 == s_gets_flushed(input, MAXSIZ_INPUT) )
		return INT_MIN;

	ret = strtol(input, &tail, 10);
	if ( 0 != errno
	|| ret > INT_MAX || ret < INT_MIN+1
	|| (0 == ret && *tail != '\0')
	)
		return INT_MIN;

	return (int)ret;
}

/* ----------------------------------------------------
 * Display the menu, get & return the user selection.
 */
int menu( void )
{
	int ret = 0;

	for (;
	{
		puts( "\n" );
		puts( "MENOY EPILOWN" );
		puts( "-------------" );
		puts( "1: artithmos se kwdika Morse" );
		puts( "2: kwdikas Morse se arithmo" );
		puts( "0: eksodos" );
		printf( "> " );
		fflush(stdout);

		ret = get_int();
		if ( ret < 0 ) {
			puts( "invalid selection, try again" );
			continue;
		}
		break;
	}

	return ret;
}


/* -------------------------------------- */
int main( void )
{
	char input[MAXSIZ_INPUT] = {'\0'};
	size_t i = 0;
	int j = 0, ar = 0;
	char mo[10][6]= {
		"-----",
		".----",
		"..---",
		"...--",
		"....-",
		".....",
		"-....",
		"--...",
		"---..",
		"----."
	};

	for (;
	{
		int c = '\0';
		int wasInvalid = 0;	/* false */

		ar = menu();
		if ( 0 == ar )
			break;

		if ( 1 == ar )
		{
			printf( "\nDwste arithmo gia metatroph se kwdika Morse: " );
			while ( '\n' != (c=getchar()) && EOF != c )
			{
				if ( !isdigit(c) ) {
					int ch;
					/* flush stdin */
					while ( '\n' != (ch=getchar()) && EOF != ch )
						/* void */ ;
					puts( "invalid input" );
					wasInvalid = 1;	/* true */
					break;
				}
				printf( "%s ", mo[ c-'0'] );
				fflush(stdout);
			}
			if ( !wasInvalid )
				putchar( '\n' );
		}

		else if ( 2 == ar )
		{
			size_t nchars = 0;

			printf( "\nDwste kwdika Morse gia metatroph se arithmo: " );
			nchars = s_gets_flushed(input, MAXSIZ_INPUT);
			if ( nchars < 5 ) {
				puts( "invalid input" );
				continue;
			}

			/* scan input by groups of 5 consequtive chars */
			for (i=0; i < nchars; i += 5)
			{
				/* look for current group in mo[][] */
				for (j=0; j < 10; j++) {
					if ( 0 == memcmp(mo[j], &input[i], 5) )
						break;
				}

				/* group not found? */
				if ( 10 == j ) {
					puts( "<invalid>" );
					break;
				}

				/* group found */
				printf( "%d", j );
				fflush( stdout );
			}
			if ( i < 10 )
				putchar( '\n' );
		}

		/*
		else
			impossible
		*/
	}

	return 0;
}

 

Μικρότερος μεν, και ενδεχομένως πιο κατανοητός επειδή είναι μικρό το πρόγραμμα, αλλά λόγω έλλειψης abstractions και οργάνωσης είναι πιο δύσκολο να επεκταθεί, καθώς και να συντηρηθεί αν επεκταθεί.

Δημοσ.

 

Εφόσον έχετε κάνει όλη την ύλη, ο κώδικας που σου έδωσα αρχικά θα έπρεπε λογικά να ήταν κατανοητός, μιας και δεν περιείχε ούτε δομές ούτε αρχεία.

 

Επειδή βρήκα λίγο χρόνο (περισσότερο για διάλειμμα, από το... πήξιμο) σου έγραψα κι άλλον κώδικα. Αυτή τη φορά τον έχω σπάσει σε συναρτήσεις, αλλά ως λογική ακολουθεί εκείνη του δικού σου κώδικα στην επεξεργασία των δεδομένων που διαβάζει.

 

Περισσότερο τον έγραψα ως σκελετό προγραμμάτων που λειτουργούν με μενού, που συνήθως λειτουργούν στο higher level με κλήσεις συναρτήσεων που αντιστοιχούν στις επιλογές των μενού, μέσα από switch. Επίσης δείχνει πως μπορείς να διαβάζεις strings και integers χωρίς να έχεις πρόβλημα με το line-buffer, με τις συναρτήσεις s_gets_flushed() και get_int(), αντίστοιχα.

 

Αυτή εδώ η s_get_flushed() διαφέρει από την προηγούμενη s_getsflushed() στο ότι σου επιστρέφει το πλήθος των χαρακτήρων που διάβασε επιτυχώς (εξαιρώντας το '\0'). Πάντως και η μια και η άλλη, κόβουν το '\n' από το τέλος των strings που διαβάζουν (αντίθετα δηλαδή από την fgets() η οποία το κρατάει, εκτός αν γίνει overflowed).

 

 

 

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXSIZ_INPUT	(255+1)		/* for storing user input */
#define SIZ_MORSECODE	(5+1)		/* size of any morse code in bytes (+1 for NUL) */
#define N_MORSECODES	10		/* # of supported morse codes */

enum {	/* Availabe menu selections */
	MS_INVALID	= -1,
	MS_EXIT		= 0,
	MS_DIG2MORSE,
	MS_MORSE2DIG
};

/* ----------------------------------------------------
 * Flush the stdin buffer.
 */
void flush_stdin( void )
{
	int c;
	while ( '\n' != (c=getchar()) && EOF != c )
		/* void */ ;
}

/* ----------------------------------------------------
 * Read a c-string from stdin, reject '\n' & flush any extra characters if needed.
 * Return the number of characters successfully read,
 * or 0 if the user pressed just an ENTER.
 */
size_t s_gets_flushed( char *s, size_t ssize )
{
	register int c;
	register size_t i;

	/* sanity checks */
	if ( !s || ssize < 1 ) {
		return 0;
	}

	/* read chars from stdin */
	for (i=0; i < ssize-1 && '\n' != (c=getchar()) && EOF != c; i++)
		s[i] = c;

	if ( s[i] && s[i] != '\n' )		/* ssize reached without '\n' ? */
		flush_stdin();			/* flush any remaining chars */

	s[i] = '\0';				/* NUL-terminate s */

	return i;
}

/* ----------------------------------------------------
 * Read an int from stdin & return it (return INT_MIN on error).
 */
int get_int( void )
{
	char input[MAXSIZ_INPUT] = {'\0'}, *tail = NULL;
	long int ret = 0;
	errno = 0;

	if ( 0 == s_gets_flushed(input, MAXSIZ_INPUT) )
		return INT_MIN;

	ret = strtol(input, &tail, 10);
	if ( 0 != errno
	|| ret > INT_MAX || ret < INT_MIN+1
	|| (0 == ret && *tail != '\0')
	)
		return INT_MIN;

	return (int)ret;
}

/* ----------------------------------------------------
 * Display the menu, get & return the user selection.
 */
int menu_selection( void )
{
	int ret = 0;

	for (;
	{
		puts( "\n" );
		puts( "MENOY EPILOWN" );
		puts( "-------------" );
		puts( "1: artithmos se kwdika Morse" );
		puts( "2: kwdikas Morse se arithmo" );
		puts( "0: eksodos" );
		printf( "> " );
		fflush(stdout);

		ret = get_int();
		if ( ret < 0 ) {
			puts( "invalid selection, try again" );
			continue;
		}
		break;
	}

	return ret;
}


/* ----------------------------------------------------
 * Read digits as chars from stdin, then convert & print them in-place as morse code.
 * Return 0 on error, 1 otherwise.
 */
int ms_dig2morse( char mo[N_MORSECODES][SIZ_MORSECODE] )
{
	int c = '\0';

	/* sanity check */
	if ( !mo ) {
		fputs( "*** internal error: invalid pointer\n", stderr );
		return 0;		/* false */
	}

	printf( "\nDwste arithmo gia metatroph se kwdika Morse: " );
	while ( '\n' != (c=getchar()) && EOF != c )
	{
		if ( !isdigit(c) ) {
			flush_stdin();
			puts( "<invalid>" );
			return 0;	/* false */
		}

		printf( "%s", mo[ c-'0'] );
		fflush(stdout);
	}
	putchar( '\n' );

	return 1;			/* true */
}

/* ----------------------------------------------------
 * Read morse code from stdin, then convert & print it as digits.
 * Return 0 on error, 1 otherwise.
 */
int ms_morse2digs( char mo[N_MORSECODES][SIZ_MORSECODE] )
{
	char input[MAXSIZ_INPUT] = {'\0'};
	int j = 0;
	size_t i = 0, nchars = 0;

	/* sanity check */
	if ( !mo ) {
		fputs( "*** internal error: invalid pointer\n", stderr );
		return 0;		/* false */
	}

	printf( "\nDwste kwdika Morse gia metatroph se arithmo: " );
	nchars = s_gets_flushed(input, MAXSIZ_INPUT);
	if ( nchars < SIZ_MORSECODE-1 ) {
		puts( "invalid input" );
		return 0;		/* false */
	}

	/* scan input by groups of SIZ_MORSECODE-1 consequtive chars */
	for (i=0; i < nchars; i += SIZ_MORSECODE-1)
	{
		/* look for current group in mo[][] */
		for (j=0; j < N_MORSECODES; j++) {
			if ( 0 == memcmp(mo[j], &input[i], SIZ_MORSECODE-1) )
				break;
		}

		/* group not found? */
		if ( N_MORSECODES == j ) {
			puts( "<invalid>" );
			return 0;
		}

		/* group found */
		printf( "%d", j );
		fflush( stdout );
	}
	if ( i < N_MORSECODES )
		putchar( '\n' );

	return 1;
}

/* -------------------------------------- */
int main( void )
{
	int  ms = 0;				/* menu selection */
	char mo[N_MORSECODES][SIZ_MORSECODE]={	/* supported morse codes*/
		"-----",
		".----",
		"..---",
		"...--",
		"....-",
		".....",
		"-....",
		"--...",
		"---..",
		"----."
	};

	for (;
	{
		ms = menu_selection();
		if ( MS_EXIT == ms )
			break;

		switch ( ms )
		{
			case MS_DIG2MORSE:
				ms_dig2morse(mo);
				break;

			case MS_MORSE2DIG:
				ms_morse2digs(mo);
				break;

			default:
				/* impossible */
				break;
		}
	}

	exit( EXIT_SUCCESS );
}

 

Σε γενικές γραμμές, ο παραπάνω κώδικας είναι πιο κοντά σε production standards, παρόλο που τον έγραψα στο πόδι. Το ίδιο πράγμα σε... student standards μπορεί να είναι κάπως έτσι...

 

 

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXSIZ_INPUT	(255+1)		/* for storing user input */

/* ----------------------------------------------------
 * Read a c-string from stdin, reject '\n' & flushing any extra characters if needed.
 * Return the number of characters successfully read,
 * or 0 if the user pressed just an ENTER.
 */
size_t s_gets_flushed( char *s, size_t ssize )
{
	register int c;
	register size_t i;

	/* sanity checks */
	if ( !s || ssize < 1 ) {
		return 0;
	}

	/* read chars from stdin */
	for (i=0; i < ssize-1 && '\n' != (c=getchar()) && EOF != c; i++)
		s[i] = c;

	if ( s[i] && s[i] != '\n' ) {		/* ssize reached without '\n' ? */
		while ( '\n' != getchar() )	/* flush any remaining chars */
			/* void */ ;
	}
	s[i] = '\0';				/* NUL-terminate s */

	return i;
}

/* ----------------------------------------------------
 * Read an int from stdin & return it (return INT_MIN on error).
 */
int get_int( void )
{
	char input[MAXSIZ_INPUT] = {'\0'}, *tail = NULL;
	long int ret = 0;
	errno = 0;

	if ( 0 == s_gets_flushed(input, MAXSIZ_INPUT) )
		return INT_MIN;

	ret = strtol(input, &tail, 10);
	if ( 0 != errno
	|| ret > INT_MAX || ret < INT_MIN+1
	|| (0 == ret && *tail != '\0')
	)
		return INT_MIN;

	return (int)ret;
}

/* ----------------------------------------------------
 * Display the menu, get & return the user selection.
 */
int menu( void )
{
	int ret = 0;

	for (;
	{
		puts( "\n" );
		puts( "MENOY EPILOWN" );
		puts( "-------------" );
		puts( "1: artithmos se kwdika Morse" );
		puts( "2: kwdikas Morse se arithmo" );
		puts( "0: eksodos" );
		printf( "> " );
		fflush(stdout);

		ret = get_int();
		if ( ret < 0 ) {
			puts( "invalid selection, try again" );
			continue;
		}
		break;
	}

	return ret;
}


/* -------------------------------------- */
int main( void )
{
	char input[MAXSIZ_INPUT] = {'\0'};
	size_t i = 0;
	int j = 0, ar = 0;
	char mo[10][6]= {
		"-----",
		".----",
		"..---",
		"...--",
		"....-",
		".....",
		"-....",
		"--...",
		"---..",
		"----."
	};

	for (;
	{
		int c = '\0';
		int wasInvalid = 0;	/* false */

		ar = menu();
		if ( 0 == ar )
			break;

		if ( 1 == ar )
		{
			printf( "\nDwste arithmo gia metatroph se kwdika Morse: " );
			while ( '\n' != (c=getchar()) && EOF != c )
			{
				if ( !isdigit(c) ) {
					int ch;
					/* flush stdin */
					while ( '\n' != (ch=getchar()) && EOF != ch )
						/* void */ ;
					puts( "invalid input" );
					wasInvalid = 1;	/* true */
					break;
				}
				printf( "%s ", mo[ c-'0'] );
				fflush(stdout);
			}
			if ( !wasInvalid )
				putchar( '\n' );
		}

		else if ( 2 == ar )
		{
			size_t nchars = 0;

			printf( "\nDwste kwdika Morse gia metatroph se arithmo: " );
			nchars = s_gets_flushed(input, MAXSIZ_INPUT);
			if ( nchars < 5 ) {
				puts( "invalid input" );
				continue;
			}

			/* scan input by groups of 5 consequtive chars */
			for (i=0; i < nchars; i += 5)
			{
				/* look for current group in mo[][] */
				for (j=0; j < 10; j++) {
					if ( 0 == memcmp(mo[j], &input[i], 5) )
						break;
				}

				/* group not found? */
				if ( 10 == j ) {
					puts( "<invalid>" );
					break;
				}

				/* group found */
				printf( "%d", j );
				fflush( stdout );
			}
			if ( i < 10 )
				putchar( '\n' );
		}

		/*
		else
			impossible
		*/
	}

	return 0;
}

 

Μικρότερος μεν, και ενδεχομένως πιο κατανοητός επειδή είναι μικρό το πρόγραμμα, αλλά λόγω έλλειψης abstractions και οργάνωσης είναι πιο δύσκολο να επεκταθεί, καθώς και να συντηρηθεί αν επεκταθεί.

Σιγουρα ο 2ος πιο κατανοητος,απο εμενα τουλαχιστον! Και παλι ευχαριστω  B)

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...