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

Image Processing C program for hough circle!!


iex

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

To να γράψεις ένα πρόγραμμα που να καταλαβαίνει ο υπολογιστής είναι εύκολο, το θέμα είναι να το γράψεις έτσι ώστε να το καταλαβαίνουν εύκολα οι άνθρωποι! Μπορεί να κάτσω κάποια στιγμή να το κάνω refactor αν θέλετε πάντως! Είναι καλή συνήθεια.

 

Ορίστε, το έκανα εγώ refactor, και με σχόλια και με sanity checks και με intrusive auto-fixes, και με reusability, κλπ...

 

 

 

/* Header inclusions */

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

/* Constants & Macros */

#define PI		3.14159265358979323846
#define MIN(x,y)	( (x) < (y) ? (x) : (y) )

#define IMG_FNAME	"_circle.raw"
#define IMG_H		256		/* image height */
#define IMG_W		256		/* image width */

#define BG_COLOR	225
#define FG_COLOR	65

#define C_CENTER	128
#define C_RADIUS	100

/* Custom Types */

typedef unsigned char Byte;

typedef struct RawImage {
	int w, h;
	Byte *buffer;
}RawImage;

/* Function Prototypes */

static int rawImage_is_valid( RawImage *image );
static int rawImage_init( RawImage *image, int height, int width, Byte bgcolor );
static int rawImage_cleanup( RawImage *image );
static void rawImage_draw_circle( RawImage *image, int center, int radius, Byte fgColor );
static int rawImage_save( RawImage *image, char *fname );

/* Function Definitions */

/* -------------------------------------------------
 * program's entry point
 */
int main( void )
{
	RawImage image = {0,0, NULL};
	int ret = 0;

	if ( !rawImage_init( &image, IMG_H, IMG_W, BG_COLOR) ) {
		fputs( "*** fatal error, aborting...\n", stderr );
		ret = 1;
	}
	else {
		rawImage_draw_circle( &image, C_CENTER, C_RADIUS, FG_COLOR );
		rawImage_save( &image, IMG_FNAME);
		rawImage_cleanup( &image );
	}

	system( "pause" );	/* Windows only */
	return ret;
}

/* ------------------------------------------------- */
static int rawImage_is_valid( RawImage *image )
{
	return 	image
		&& image->buffer
		&& image->h > 0
		&& image->w > 0
		;
}

/* -------------------------------------------------
 * init an (already existed) image according to the specified specidications
 */
static int rawImage_init( RawImage *image, int height, int width, Byte bgcolor )
{
	int i;
	const int npixels = height * width;

	/* sanity check */
	if ( !image ) {
		fputs( "rawImage_init: invalid pointer argument\n", stderr );
		return 0;
	}

	/* demand valid dimensions */
	if ( height < 1 || width < 1 ) {
		fputs( "rawImage_init: invalid image dimensions\n", stderr );
		return 0;
	}

	/* apply specifications */

	if ( image->buffer ) {
		puts( "rawImage_init: overwriting old data" );
		free( image->buffer );
	}

	image->buffer = calloc(npixels, sizeof(Byte) );
	if ( NULL == image->buffer ) {
		perror( "rawImage_init: calloc" );
		return 0;
	}

	for (i=0; i < npixels; i++)
		image->buffer[i] = bgcolor;
	image->h = height;
	image->w = width;

	return 1;
}

/* ------------------------------------------------- */
static int rawImage_cleanup( RawImage *image )
{
	if ( !image ) {
		fputs( "rawImage_init: invalid pointer argument\n", stderr );
		return 0;
	}

	image->h = 0;
	image->w = 0;
	if ( image->buffer ) {
		free( image->buffer );
		image->buffer = NULL;
	}

	return 1;
}

/* ------------------------------------------------- */
static void rawImage_draw_circle( RawImage *image, int center, int radius, Byte fgColor )
{
	double angle;
	const double maxANGLE = 2 * PI;

	/* ensure valid rawImage */
	if ( !rawImage_is_valid(image) ) {
		fputs( "rawImage_draw_circle: invalid image\n", stderr );
		return;
	}

	/* ensure proper radius */
	if ( radius < 0 ) {
		radius = abs(radius);
		puts( "*** rawImage_draw_circle: negative radius fixed" );
	}
	else if ( 0 == radius ) {
		radius = 1;
		puts( "*** rawImage_draw_circle: 0 radius fixed to 1" );
	}
	/* ensure proper center + radius */
	int maxrange = MIN(image->h, image->w);
	if ( center + radius > maxrange ) {
		puts( "*** rawImage_draw_circle: circle scaled down to fit the image" );
		center = radius = maxrange / 2;
	}

	/* draw the circle */
	for (angle = 0.0; angle < maxANGLE; angle += 0.01)
	{
		int y = (radius * sin(angle)) + center;
		int x = (radius * cos(angle)) + center;

		image->buffer[y * image->w + x] = fgColor;
	}
}

/* -------------------------------------------------
 * save the buffer of an image to disk
 */
