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

Έλεγχος και διόρθωση σφαλμάτων στη C


voulaji

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

Δημοσ.

Έχω το εξής πρόβλημα. Η πιο κάτω συνάρτηση "enrollFemale" επιτρέπει την εγγραφή μόνο φοιτητριών σε ένα Πανεπιστήμιο.

/*

* enrollFemale

*

* returns gender i.e. always female or negative value indicating error

*

*/

int enrollFemale(char *femaleName){

 

if (femaleName == NULL)

return(-1);

 

struct student s;

s.gender = 'f'; //only females allowed.

strncpy( s.name, femaleName, strlen(femaleName));

return(s.gender);

}

 

Το ερώτημά μου είναι το εξής:

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

Δημοσ.

#include <stdio.h>

#include <string.h>

 

struct student {

int id;

char name[4];

char gender;

};

 

/*

* enrollFemale

*

* returns gender i.e. always female or negative value indicating error

*

*/

int enrollFemale(char *femaleName){

 

if (femaleName == NULL)

return(-1);

 

struct student s;

s.gender = 'f'; //only females allowed.

strncpy( s.name, femaleName, strlen(femaleName));

return(s.gender);

}

Δημοσ.

[spam]

μονο για γυναικες????

οχι, αυτο δεν το δεχομαι, ειναι σεξιστικος ρατσισμος

αρσενικα του φορουμ ενωθειτε, διεκδηκιστε το δικαιωμα να ειστε ορισματα σε αυτη τη συναρτηση και εσεις

[/spam]

 

καταρχην, στο struct το πεδιο name χωραει μονο 4 χαρακτηρες.... επιτηδες το εκανες ετσι ή σου ξεφυγε?

και αυτο γιατι με αυτο

>     strncpy( s.name, femaleName, strlen(femaleName));

αν το femaleName ειναι μεγαλυτερου μηκους απο 4 (παααρα πολυ πιθανο) εεεεε θα γινει κατι.... καταλαβαινεις?

 

οσο για το

Το ερώτημά μου είναι το εξής:

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

το κανεις λιιιγο πιο λιανα?

Δημοσ.

Για κοίτα το πως υλοποιώ εγώ κάτι ανάλογο με την άσκηση σου. Δεν επιστρέφω το Gender απευθείας από την συνάρτηση αλλά με αναφορά το επιστρέφω μέσω από τα ορίσματα της συνάρτησης και κατόπιν ελέγχω για την τιμή του. Επίσης έχω ορίσει ένα πίνακα από δείκτες ως global που είναι στην ουσία ένα πίνακας από δείκτες που θα δείχνουν σε δομές τύπου Student. Η συνάρτηση επιστρέφει ένα δείκτη στην διέυθυνση της μνήμης όπου βρίσκεται η δομή που δεσμεύω χώρο οπότε ανακατευθύνω τον δείκτη από τον πίνακα δομών σε εκείνη την θέση και έχω λοιπόν κάθε φορά ένα δείκτη για εκείνη την θέση.

 

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

/* Structures. */

/* Student Structure. */

typedef struct _Student
{
char *stdName;
int id;
char gender;
}Student;

/* Global Structure array. */
Student *nStuds[128];

/* Exit. */
void Exit(const char *Tmsg)
{
if(Tmsg)
{
	printf("%s\n", Tmsg);
	getchar();
}
}

/* Return gender. */

Student* EnrollGender(char *femaleName, char *Gender)
{
if(!femaleName)
{
	printf("Error in name parameter:%s\n", strerror(errno));
	return NULL;
}
else
{
	/* Static index. */
	static int i = 0;
	/* Declare an empty structure. */
	Student *s = NULL;

	/* Get memory. */
	if((s = (malloc(sizeof(Student)))) == NULL)
	{
		printf("Error in memory:%s\n", strerror(errno));
		return NULL;
	}
	else
	{
		/* Init with values. */
		s->stdName = calloc(strlen(femaleName)+1, sizeof(char));
		if(!s->stdName)
			return NULL;
           /* Copy Values. */
		strcpy(s->stdName, femaleName);
		s->id = i++;
		s->gender = 'f';

		/* Save Gender. */
		*Gender = s->gender;

		/* Return. */
		return s;
	}

}
}

/* Main Code. */
int main(int argc, char* argv[])
{
char femGender = 0;
nStuds[0] = EnrollGender("Niki", &femGender);
nStuds[1] = EnrollGender("Vasw", &femGender);
if(femGender == 'f')
{
	printf("Board:\n");
	printf("%s %d %c\n", nStuds[0]->stdName, nStuds[0]->id, nStuds[0]->gender);
	printf("%s %d %c\n", nStuds[1]->stdName, nStuds[1]->id, nStuds[1]->gender);
}
else
	printf("Well its a boy....\n");
/* In any case exit. */
Exit("Hit enter to continue....");
return 0;
}

 

Εκτυπωμένα αποτελέσματα:

 

Board:

Niki 0 f

Vasw 1 f

Hit enter to continue....

Δημοσ.

Σε γενικές γραμμές κατάλαβα τις παρατηρήσεις σας και σας ευχαριστώ πολύ.

Δεν έχω όμως σαφή απάντηση για τα ερώτηματά μου.

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

2. Τι τιμή επιστρέφει η συνάρτηση όταν δεν περνάει των έλεγχο;

