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

Ερωτήσεις για C


capoelo

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

>
#include <stdio.h>

int main(void)
{
int num1,num2;

printf("Δώστε δύο αριθμούς χωρισμένους με κενά: \n");
scanf("%d%d",&num1 , &num2);

printf("Άθροισμα :%d \n Διαφορά :%d \n Γινόμενο : %d ",(num1+num2),(num1-num2),(num1*num2));

if(num2!=0)
   printf("Διαίρεση :%.2f \n", (float)num1/num2);

else
   printf(" Σφάλμα διαίρεσης : oo " );

return 0;

}

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 1,6k
  • Δημ.
  • Τελ. απάντηση

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

Ναι να του δώσω κωδικα 50 γραμμες να εχει ελεγχους μεσα

μηπως δωσει και χαρακτηρα ο χρηστης αντι για αριθμο και κρασαρει

η scanf.

 

 

α) Δεν ήταν απάντηση σε εσένα.

 

β) Εάν δεν μπορείς να κάνεις συζήτηση χωρίς εντάσεις, τότε μην κάνεις καθόλου.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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

 

Ένα εξίσου βασικό πρόβλημα είναι το data-range (under)overflow κατά την εκτέλεση των πράξεων. Για παράδειγμα, όταν θέλουμε να υλοποιήσουμε την πράξη της πρόσθεσης σε 2 ακέραιους τύπου int, πρέπει να προβλέψουμε την περίπτωση του: n1 = INT_MAX, n2 > 0

 

Ομοίως προφανώς και για τις υπόλοιπες αριθμητικές πράξεις. Για τις 4 βασικές αριθμητικές πράξεις (πρόσθεση, αφαίρεση, διαίρεση, πολλαπλασιασμός) το αποκορύφωμα είναι όταν π.χ. θέλουμε να υπολογίσουμε το γινόμενο: INT_MAX * INT_MAX ή το αρνητικό του αντίστοιχο.

 

Συνδυασμένο με το γνωστό πρόβλημα του line-buffering στην ανάγνωση οποιασδήποτε πληροφορίας από την κύρια είσοδο, το όλο θέμα μπορεί εύκολα να χαρακτηριστεί εφιάλτης για όποιον θέλει να γράφει bullet-proof εφαρμογές.

 

Στην απλούστερη μορφή του, το πρόβλημα μπορεί να τεθεί σε μια εκφώνηση σαν την παρακάτω...

 

>
Γράψτε ένα πρόγραμμα που διαβάζει από την κύρια είσοδο και τυπώνει στην κύρια έξοδο έναν ακέραιο αριθμό τύπου int.

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

 

Το ...

>
#include <stdio.h>
int main( void )
{
  int n = 0;

  scanf("%d", &n);
  printf("%d\n");

  return 0;
}

που στοιχηματίζω θα απαντούσε η συντριπτική πλειοψηφία πρωτοετών στην C, είναι προφανώς προβληματικό για τιμές μεγαλύτερες του INT_MAX και μικρότερες του INT_MIN.

 

Το...

>
#include <stdio.h>
int main( void )
{
 int n = 0;

 if ( 1 == scanf("%d", &n) )
	printf("%d\n");
 else
	puts( "internal error" );

 return 0;
}

δεν προσφέρει απολύτως τίποτα, αφού η scanf δεν επιστρέφει αποτυχία σε περίπτωση overflow.

 

Η χρήση τύπου μεγαλύτερου από τον ζητούμενο....

>
#include <stdio.h>
#include <limits.h>

int main( void )
{
 long int n = 0;

 if ( 1 == scanf("%d", &n) )
 {
if ( n > INT_MIN-1 && n < INT_MAX+1 )
  		printf("%d\n");
else
  		puts( "over(under)flowed input" );
 }
 else
puts( "internal error" );

  return 0;
}

έχει τη δυναμική να μας δώσει προσωρινή λύσή, αλλά το πρόβλημα επανέρχεται αν ο χρήστης μας δώσει τιμή έξω από το εύρος [ LONG_MIN ... LONG_MAX ]

 