static int rawImage_save( RawImage *image, char *fname )
{
	FILE *fp = NULL;
	int ret = 1;

	if ( !rawImage_is_valid(image) ) {
		fputs( "rawImage_save: invalid image\n", stderr );
		return 0;
	}

	/* save buffer of image to disk */
	size_t buflen = image->h * image->w;
	if ( NULL == (fp = fopen(fname, "wb")) ) {
		perror("rawImage_save: fopen");
		return 0;
	}
	if ( buflen != fwrite(image->buffer, sizeof(Byte), buflen, fp) ) {
		perror("rawImage_save: fwrite");
		ret = 0;
	}
	 
	fclose(fp);

	return ret;
}

 

 

Η αρχική έκδοση του DirectX εξακολουθεί να είναι μακράν πιο ευανάγνωστη.

 

Όπως είπαν και τα άλλα παιδιά, για τόσο μικρό κώδικα που έτσι κι αλλιώς παρατέθηκε ως απλό παράδειγμα το "production refactoring" περισσότερο δυσχεραίνει παρά διευκολύνει την ανάγνωση της ουσίας, γιατί κουβαλάει ένα κάρο visual (και όχι μόνο) overhead μαζί του.

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

Ορίστε, το έκανα εγώ refactor, και με σχόλια και με sanity checks και με intrusive auto-fixes, και με reusability, κλπ... [..]

Ωραίος! :-)

To να γράψεις ένα πρόγραμμα που να καταλαβαίνει ο υπολογιστής είναι εύκολο, το θέμα είναι να το γράψεις έτσι ώστε να το καταλαβαίνουν εύκολα οι άνθρωποι!

Ξέρεις καμία φορά το πρόβλημα δεν είναι μόνο στο refactor του κώδικα αλλά στις γνώσεις του ανθρώπου που προσπαθεί να τον διαβάσει.

Μπορεί να κάτσω κάποια στιγμή να το κάνω refactor αν θέλετε πάντως! Είναι καλή συνήθεια.

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

Πολύ καλογραμμένο migf1!

Το πρόγραμμά σου πιστεύω ότι είναι αρκετά πιο self-explanatory σε σχέση με το αρχικό(ένας από τους σκοπούς του refactoring). To visual overhead αποφεύγεται εύκολα σπάζοντας το project σε αρχεία.

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

Δημοσ. (επεξεργασμένο)

 


Ευχαριστώ για τα καλά σας λόγια για τον κώδικα, αλλά θα ήθελα να καταστήσω σαφές πως τον έγραψα για να ενισχύσω την άποψη των παιδιών που υποστηρίζουν πως στην προκειμένη περίπτωση δυσχεραίνει την ανάγνωση του παραδείγματος.
 
Γενικώς, ένα πολύ μεγάλο μέρος του refactoring (αν όχι όλο) στηρίζεται στην προσθήκη έξτρα abstraction levels στον κώδικα (χρησιμοποιείται και ο όρος levels of indirection). Κάθε νέο τέτοιο επίπεδο απομακρύνεται ολοένα και περισσότερο από τις λεπτομέρειες της υλοποίησης, οι οποίες κατά την άποψή μου ήταν αυτές που ενδιαφερόταν να διαβάσει εξαρχής ο topic-starter αυτού του νήματος.
 
Ο κώδικας χρησιμοποιεί (συνειδητά) και εκτεταμένο error-checking, το οποίο δυσχεραίνει ακόμα περισσότερο τον εντοπισμό της υλοποίησης αυτής κάθε αυτής. Παρεμπιπτόντως, θα μπορούσα να βάλω κι άλλα abstractions στον κώδικα, π.χ. αντί για κύκλο θα μπορούσα ας πούμε να χρησιμοποιήσω μια πιο γενική έννοια (ας πούμε κλάση) π.χ. shape με τον κύκλο να αποτελεί subclassed αντικείμενό της, κλπ, κλπ. Προσθέτοντας ακόμα ένα abstraction level χωρίζοντας τον κώδικα σε αρχεία όπως προτείνεις φίλε jsiskos θα επιδείνωνε ακόμα περισσότερο το readability.
 
Επίσης κατά κανόνα το refactoring λειτουργεί εις βάρος των επιδόσεων, κάτι που σε συγκεκριμένες κατηγορίες λογισμικού δεν είναι επιθυμητό.
 
Αυτό που θέλω να καταλήξω είναι πως το refactoring είναι καλό πράγμα γενικώς, αλλά όπως σχεδόν όλα τα πράγματα στον προγραμματισμό δεν αποτελεί πανάκεια... πρέπει να σταθμιστούν τα + και τα - του ή/και ο βαθμός εφαρμογής του, ανάλογα την περίσταση ;)

 

Επεξ/σία από migf1
  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καλησπέρα σας σε όλους ευχαριστώ και πάλι για την βοήθεια και τον χρόνο σας.
Σας στέλνω την τελική υλοποίηση μου που καλύπτει τα ζήτηματα της άσκησης. Να είναι γεμάτος ο κύκλος με χρώμα και η ακτίνα να δίνεται απο τον χρήστη.

// ---------------------------------------------------------------

//
// ---------------------------------------------------------------

#include
#include
#include