Δημοσ.

οι τιμες που παιρνει η συναρτηση σου ειναι ονοματα

 

πως οριζεις ενα ονομα ως ακραια τιμη?

 

σιγουρα μια τετοια ακραια τιμη ειναι η ΝULL, ή το "" ή 500 κενοι χαρακτηρες στη σειρα

 

και σε αυτες τις περιπτωσεις, πως θα ηθελες να ανταποκρινεται η συναρτηση? Τι να κανει?

 

Πρωτα σκεψου το, και μετα περναμε σε κωδικα

Δημοσ.

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

Δημοσ.

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

 

Επομένως, δεν με ενδιαφέρει για ποιούς αλλά για πόσους χαρακτήρες του string femaleName η συνάρτηση enrollFemale γυρνάει 'f'

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

 

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

 

Επομένως, δεν με ενδιαφέρει για ποιούς αλλά για πόσους χαρακτήρες του string femaleName η συνάρτηση enrollFemale γυρνάει 'f'

 

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

Αν περνάει αυτά τα test πχ τότε δεν σε νοιάζει αν το όνομα είναι πχ Niki ή Nkasd σωστά;

Με άλλα λόγια θέλεις μία συνάρτηση που να κάνει check στο femaleName για μη αποδεκτές εισόδους -> μόνο χαρακτήρες δηλαδή.

Σωστά;

Δημοσ.

H παρακάτω συνάρτηση είναι ειδική στο να ανιχνεύει πιθανά λάθη στο πως θα ήθελες να είναι ένα γυναικείο όνομα, με λίγα λόγια αν περιέχει η λέξη σου κενά, άλλα σύβολα όπως πχ(μία παρένθεση ή το !.@#$ κτλ), αριθμούς ή και παραπάνω από ALLOWED_LET γράμματα συνεχόμενα μέσα στο σώμα της επιστρέφει ένα αρνητικό αριθμό σύμφωνα με αυτά που έχω ορίσει στο enumeration. Για να καλέσεις την συνάρτηση περνάς σαν όρισμα το string και κατόπιν έχεις τις εξής επιλογές:

 

1. Για να ελέγχεις όλο το string στην δεύτερη παράμετρο περνάς το μηδέν ή το strlen(string).

2. Για να ελέγχεις n πρώτους χαρακτήρες από το string σου περνάς ένα θετικό αριθμό μικρότερο από το μέγεθος του.

 

>
typedef enum _Errors
{
OK,
NULL_INPUT = -1,
INVALID_LEN = -2,
WHITESPACE = -3,
DIGIT = -4,
BAD_SYMBOL = -5,
SIMILAR_LETTERS = -6,
ALLOWED_LET = 2
}Errors;

int CheckForInvalidInput(const char *pszInput, int pszLen)
{
/* Get the len. */
int nLen = !pszLen ? (int)strlen(pszInput) : pszLen;
/* Loop Variables. */
int i, j, nLetters = 0;
if(!pszInput)
{
	printf("Error NULL Input:%s\n", strerror(errno));
	return NULL_INPUT;
}
if(pszLen < 0 || pszLen > (int)strlen(pszInput))
{
	printf("Error Invalid Length:%s\n", strerror(errno));
	return INVALID_LEN;
}
/* Check Procedure. */
/* Loop. */
for(i = 0; i < nLen; i++)
{
	 /* Check for whitespace. */

	 if(isspace(pszInput[i]))
		return WHITESPACE;

	 /* Check for digit. */

	 if(isdigit(pszInput[i]))
		return DIGIT;

	 /* Check for non alpha character. */

	 if(!isalpha(pszInput[i]))
		return BAD_SYMBOL;

	 /* Check for a predifined number of same letters. */

	 if(i < nLen-ALLOWED_LET && pszInput[i] == pszInput[i+1])
	 {
		 j = i+1;
		 while(pszInput[j] != '\0' && pszInput[i] == pszInput[j])
			j++;
		 /* How many same letters counted. */

		 nLetters = j-i;

		 /* Return too many similar letters in the word. */

		 if(nLetters > ALLOWED_LET)
			return SIMILAR_LETTERS;
		 /* Rewind j to use again. */
		 else
			j = 0;
	 }
}
/* Return a valid word. */
return OK;
}

 

Δοκιμάστηκε σε CodeGear C++ Builder 2007 και μπορεί να περιέχει bugs. Όσα test έγιναν από εμένα πέρασαν επιτυχώς. Κάθε διόρθωση καλοδεχούμενη.

Δημοσ.

Σωστά, δεν με νοιάζει να είναι ορθογραφικά σωστή μια λέξη, (άλλωστε σε ποια γλώσσα θα δοθούν τα γράμματα ; ).

Θέλω οποιοδήποτε συνδυασμό γραμμάτων που θα περνά το συγκεκριμένο test.

Και βέβαια ποια τιμή θα μου δώσει κατόπιν η συνάρτηση.

Δημοσ.

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

Δημοσ.

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

 

>

int EnrollGender(char *femaleName)
{
....
int nRetVal = CheckForInvalidInput(femaleName, strlen(femaleName));
switch(nRetVal)
{
	case WHITESPACE:
	....
	case DIGIT:
	....
	case BAD_SYMBOL:
	....
}
....
return gender;
}

Αρχειοθετημένο

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

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