... και πάει λέγοντας, ακόμα και για τον μέγιστο τύπο ακεραίων στην C99, τον intmax_t, με εύρος [ INTMAX_MIN ... INTMAX_MAX ] (#include <inttypes.h>)

 

To make a long story short, και εξαιρώντας τη χρήση έτοιμων βιβλιοθηκών, ο ενδεδειγμένος τρόπος ανάγνωσης την κύριας εισόδου στη C είναι μονοκόμματα σε ένα μεγάλο c-string (π.χ. με fgets() ή με custom συνάρτηση που επιπρόσθετα κάνει και flush τυχόν σκουπίδα), από το οποίο c-string κατόπιν κρατάμε όσα tokens χρειαζόμαστε (π.χ. με την sscanf() ).

 

Εναλλακτικά μπορούμε να δημιουργήσουμε αυτά τα tokens με την strtok() και κατόπιν να τα μετατρέψουμε σε αριθμούς με τις συναρτήσεις strto??(), οι οποίες μας δίνουν πλήρη έλεγχο για το τι θα κρατήσουμε και τι θα πετάξουμε (αγνοήσουμε).

 

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

 

Ο κώδικας που ακολουθεί δείχνει έναν από τους (διάφορους) bullet-proof τρόπους να διαβάζουμε έναν αριθμό τύπου int, από την κύρια είσοδο...

 

 

 

>
#include <stdio.h>
#include <stdlib.h>	/* strtol() */
#include <limits.h>	/* INT_MIN, INT_MAX */

/*********************************************************//**
* @brief	Read into existing c-string s up to (ssize-sizeof(char)) chars from
* 		stdin or until ENTER is pressed, and null terminate it (remove ENTER
*		if necessary).
* 		If more than (ssize-sizeof(char)) chars have been typed before the
*		ENTER is pressed, they are ignored and they are removed from the
*		stdin buffer.
*
* @return	A pointer to the start of read c-string, or NULL on error.
*************************************************************
*/
char *s_getsflushed( char *s, const size_t ssize )
{
const size_t 	charsize = sizeof(char);/* don't assume 1 byte == sizeof(char) */
size_t 		i = 0;


/* sanity checks */
if ( !s )
	return NULL;
if ( ssize < charsize ) 
	return s;

/* read chars from stdin */
for (i=0; (s[i]=getc(stdin)) != '\n' && i < ssize-charsize; i += charsize)
	;					/* ... empty loop-body        */

if ( s[i] != '\n' ) {				/* ssize reached without '\n'   */
	s[i] = '\0';				/* ... null terminate s   	*/
	while (getchar() != '\n')		/* ... flush remaining chars  */
		;				/* ... ... empty loop-body    */
}
else
	s[i] = '\0';

return s;
}
/*********************************************************//**
* @brief	Read safely an integer form stdin.
* @return	The integer, or INT_MIN if input contained non-digits (including blanks),
*		or INT_MAX in case of out of range integer value.
*************************************************************
*/
int readInt( void )
{
char input[ 255+1 ] = {'\0'};
char *tail = NULL;
long int ret = INT_MAX;			/* INT_MAX & INT_MIN denote errors (see comments above) */

/* input failure? */
if ( !s_getsflushed(input, 255+1) )
	return INT_MAX;

ret = strtol(input, &tail, 10 );

/* blank or non-digit chars in input? */
if ( '\0' != *tail || (tail == input && 0 == ret) )
	return INT_MIN;

/* over/underflowed input? */
if ( ret > INT_MAX-1 || ret < INT_MIN+1 )
	return INT_MAX;

/* everything ok */
return (int)ret;
}

/* ------------------------------------------------- */
int main( void )
{
int n;

printf( "Enter a valid integer: " );
n = readInt();

if ( INT_MAX == n )
	puts("*** error: out of range integer!");
else if ( INT_MIN == n )
	puts("*** error: blank or non-digit chars in input!");
else
	printf( "%d was a valid input\n", n );

system("pause");	/* windows only */
return 0;
}

 

 

Η s_getsflushed() διαβάζει μονοκόμματα την κύρια είσοδο σε ένα μεγάλο c-string, το οποίο χρησιμοποιεί κατόπιν η readInt() για να το κάνει validate ως έγκυρο int και να το επιστρέψει στην main(). Η readInt() καταργεί τις τιμές INT_MIN και INT_MAX ως έγκυρες τιμές int, διότι τις χρησιμοποιεί για να επισημάνει τυχόν προβλήματα κατά το validation

 

Αυτή λοιπόν είναι μια (από τις πολλές) ολοκληρωμένη και κυρίως bullet-proof υλοποίηση για το (φαινομενικά απλούστατο) πρόβλημα διαβάσματος και τυπώματος ενός αριθμού τύπου int, σε C. Και σίγουρα ΔΕΝ είναι τετριμμένη διαδικασία (τετριμμένη την κάνουμε αν χρησιμοποιήσουμε κάποια εξωτερική βιβλιοθήκη, ή αν φτιάξουμε δικιά μας, με συναρτήσεις όπως οι παραπάνω).

 

Τώρα, για να μπορέσουμε να διαβάσουμε 2 ακέραιους int και να κάνουμε πάνω τους τις 4 βασικές αριθμητικές πράξεις, θέλουμε επιπρόσθετη μέριμνα όχι μόνο για την ύπαρξη μηδενικού παρανομαστή, όχι μόνο για την πιθανότητα υπερ(υπο)χείλισης των αριθμών που μας εισαγάγει ο χρήστης, αλλά και για την υπερ(υπο)χείλιση των αποτελεσμάτων της κάθε πράξης!

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

 

Ο κώδικας που ακολουθεί κάνει ότι επιχειρεί να κάνει ο κώδικας που ποστάρισε ο φίλος Starlight, με τη διαφορά πως αυτός εδώ λειτουργεί χωρίς να κρασάρει ότι input και να του δώσει ο χρήστης (με παραμετροποιήσιμο όριο τους 255 χαρακτήρες στη γραμμή εντολών). Δείχνει επίσης την ενίοτε τεράστια διαφορά που χωρίζει τους εκπαιδευτικούς κώδικες από τους κώδικες παραγωγής (ή που θα έπρεπε να χωρίζει :P).

 

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

 

Σημειώστε επίσης πως τα αποτελέσματα των πράξεων γίνονται cast στους μέγιστους δυνατούς τύπους που τους αντιστοιχούν, για να υπολογιστούν και να τυπωθούν στην οθόνη. Δηλαδή τυπώνονται κανονικά τα αποτελέσματα ακόμα κι αν υπερ(υπο)χειλίζουν τον τύπο δεδομένων τοων 2 όρων. Όσο ευρύτερος είναι ο τύπος δεδομένων που ζητάει η εκφώνηση, τόσο στενεύουν τα περιθώρια να μπορούμε να διαχειριστούμε ενδεχόμενη υπερ(υπο)χείλισής τους (τόσο στην είσοδο όσο και στην έξοδο).

 

 

 

>
/** C99 **/

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <inttypes.h>

#define MAXINPUT		(255+1)
#define INT_ISVALID(n)		( (n) > INT_MIN && (n) < INT_MAX )

/*********************************************************//**
* @brief	Read into existing c-string s up to (ssize-sizeof(char)) chars from
* 		stdin or until ENTER is pressed, and null terminate it (remove ENTER
*		if necessary).
* 		If more than (ssize-sizeof(char)) chars have been typed before the
*		ENTER is pressed, they are ignored and they are removed from the
*		stdin buffer.
*
* @return	A pointer to the start of read c-string, or NULL on error.
*************************************************************
*/
char *s_getsflushed( char *s, const size_t ssize )
{
const size_t 	charsize = sizeof(char);/* don't assume 1 byte == sizeof(char) */
size_t 		i = 0;

/* sanity checks */
if ( !s )
	return NULL;
if ( ssize < charsize ) 
	return s;

/* read chars from stdin */
for (i=0; (s[i]=getc(stdin)) != '\n' && i < ssize-charsize; i += charsize)
	;					/* ... empty loop-body    	*/

if ( s[i] != '\n' ) {				/* ssize reached without '\n'   */
	s[i] = '\0';				/* ... null terminate s   	*/
	while (getchar() != '\n')		/* ... flush remaining chars  */
		;				/* ... ... empty loop-body	*/
}
else
	s[i] = '\0';

return s;
}

/*********************************************************//**
* @brief	Convert a c-string to an integer.
* @return	The integer, or INT_MIN if input contained non-digits (including blanks),
*		or INT_MAX in case of out of range integer value.
*************************************************************
*/
int s_toInt( const char *s )
{
long ret   = 0L;
char *tail = NULL;

if ( !s || !*s )
	return INT_MIN;

ret = strtol(s, &tail, 10 );

/* blank or non-digit chars in s? */
if ( '\0' != *tail || (tail == s && 0 == ret) )
	return INT_MIN;

/* over/underflowed s as int? */
if ( ret > INT_MAX-1 || ret < INT_MIN+1 )
	return INT_MAX;

/* everything ok */
return (int)ret;
}

/*********************************************************//**
* @brief	Break an existing c-string to up to ntoks tokens
*		and store them in *tokens[] (uses any char in delims
*		as separators between tokens).
* @return 	The number of tokens, or 0 on failure.
*************************************************************
*/
int s_tokenize( char *s, char *tokens[], int ntoks, const char *delims )
{
register int i=0;

/* sanity checks */
if ( !s || !tokens || !delims )
	return 0;
if ( !*s || !*delims || ntoks < 1 )
	return 0;

tokens[ 0 ] = strtok(s, delims);
if ( NULL == tokens[0] )
	return 0;
for (i=1; i < ntoks && (tokens[i]=strtok(NULL, delims)) != NULL; i++)
	;	/* void */

return i;
}
/*********************************************************//**
*
*************************************************************
*/
int main( void )
{
char 		input[ MAXINPUT ] = {'\0'};
char 		*tokens[2] = {NULL};
int 		n1 = 0, n2 = 0;

/* ask for 2 integers */
printf( "Give 2 valid ints, separated by blanks: " );
if ( NULL == s_getsflushed(input, MAXINPUT) ) {
	fputs( "*** internal error, aborting...\n", stderr );
	goto ret_fatal;
}
/* validate input line */
if ( '\0' == input || 2 > s_tokenize( input, tokens, 2, " \t\n\f" ) ) {
	fputs( "*** insufficient data...\n", stderr );
	goto ret_fatal;
}

/* validate given integers */
n1 = s_toInt( tokens[0] );
n2 = s_toInt( tokens[1] );
if ( !INT_ISVALID(n1) || !INT_ISVALID(n2) ) {
	fputs( "*** invalid data...\n", stderr );
	goto ret_fatal;
}

/* perform & print the 4 basic arithmetic operations on the 2 ints */

/* addition */
printf( "%d + %d = %"PRIdMAX"\n", n1, n2, (intmax_t)n1 + (intmax_t)n2 );

/* subtraction */
printf( "%d - %d = %"PRIdMAX"\n", n1, n2, (intmax_t)n1 - (intmax_t)n2 );

/* multiplication */
printf( "%d * %d = %"PRIdMAX"\n", n1, n2, (intmax_t)n1 * (intmax_t)n2 );

/* division */
printf( "%d / %d = ", n1, n2 );
if ( 0 == n2 )
	puts( "ERR (division by 0)" );
else
	printf( "%Lg\n", (long double)n1 / n2 );

system("pause");			/* windows only */
exit( EXIT_SUCCESS );

ret_fatal:
system("pause");			/* windows only */
exit( EXIT_FAILURE );
}

 

 

Ένας ακόμα λόγος που έκανα αυτή την δημοσίευση (πέραν του ενημερωτικού/εκπαιδευτικού) είναι για να αποθαρρύνω (ναι σωστή είναι η λέξη) επίδοξους μελλοντικούς επαγγελματίες, που ίσως να θεωρούν πως ο προγραμματισμός είναι χαβαλές, που ίσως νομίζουν πως θα βρουν δουλειά (ή πως θα παραμείνουν σε δουλειά) χωρίς να έχουν το κατάλληλο υπόβαθρο... και κυρίως όσους δεν έχουν τη διάθεση, το "mentality" αν προτιμάτε, να θέλουν να αποκτήσουν το εκάστοτε κατάλληλο υπόβαθρο.

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

LOL ok ok.

 

Οποιος θελει να γινει προγραμματιστης να βαλει το κεφαλι κατω

να ξεχασει τον χαβαλε και την πλακα και στο εξης να λεει καλημερα μονο

στον υπολογιστη του. Ο προγραμματισμος δεν εχει σχεση με τον χαρακτηρα του ανθρωπου.

Τι τα μπλεκεις δεν μπορω να καταλαβω migf1

 

Λοιπον ο κωδικας που εδωσε ο φιλος ηταν για απλες πραξεις κατι που για μενα

προσωπικα σημαινει πως οι δηλωσεις ειναι ολες σε απλα int , τον ελεγχο ας τον εβαζε μονος του ημουν κουρασμενος χθες το βραδυ και μονο που τον ειδα ως προς τις scanf ηταν ενταξει θεωρω πως ειναι αυτονοητο καποιος να γνωριζει οτι στο 1/κατι αυτο το κατι ειναι διαφορετικο του μηδενος για να οριζεται και να εχει νοημα η παρασταση . Τωρα αν καποιος με απελυε

για αυτα ας με απελυε. Θα μπω εγω σε 1ο εξαμηνο 1 μερα και να τους αρχισω με εισοδους

με strings και χειρισμο μεσω δεικτων. Και αν καταλαβουν τιποτα σφυρα μου. Η βασικη δομη ειναι

αυτη την οποια ακολουθουν πολλοι καθηγητες σε πολλες σχολες... οποιος θελει να το ψαξει παραπανω μπορει να διαβασει τους κωδικες σου migf1.

 

O εκπαιδευτικος πρεπει να προσαρμοζεται στις εκαστοτε αναγκες των φοιτητων και συμφωνα με αυτες να κανει το μαθημα του. Μαθημα κανει οχι επιδειξη.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Γιατί πρέπει να εκλαμβάνεις τα πάντα ως προσωπικές επιθέσεις εναντίον σου; Όταν θέλω να απευθυνθώ σε κάποιον συγκεκριμένα κάνω παράθεση στα λεγόμενά του, και σχολιάζω. Και δόξα το θεό δεν έχω κανένα πρόβλημα να απευθυνθώ προσωπικά στον οποιοδήποτε.

 

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Γιατί πρέπει να εκλαμβάνεις τα πάντα ως προσωπικές επιθέσεις εναντίον σου; Όταν θέλω να απευθυνθώ σε κάποιον συγκεκριμένα κάνω παράθεση στα λεγόμενά του, και σχολιάζω. Και δόξα το θεό δεν έχω κανένα πρόβλημα να απευθυνθώ προσωπικά στον οποιοδήποτε.

 

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

 

 

Οχι δεν ειναι προσωπικη επιθεση συζητηση κανουμε. Απλα σου λεω οτι εγω προσωπικα

δεν θα υιοθετουσα τετοια σταση σε κανεναν. Ο απλος λογος για αυτο ειναι οτι ολοι ειμαστε ανθρωποι

και κανουμε λαθη . Δηλαδη μου εφερε εναν κωδικα ο αλλος στο ετσι... εγω θα τον εβλεπα και θα γελουσα

αλλα θα φροντιζα να του εξηγησω (αν φυσικα ηξερα και ημουν εμπειρος) ... νταξει η δουλεια δεν κυλαει

και αν δεν το παρεις και λιγο χαλαρα. Και επισης αν δεν υπηρχε λαθος στους προγραμματιστες δεν θα υπηρχαν

νεοτερες εκδοσεις στα προγραμματα ετσι δεν ειναι? ολοι κανουμε λαθη δεν χρειαζεται

ουτε αγχος ουτε να χαλαμε τις καρδιες μας τωρα.

 

p.s Δεν κρινω την σταση σου απλα τονιζω την διαφορετικοτητα για να μην παρεξηγουμαστε.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Οχι δεν ειναι προσωπικη επιθεση συζητηση κανουμε. Απλα σου λεω οτι εγω προσωπικα

δεν θα υιοθετουσα τετοια σταση σε κανεναν.

Σε ποια στάση αναφέρεσαι; Με διαβάζω και με ξανα-διαβάζω και αδυνατώ να βρω κάτι το επιλήψιμο στη στάση που έχω κρατήσει σε αυτό το νήμα.

 

Ο απλος λογος για αυτο ειναι οτι ολοι ειμαστε ανθρωποι

και κανουμε λαθη . Δηλαδη μου εφερε εναν κωδικα ο αλλος στο ετσι... εγω θα τον εβλεπα και θα γελουσα

αλλα θα φροντιζα να του εξηγησω (αν φυσικα ηξερα και ημουν εμπειρος) ... νταξει η δουλεια δεν κυλαει

και αν δεν το παρεις και λιγο χαλαρα. Και επισης αν δεν υπηρχε λαθος στους προγραμματιστες δεν θα υπηρχαν

νεοτερες εκδοσεις στα προγραμματα ετσι δεν ειναι? ολοι κανουμε λαθη δεν χρειαζεται

ουτε αγχος ουτε να χαλαμε τις καρδιες μας τωρα.

 

p.s Δεν κρινω την σταση σου απλα τονιζω την διαφορετικοτητα για να μην παρεξηγουμαστε.

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

 

Θεώρησες χρήσιμο να ποστάρεις 2 αποσπάσματα κώδικα χωρίς να έχουν ζητηθεί, προφανώς καλοπροαίρετα ως προέκταση της αρχικής ερώτησης. Και τα 2 σου αυτά αποσπάσματα περιείχαν χτυπητό bug το οποίο και θεώρησα χρήσιμο να επισημάνω, επίσης καλοπροαίρετα. Αντί να το δεχτείς προσπάθησε να υποβιβάσεις την σημασία της επισήμανσης.

 

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Mπα δεν υπάρχει καμια υπονοια υποβιβασμου των συμβουλων σου απο μεριας μου.

Ισα ισα εχω ενστερνιστεί και αρκετες απο αυτες στον προγραμματισμο φυσικα.

Απλα εκεινο που με προβληματιζει ειναι το κατα ποσο θα μπορεσει ενας αρχαριος

να παρακολουθησει αυτα που γραφεις. Καπου είδα οτι εγραψες οτι δεν αρκει μονο

να μην υπερχειλιζει ενας εκ των 2 τελεστεων αλλα ουτε και το τελικο αποτελεσμα!!!!

 

Αυτο φυσικα θελει απο μονο του ειδικες γνωσεις πανω στις μετατροπες να γνωριζει δηλαδη και την λεπτομερεια οτι κατα την διαρκεια μια εκχωρησης ο δεξιος γινεται παντοτε τύπος του αριστερού + οτι θα πρεπει ο αλλος να εχει πληρη εικονα του τι συμβαινει με την αναπαρασταση των αριθμων... τα συμπληρωματα ως προς 1

ως προς 2 κτλπ γιατι αν καταλαβα καλα εκεινο που λες ειναι πολυ απλοικα οτι αν εχουμε ενα 8bit συστημα

ξερω γω και ειναι καπως ετσι :

 

> 

bin | dec
000 | 0
001 | 1
010 | 2
011 | 3
100 |-4
101 |-3
110 |-2
111 |-1 

 

η παρασταση συμπληρωματος ως προς 2 τοτε αν παω εγω να κανω την πράξη 3 + 2 το 5 που θα προκυψει δεν υπάρχει στην πιο πανω αναπαρασταση επομενως κατι τετοιο ειναι με την μια overflow condition δηλαδη μια ανιχνευσιμη κατασταση λαθους απο το συστημα που σου λεει οτι το αποτελεσμα της πραξης που επιχειρεις να κανεις δεν υποστηριζεται . Ολα τα παραπανω δηλαδη για μενα ειναι προαπαιτουμενα ωστε να καταλαβει καποιος τι θες να του εννοοησεις αρχικα ουτε καν να προγραμματισεις με την λεξη overflow.

 

Δεν λεω πως εχεις αδικο αλλα.... ολα αυτα οπως ξερεις πολυ καλυτερα απο μενα ειναι αλυσιδα... το να μου πεταξει εμενα ενα βιβλιο ας πουμε το keyword IEEE 754 για αναπαρασταση αριθμων κινητης υποδιαστολης αυτο απο πισω θελει καταρχην να ξερεις πως αναπαριστωνται αυτοι οι αριθμοι στο μηχανημα και μεταααα να πας στο παραπανω προτυπο. Θελω να πω πως καμια φορα οι ελεγχοι μπορουν να αποφευγονται για απλοτητα και αυτο δεν το τονισα εξαρχης οκ.

 

Εχω αδικο στα παραπανω ?

 

p.s bin - binary & dec -> decimal στον πίνακα.

 

p.s2 3 bits χρειαζονται στην αναπαρασταση καθε αριθμου επειδη 2^n = 8 => 2^n = 2^3 (ίσες βάσεις - εξισώνουμε τους εκθέτες) => n = 3

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

...

Καπου είδα οτι εγραψες οτι δεν αρκει μονο

να μην υπερχειλιζει ενας εκ των 2 τελεστεων αλλα ουτε και το τελικο αποτελεσμα!!!!

 

Αυτο φυσικα θελει απο μονο του ειδικες γνωσεις πανω στις μετατροπες να γνωριζει δηλαδη και την λεπτομερεια οτι κατα την διαρκεια μια εκχωρησης ο δεξιος γινεται παντοτε τύπος του αριστερού + οτι θα πρεπει ο αλλος να εχει πληρη εικονα του τι συμβαινει με την αναπαρασταση των αριθμων... τα συμπληρωματα ως προς 1

ως προς 2 κτλπ γιατι αν καταλαβα καλα εκεινο που λες ειναι πολυ απλοικα οτι αν εχουμε ενα 8bit συστημα

ξερω γω και ειναι καπως ετσι :

 

 

 

> 

bin | dec
000 | 0
001 | 1
010 | 2
011 | 3
100 |-4
101 |-3
110 |-2
111 |-1 

 

η παρασταση συμπληρωματος ως προς 2 τοτε αν παω εγω να κανω την πράξη 3 + 2 το 5 που θα προκυψει δεν υπάρχει στην πιο πανω αναπαρασταση επομενως κατι τετοιο ειναι με την μια overflow condition δηλαδη μια ανιχνευσιμη κατασταση λαθους απο το συστημα που σου λεει οτι το αποτελεσμα της πραξης που επιχειρεις να κανεις δεν υποστηριζεται . Ολα τα παραπανω δηλαδη για μενα ειναι προαπαιτουμενα ωστε να καταλαβει καποιος τι θες να του εννοοησεις αρχικα ουτε καν να προγραμματισεις με την λεξη overflow.

 

Δεν λεω πως εχεις αδικο αλλα.... ολα αυτα οπως ξερεις πολυ καλυτερα απο μενα ειναι αλυσιδα... το να μου πεταξει εμενα ενα βιβλιο ας πουμε το keyword IEEE 754 για αναπαρασταση αριθμων κινητης υποδιαστολης αυτο απο πισω θελει καταρχην να ξερεις πως αναπαριστωνται αυτοι οι αριθμοι στο μηχανημα και μεταααα να πας στο παραπανω προτυπο. Θελω να πω πως καμια φορα οι ελεγχοι μπορουν να αποφευγονται για απλοτητα και αυτο δεν το τονισα εξαρχης οκ.

 

Εχω αδικο στα παραπανω ?

 

p.s bin - binary & dec -> decimal στον πίνακα.

 

p.s2 3 bits χρειαζονται στην αναπαρασταση καθε αριθμου επειδη 2^n = 8 => 2^n = 2^3 (ίσες βάσεις - εξισώνουμε τους εκθέτες) => n = 3

 

 

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

 

Το μόνο που χρειάζεται είναι να κάνεις ένα απλό cast (ότι δηλαδή κάνει και ο κώδικας που ποστάρισα παραπάνω, τον οποίο κρίνοντας από την ερώτηση υποθέτω δεν διάβασες)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αυτό που γράφω στο σχόλιο, ότι δηλαδή δουλεύει και σε πλατφόρμες όπου το sizeof(char) δεν ισούται με 1 byte.

 

Δεν έχω ασχοληθεί με πολύ εξωτικές πλατφόρμες αλλά υπάρχουν πλατφόρμες με pre-c89 compilers ?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αν δεν απατώμαι, το στάνταρ έχει αλλάξει και το sizeof(char) δεν περιγράφεται πλέον ως guaranteed equal to 1 byte, αλλά ως guaranteed equal to 1 unit... με το "unit" ορισμένο ώς το μικρότερο δυνατό μέγεθος απεικόνισης, όχι απαραίτητα όμως σε LL... ή κάπως έτσι τέλος πάντων.

 

Ψάξτο αν σε ενδιαφέρει, πρέπει να είναι στο C99 αν δεν κάνω λάθος (αν το βρεις βάλε και ένα link να το έχουμε πρόχειρο :) )

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επισκέπτης
Αυτό το θέμα είναι πλέον κλειστό για περαιτέρω απαντήσεις.

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