// ---------------------------------------------------------------
// ÓÔÁÈÅÑÁ ÓÔÏÉ×ÅÉÁ ÔÙÍ ÅÉÊÏÍÙÍ ÅÉÓÏÄÏÕ-ÅÎÏÄÏÕ
// ---------------------------------------------------------------
#define INPUT_FILENAME "test_image.raw" // ÄéáäñïìÞ/üíïìá áñ÷åßïõ åéóüäïõ
#define OUTPUT_FILENAME "erotima2.raw" // ÄéáäñïìÞ/üíïìá áñ÷åßïõ åîüäïõ
#define ROWS 256 // ÐëÞèïò ãñáììþí åéêüíáò åéóüäïõ
#define COLUMNS 256 // ÐëÞèïò óôçëþí åéêüíáò åéóüäïõ
#define GREYLEVELS 256 // ÐëÞèïò áðï÷ñþóåùí åéêüíáò
#define CENTER 128
#define OUTPUT_ROWS ROWS // ÐëÞèïò ãñáììþí åéêüíáò åîüäïõ
#define OUTPUT_COLUMNS COLUMNS // ÐëÞèïò óôçëþí åéêüíáò åîüäïõ
#define BKGRND 225
// ---------------------------------------------------------------
// ÔÅËÏÓ ÐÑÏÓÄÉÏÑÉÓÌÏÕ ÓÔÏÉ×ÅÉÙÍ ÅÉÊÏÍÙÍ
// ---------------------------------------------------------------


int main(void)
{
// ÄÇËÙÓÅÉÓ ÌÅÔÁÂËÇÔÙÍ
// -----------------------------------------------------------

// Ðßíáêåò åéêüíùí
unsigned char inputImage [ROWS][COLUMNS],
outputImage [OUTPUT_ROWS][OUTPUT_COLUMNS];

// Áñ÷åßá
FILE *inputFile,
*outputFile;

// ÌåôáâëçôÝò ãåíéêÞò ÷ñÞóåùò
int i = 0,
j = 0;
int x,y,r;


// -----------------------------------------------------------
// ÔÅËÏÓ ÄÇËÙÓÅÙÍ ÌÅÔÁÂËÇÔÙÍ
// -----------------------------------------------------------

// ÖÏÑÔÙÓÇ ÅÉÊÏÍÁÓ ÅÉÓÏÄÏÕ ÁÐÏ ÄÉÓÊÏ
// -----------------------------------------------------------


if ( ((inputFile = fopen(INPUT_FILENAME,"rb")) != NULL))
{
for (i = 0; i < ROWS; i++)
{
for (j = 0; j < COLUMNS; j++)
{
fscanf(inputFile, "%c", &inputImage[j]);
}
}
}
else
{
printf("Error loading image.");
}
fclose(inputFile);

// -----------------------------------------------------------
// ÊÙÄÉÊÁÓ ÅÐÅÎÅÑÃÁÓÉÁÓ ÅÉÊÏÍÁÓ - ÁÑ×Ç
// -----------------------------------------------------------

memset(&outputImage, BKGRND, sizeof(outputImage));


elegxos:
printf ("Dose tin akrina tou kuklou (prosoxi na einai mikroteri apo 128): ");
scanf ("%d",&r);

if (r>CENTER)
{
printf ("EDOSES MH epitreptes diastaseis. \n ");
goto elegxos;
}
else
{
for (i= -r; i< r; i++)
{
int height = sqrt(r * r - i * i);
for (j = -height; j < height; j++)
{
x=i+CENTER;
y=j+CENTER;
outputImage[x][y]= 64;
}

}
}
// -----------------------------------------------------------
// ÊÙÄÉÊÁÓ ÅÐÅÎÅÑÃÁÓÉÁÓ ÅÉÊÏÍÁÓ - ÔÅËÏÓ
// -----------------------------------------------------------

// ÁÐÏÈÇÊÅÕÓÇ ÅÉÊÏÍÁÓ ÅÎÏÄÏÕ ÓÔÏ ÄÉÓÊÏ
// -----------------------------------------------------------
if ( ((outputFile = fopen(OUTPUT_FILENAME,"wb")) != NULL))
{
for (i = 0; i < OUTPUT_ROWS; i++)
{
for (j = 0; j < OUTPUT_COLUMNS; j++)
{
fprintf(outputFile, "%c", outputImage[j]);
}
}
}
else
{
printf("Error saving image.");
}
fclose(outputFile);

}

 

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

edited:<br /><br />Με μία γρήγορη ματία που έριξα έχω μια παρατήρηση μόνο.<br />Καλύτερα να αλλάξεις το goto με ένα do while και να κάνεις έλεγχο για αρνητική ακτίνα...<br /><br />Επίσης μία ερώτηση. Η memset είναι πιο γρήγορα από ένα loop για το γέμισμα του πίνακα;

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

Δεν το έκανα compile αλλά νομίζω πρέπει να είναι οκ...

 

 

// ---------------------------------------------------------------
//
// ---------------------------------------------------------------

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

// ---------------------------------------------------------------
// OOAEANA OOIE?AEA OUI AEEIIUI AEOIAIO-AIIAIO
// ---------------------------------------------------------------
#define FNAME_IN	"test_image.raw"// Aeaanii?/uiiia an?a?io aeouaio
#define FNAME_OUT	"erotima2.raw" 	// Aeaanii?/uiiia an?a?io aiuaio
#define ROWS		256		// ?e?eio anaii?i aeeuiao aeouaio
#define COLS		256		// ?e?eio ooce?i aeeuiao aeouaio
#define GREYLEVELS	256		// ?e?eio a?i?n?oaui aeeuiao
#define CENTER		128
#define BG_COLOR	225
// ---------------------------------------------------------------
// OAEIO ?NIOAEINEOIIO OOIE?AEUI AEEIIUI
// ---------------------------------------------------------------


int main( void )
{
	// ACEUOAEO IAOAAECOUI
	// -----------------------------------------------------------

	// ??iaeao aeeuiui
	unsigned char imageIn[ROWS][COLS]  = { {0,0} };
	unsigned char imageOut[ROWS][COLS] = { {0,0} };

	// An?a?a
	FILE *fpIn = NULL, *fpOut = NULL;	/* input & output file pointers */

	// IaoaaecoYo aaiee?o ?n?oauo
	int i=0, j=0;
	int x,y, r;				/* (x,y) point at perimeter, r = radius */


	// -----------------------------------------------------------
	// OAEIO ACEUOAUI IAOAAECOUI
	// -----------------------------------------------------------

	// OINOUOC AEEIIAO AEOIAIO A?I AEOEI
	// -----------------------------------------------------------

	/* read data from fpIn to imageIn */
	if ( (fpIn = fopen(FNAME_IN,"rb")) != NULL )
	{
		for (i=0; i < ROWS; i++)
		{
			for (j=0; j < COLS; j++)
			{
				// was: fscanf(fpIn, "%c", &imageIn[i][j]);
				imageIn[i][j] = (unsigned char)fgetc(fpIn);
			}
		}
	}
	else
	{
		printf("Error loading image.");
	}
	fclose(fpIn);

	// -----------------------------------------------------------
	// EUAEEAO A?AIANAAOEAO AEEIIAO - AN?C
	// -----------------------------------------------------------

	memset( &imageOut, BG_COLOR, sizeof(imageOut) );

#if 0	/* DISABLED: des parakatw sto #else */

elegxos:
	printf ("Dose tin akrina tou kuklou (prosoxi na einai mikroteri apo 128): ");
	scanf ("%d",&r);

	if (r > CENTER)
	{
		printf ("EDOSES MH epitreptes diastaseis. \n ");
		goto elegxos;
	}
	else
	{
		for (i= -r; i< r; i++)
		{
			int height = sqrt(r * r - i * i);
			for (j = -height; j < height; j++)
			{
				x = i + CENTER;
				y = j + CENTER;
				imageOut[x][y] = 64;
			}
		}
	}
#else
	/* keep asking until valid radius is entered */
	for (;
	{
		char input[255+1] = {'\0'};	/* input string */
		printf( "Akrina kuklou (thetikh, mikroteri apo %d): ", CENTER );
		fgets( input, 255+1, stdin );	/* read input string from user*/

		r = atoi(input);		/* convert input string to int */
		if ( r < 0 || r > CENTER ) {
			puts( "EDOSES MH epitreptes diastaseis.");
			continue;
		}
		break;
	}

	/* draw the circle into imageOut */
	for (i = -r; i < r; i++)
	{
		int height = sqrt(r * r - i * i);
		for (j = -height; j < height; j++)
		{
			x = i + CENTER;
			y = j + CENTER;
			imageOut[x][y] = 64;
		}
	}
#endif

	// -----------------------------------------------------------
	// EUAEEAO A?AIANAAOEAO AEEIIAO - OAEIO
	// -----------------------------------------------------------

	// A?IECEAOOC AEEIIAO AIIAIO OOI AEOEI
	// -----------------------------------------------------------

	/* save data from imageOut to fpOut */
	if ( (fpOut = fopen(FNAME_OUT,"wb")) != NULL )
	{
		for (i = 0; i < ROWS; i++)
		{
			for (j = 0; j < COLS; j++)
			{
				// was: fprintf(fpOut, "%c", imageOut[i][j]);
				fputc( image[i][j], fpOut );
			}
		}
	}
	else
	{
		printf("Error saving image.");
	}
	fclose(fpOut);

}

 

ΥΓ. Γιατί χρησιμοποιείς δυο image buffers? Μπορείς να κάνεις τη δουλειά σου με ένα, άρα εξοικονομώντας μνήμη.

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

@iex Eγω διαφωνω οταν έχεις μια εντολη σαν σωμα των for ή if κτλπ να βάζεις extra braces... εμενα προσωπικα με μπερδευει. To statement οταν ειναι ενα μπορει να υπάρχει και χωρις αγκυλες ενω αν ειναι περισσοτερα του ενος ειναι ουσιαστικα ενα compound statement και τοτε τοποθετεις αγκυλες επειδη ουσιαστικα εχεις μια ομαδα εντολων και θελεις ο μεταγλωτιστης να τις λαβει υποψιν του σαν μια  μονη εντολη.


 


Ευχαριστώ για τα καλά σας λόγια για τον κώδικα, αλλά θα ήθελα να καταστήσω σαφές πως τον έγραψα για να ενισχύσω την άποψη των παιδιών που υποστηρίζουν πως στην προκειμένη περίπτωση δυσχεραίνει την ανάγνωση του παραδείγματος.
 
Γενικώς, ένα πολύ μεγάλο μέρος του refactoring (αν όχι όλο) στηρίζεται στην προσθήκη έξτρα abstraction levels στον κώδικα (χρησιμοποιείται και ο όρος levels of indirection). Κάθε νέο τέτοιο επίπεδο απομακρύνεται ολοένα και περισσότερο από τις λεπτομέρειες της υλοποίησης, οι οποίες κατά την άποψή μου ήταν αυτές που ενδιαφερόταν να διαβάσει εξαρχής ο topic-starter αυτού του νήματος.
 
Ο κώδικας χρησιμοποιεί (συνειδητά) και εκτεταμένο error-checking, το οποίο δυσχεραίνει ακόμα περισσότερο τον εντοπισμό της υλοποίησης αυτής κάθε αυτής. Παρεμπιπτόντως, θα μπορούσα να βάλω κι άλλα abstractions στον κώδικα, π.χ. αντί για κύκλο θα μπορούσα ας πούμε να χρησιμοποιήσω μια πιο γενική έννοια (ας πούμε κλάση) π.χ. shape με τον κύκλο να αποτελεί subclassed αντικείμενό της, κλπ, κλπ. Προσθέτοντας ακόμα ένα abstraction level χωρίζοντας τον κώδικα σε αρχεία όπως προτείνεις φίλε jsiskos θα επιδείνωνε ακόμα περισσότερο το readability.
 
Επίσης κατά κανόνα το refactoring λειτουργεί εις βάρος των επιδόσεων, κάτι που σε συγκεκριμένες κατηγορίες λογισμικού δεν είναι επιθυμητό.
 
Αυτό που θέλω να καταλήξω είναι πως το refactoring είναι καλό πράγμα γενικώς, αλλά όπως σχεδόν όλα τα πράγματα στον προγραμματισμό δεν αποτελεί πανάκεια... πρέπει να σταθμιστούν τα + και τα - του ή/και ο βαθμός εφαρμογής του, ανάλογα την περίσταση ;)

 

 

 

Like so many other things in life be used in moderation :P

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

goto; απαπα πράγματα του διαβόλου!!!



@iex Eγω διαφωνω οταν έχεις μια εντολη σαν σωμα των for ή if κτλπ να βάζεις extra braces... εμενα προσωπικα με μπερδευει. To statement οταν ειναι ενα μπορει να υπάρχει και χωρις αγκυλες ενω αν ειναι περισσοτερα του ενος ειναι ουσιαστικα ενα compound statement και τοτε τοποθετεις αγκυλες επειδη ουσιαστικα εχεις μια ομαδα εντολων και θελεις ο μεταγλωτιστης να τις λαβει υποψιν του σαν μια  μονη εντολη.


 

 

Like so many other things in life be used in moderation :P

 

Κάπου εγώ νομίζω ότι μπαίνει και ένα θέμα συνήθειας στην κατανόηση κώδικα. Εδώ υπάρχει κόσμος που παθαίνει εμπλοκή όταν αλλάζεις το που βάζεις τα braces(μετά το function vs στην επόμενη γραμμή).

 

Δηλαδή αν έχω ένα if statement με μια μόνο εντολή κάλλιστα θα το έγραφα.

 

if (x == 1) y = x;

 

Μια χαρά readable είναι. Για λόγους consistency όμως, και για να μην ξαναπηγαίνω και προσθέτω braces αν αλλάξω γνώμη το γράφω πάντα:

if (x == 1) {
  y = x;
}

επίσης έχεις και το θέμα του πως βάζεις τα braces. Δηλαδή:

if (x == 1)
  y = x;
else 
  y = 2;

vs 

if (x == 1) {
  y = x;
} else {
  y = 2;
} 

Οπότε αν γράψεις με αυτό το style καλό είναι να είσαι consistent με τα braces.

 

Σε σχέση με τη C++ κάτι :

std::vector<std::vector<int>>> v;

 

Που τα βλέπουν κάποιοι και παθαίνουν εμπλοκή,  ενώ εγώ το έχω συνηθίσει και δεν με ενοχλεί.

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

To να μην πηγαινεις να τις προσθεσεις αν αλλαξεις γνωμη μετα οκ μπορω να το καταλαβω αλλα γιατι consistency? Ως προς ποιον / τι θεμα συνεπειας δηλαδη? εκτος και αν δινεις αλλο νοημα στην λεξη και δεν σε εχω καταλαβει.

 

 Κοιτα εγω το εχω μαθει ετσι ... δηλαδη οταν μαθαινει καποιος την if ή την for θα πρεπει να καταλαβει ποτε χρειαζονται braces και ποτε οχι. Ε ειναι αυτο που εγραψα βασικα.... εφοσον τα { ... } ειναι για compound statements και το ενα statement δεν ειναι compound τι νοημα εχει ?

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

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

 

if ()
{
   statement;
}
else
{
   statement;
}

if ()
   statement;
else 
   statement;

 

Οπότε δεν αλλάζει και τίποτα ουσιαστικά

 

ενώ στην άλλη περίπτωση έχεις συνηθίσει το else να βρίσκεται πάντα 2 space πιο μέσα απο το if, οπότε αν το κάνεις αυτό σε ένα πολύπλοκο if-else statement με πολλά nested if-else θα χάσεις τη μπάλα αν δεν κρατίσεις το consistency.

 

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

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

 

Δεν το έκανα compile αλλά νομίζω πρέπει να είναι οκ...

 

 

 

// ---------------------------------------------------------------
//
// ---------------------------------------------------------------

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

// ---------------------------------------------------------------
// OOAEANA OOIE?AEA OUI AEEIIUI AEOIAIO-AIIAIO
// ---------------------------------------------------------------
#define FNAME_IN	"test_image.raw"// Aeaanii?/uiiia an?a?io aeouaio
#define FNAME_OUT	"erotima2.raw" 	// Aeaanii?/uiiia an?a?io aiuaio
#define ROWS		256		// ?e?eio anaii?i aeeuiao aeouaio
#define COLS		256		// ?e?eio ooce?i aeeuiao aeouaio
#define GREYLEVELS	256		// ?e?eio a?i?n?oaui aeeuiao
#define CENTER		128
#define BG_COLOR	225
// ---------------------------------------------------------------
// OAEIO ?NIOAEINEOIIO OOIE?AEUI AEEIIUI
// ---------------------------------------------------------------


int main( void )
{
	// ACEUOAEO IAOAAECOUI
	// -----------------------------------------------------------

	// ??iaeao aeeuiui
	unsigned char imageIn[ROWS][COLS]  = { {0,0} };
	unsigned char imageOut[ROWS][COLS] = { {0,0} };

	// An?a?a
	FILE *fpIn = NULL, *fpOut = NULL;	/* input & output file pointers */

	// IaoaaecoYo aaiee?o ?n?oauo
	int i=0, j=0;
	int x,y, r;				/* (x,y) point at perimeter, r = radius */


	// -----------------------------------------------------------
	// OAEIO ACEUOAUI IAOAAECOUI
	// -----------------------------------------------------------

	// OINOUOC AEEIIAO AEOIAIO A?I AEOEI
	// -----------------------------------------------------------

	/* read data from fpIn to imageIn */
	if ( (fpIn = fopen(FNAME_IN,"rb")) != NULL )
	{
		for (i=0; i < ROWS; i++)
		{
			for (j=0; j < COLS; j++)
			{
				// was: fscanf(fpIn, "%c", &imageIn[i][j]);
				imageIn[i][j] = (unsigned char)fgetc(fpIn);
			}
		}
	}
	else
	{
		printf("Error loading image.");
	}
	fclose(fpIn);

	// -----------------------------------------------------------
	// EUAEEAO A?AIANAAOEAO AEEIIAO - AN?C
	// -----------------------------------------------------------

	memset( &imageOut, BG_COLOR, sizeof(imageOut) );

#if 0	/* DISABLED: des parakatw sto #else */

elegxos:
	printf ("Dose tin akrina tou kuklou (prosoxi na einai mikroteri apo 128): ");
	scanf ("%d",&r);

	if (r > CENTER)
	{
		printf ("EDOSES MH epitreptes diastaseis. \n ");
		goto elegxos;
	}
	else
	{
		for (i= -r; i< r; i++)
		{
			int height = sqrt(r * r - i * i);
			for (j = -height; j < height; j++)
			{
				x = i + CENTER;
				y = j + CENTER;
				imageOut[x][y] = 64;
			}
		}
	}
#else
	/* keep asking until valid radius is entered */
	for (;
	{
		char input[255+1] = {'\0'};	/* input string */
		printf( "Akrina kuklou (thetikh, mikroteri apo %d): ", CENTER );
		fgets( input, 255+1, stdin );	/* read input string from user*/

		r = atoi(input);		/* convert input string to int */
		if ( r < 0 || r > CENTER ) {
			puts( "EDOSES MH epitreptes diastaseis.");
			continue;
		}
		break;
	}

	/* draw the circle into imageOut */
	for (i = -r; i < r; i++)
	{
		int height = sqrt(r * r - i * i);
		for (j = -height; j < height; j++)
		{
			x = i + CENTER;
			y = j + CENTER;
			imageOut[x][y] = 64;
		}
	}
#endif

	// -----------------------------------------------------------
	// EUAEEAO A?AIANAAOEAO AEEIIAO - OAEIO
	// -----------------------------------------------------------

	// A?IECEAOOC AEEIIAO AIIAIO OOI AEOEI
	// -----------------------------------------------------------

	/* save data from imageOut to fpOut */
	if ( (fpOut = fopen(FNAME_OUT,"wb")) != NULL )
	{
		for (i = 0; i < ROWS; i++)
		{
			for (j = 0; j < COLS; j++)
			{
				// was: fprintf(fpOut, "%c", imageOut[i][j]);
				fputc( image[i][j], fpOut );
			}
		}
	}
	else
	{
		printf("Error saving image.");
	}
	fclose(fpOut);

}

 

ΥΓ. Γιατί χρησιμοποιείς δυο image buffers? Μπορείς να κάνεις τη δουλειά σου με ένα, άρα εξοικονομώντας μνήμη.

 

Χρησιμοποίησα 2 image buffers κατευθείαν από προηγούμενη άσκηση που επεξεργαζόμουν την αρχική εικόνα και την αποθήκευα με νέο όνομα διατηρώντας το αρχικό αρχείο.

goto; απαπα πράγματα του διαβόλου!!!

 

 

Κάπου εγώ νομίζω ότι μπαίνει και ένα θέμα συνήθειας στην κατανόηση κώδικα. Εδώ υπάρχει κόσμος που παθαίνει εμπλοκή όταν αλλάζεις το που βάζεις τα braces(μετά το function vs στην επόμενη γραμμή).

 

Δηλαδή αν έχω ένα if statement με μια μόνο εντολή κάλλιστα θα το έγραφα.

 

if (x == 1) y = x;

 

Μια χαρά readable είναι. Για λόγους consistency όμως, και για να μην ξαναπηγαίνω και προσθέτω braces αν αλλάξω γνώμη το γράφω πάντα:

if (x == 1) {
  y = x;
}

επίσης έχεις και το θέμα του πως βάζεις τα braces. Δηλαδή:

if (x == 1)
  y = x;
else 
  y = 2;

vs 

if (x == 1) {
  y = x;
} else {
  y = 2;
} 

Οπότε αν γράψεις με αυτό το style καλό είναι να είσαι consistent με τα braces.

 

Σε σχέση με τη C++ κάτι :

std::vector<std::vector<int>>> v;

 

Που τα βλέπουν κάποιοι και παθαίνουν εμπλοκή,  ενώ εγώ το έχω συνηθίσει και δεν με ενοχλεί.

 

goto γιατί όπως και να έχει ο χρήστης πρέπει να δώσει μία τιμή και αυτό μου ήρθε εκείνη την στιγμή όσο "λανθασμένος τρόπος σκέψης" και αν είναι... επίσης δεν είμαι και expert!!! φοιτητής είμαι που υλοποιώ βασικά πράγματα στα πλαίσια της σχολής...

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

@iex Eγω διαφωνω οταν έχεις μια εντολη σαν σωμα των for ή if κτλπ να βάζεις extra braces... εμενα προσωπικα με μπερδευει. To statement οταν ειναι ενα μπορει να υπάρχει και χωρις αγκυλες ενω αν ειναι περισσοτερα του ενος ειναι ουσιαστικα ενα compound statement και τοτε τοποθετεις αγκυλες επειδη ουσιαστικα εχεις μια ομαδα εντολων και θελεις ο μεταγλωτιστης να τις λαβει υποψιν του σαν μια  μονη εντολη.

Κάπου εγώ νομίζω ότι μπαίνει και ένα θέμα συνήθειας στην κατανόηση κώδικα. Εδώ υπάρχει κόσμος που παθαίνει εμπλοκή όταν αλλάζεις το που βάζεις τα braces(μετά το function vs στην επόμενη γραμμή).

To να μην πηγαινεις να τις προσθεσεις αν αλλαξεις γνωμη μετα οκ μπορω να το καταλαβω αλλα γιατι consistency? Ως προς ποιον / τι θεμα συνεπειας δηλαδη? εκτος και αν δινεις αλλο νοημα στην λεξη και δεν σε εχω καταλαβει.

Όπως είπε και ο ZAKKWYLDE είναι θέμα συνήθειας αλλά η συνέπεια δεν είναι ασήμαντος λόγος. Δοκίμασε να διαβάσεις ένα κώδικα 1500 γραμμών με 4 διαφορετικά στυλ και θα δεις ότι είναι κουραστικό.

 

Από εκεί και πέρα συνήθως θεωρείται "σωστό" όταν κάτι δεν παρέχει χρήσιμες πληροφορίες να μην μπαίνει. Για παράδειγμα στον κώδικα "i++; /* increase i by one */" το σχόλιο δεν σου δίνει τίποτα οπότε είναι άχρηστο. Το ίδιο γίνεται και με τις αγκύλες σε μονές δηλώσεις (και ειδικά σε allman στυλ τρώνε 2 γραμμές).

επίσης έχεις και το θέμα του πως βάζεις τα braces. Δηλαδή:

if (x == 1)
  y = x;
else 
  y = 2;
vs 
if (x == 1) {
  y = x;
} else {
  y = 2;
} 
Οπότε αν γράψεις με αυτό το style καλό είναι να είσαι consistent με τα braces.

 

 

Αυτά τα στυλ θεωρούνται αποδεχτά και τα δύο και είναι θέμα συνήθειας (και συνέπειας) ποιο χρησιμοποιεί κανείς. Αυτό που θεωρείται απαράδεχτο από πολλούς είναι το παρακάτω:
if (x == 1)
  y = x;
  else {
  y = 2;
  k = 5;
} 
Όταν στο ένα branch χρειάζονται αγκύλες θεωρείται σωστό να μπαίνουν αγκύλες και στα υπόλοιπα branches. Και αυτό όμως ακόμη σηκώνει συζήτηση γιατί κάποιοι δεν το δέχονται.

 

 

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

 

 

if ()
{
   statement;
}
else
{
   statement;
}

if ()
   statement;
else 
   statement;
Οπότε δεν αλλάζει και τίποτα ουσιαστικά

 

 

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

Κοιτα εγω το εχω μαθει ετσι ... δηλαδη οταν μαθαινει καποιος την if ή την for θα πρεπει να καταλαβει ποτε χρειαζονται braces και ποτε οχι. Ε ειναι αυτο που εγραψα βασικα.... εφοσον τα { ... } ειναι για compound statements και το ενα statement δεν ειναι compound τι νοημα εχει ?

Κάτι που χρησιμοποιείται σπάνια αλλά ίσως αξίζει να αναφέρουμε είναι ότι οι αγκύλες δεν μπαίνουν μόνο για ομορφιά αλλά έχουν συμπεριφορά ακόμη και σε μία δήλωση. Ας δούμε ένα χαζό παράδειγμα:
#include <stdio.h>

int main(void)
{
	int k = 3;

	printf("k = %d - %p\n",k, &k);
	if (k == 3)
		int k = 5;
	printf("k = %d - %p\n",k, &k);

	return 0;
}
In function ‘main’:
σφάλμα: expected expression before ‘int’
 int k = 5;
 ^
Χάριν ευκολίας ας ξεχάσουμε ότι το %p χρειάζεται δείκτη σε void. Βλέπουμε ότι το παραπάνω δεν γίνεται compile επειδή δηλώνουμε για δεύτερη φορά την μεταβλητή k.
#include <stdio.h>

int main(void)
{
	int k = 3;

	printf("k = %d - %p\n",k, &k);
	if (k == 3) {
		int k = 5;
	}
	printf("k = %d - %p\n",k, &k);

	return 0;
}
In function ‘main’:
προειδοποίηση: unused variable ‘k’ [-Wunused-variable]
 int k = 5;
     ^
Έγινε compile κανονικά χωρίς κανένα πρόβλημα. Αν προσθέσω μέσα στην αγκύλες ακόμη ένα ίδιο printf θα δούμε
k = 3 - 0xec
k = 5 - 0xe8
k = 3 - 0xec
  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπράβο φίλε μου που ασχολήθηκες, αλλά όλα στη main; Πολύ κακή προγραμματιστική συνήθεια ακόμα και για το πιο απλό πρόγραμμα!

 

Όταν πρόκειται για κάτι τόσο απλό επέτρεψε μου να διαφωνήσω μαζί σου.

 

Θα πάω και γω με τον Directx. jsiskos, παρόλο που γενικά συμφωνώ με το πνεύμα αυτού που γράφεις, όταν γράφεις ένα scratch program των 20 γραμμών το οποίο ξέρεις ότι στη συνέχεια θα το "πετάξεις", δε χρειάζεται να το κουράζεις πολύ. Αυτό βέβαια προϋποθέτει ότι μιλάμε για κάτι που αν αποφασίσεις να το κάνεις "το κάνεις και στον ύπνο σου", και δεν είναι δικαιολογία για κάποιον που βασικά δεν έχει μάθει να το κάνει.

 

Αν μου επιτρέπεις, η τοποθέτησή σου μου φέρνει στο μυαλό το "οι φοιτητές ιατρικής σε κάθε διάγνωση διαγιγνώσκουν την ασθένεια που διδάχτηκαν την προηγούμενη βδομάδα". Χωρίς παρεξήγηση, we 've all been there.

 

 

@iex Eγω διαφωνω οταν έχεις μια εντολη σαν σωμα των for ή if κτλπ να βάζεις extra braces... εμενα προσωπικα με μπερδευει. To statement οταν ειναι ενα μπορει να υπάρχει και χωρις αγκυλες ενω αν ειναι περισσοτερα του ενος ειναι ουσιαστικα ενα compound statement και τοτε τοποθετεις αγκυλες επειδη ουσιαστικα εχεις μια ομαδα εντολων και θελεις ο μεταγλωτιστης να τις λαβει υποψιν του σαν μια  μονη εντολη.

Like so many other things in life be used in moderation :P

 

if(age > 0)
    if (age > 18) printf("Ενήλικας");
else if (age < 0) printf("Μας δουλεύεις?");

 

Το παράδειγμα δεν είναι και το καλύτερο αλλά νομίζω κάνει το point που πρέπει.

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

 φοιτητής είμαι που υλοποιώ βασικά πράγματα στα πλαίσια της σχολής...

 

Θα σε συμβούλευα ως βασικό πράγμα να ξεχάσεις άμεσα ότι υπάρχει το goto :P. Προσπάθησε να κάνεις το ίδιο με μια while. Αργότερα τέτοια loops θα τα κάνεις συνέχεια για input checks οπότε καλό είναι να τα συνηθίσεις απο τώρα.

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

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

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

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

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

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

Σύνδεση

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

Συνδεθείτε τώρα
  • Δημιουργία νέου...