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

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

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


#include <stdio.h>
#include <string.h>
char pr(char x[80])
{
char y[80], *p1, *p2;
int i, o,n;
n = strlen(x);
o = n - 1;
for (i = 0; i <n; i++)
{
p1 = &x;
y[o] = *p1;
o--;
}
for (i = 0; i < n; i++)
x = y;
return (x);
}

 
main()
{
char f[80], x, c[80];
int i, y = 0, n = 0;
printf("Grapse mia grammatoseira\n");
gets(f);
scanf("%c", &x);
n = strlen(f);
for (i = 0; i < n; i++)
{
if (f == x)
y++;
};
printf("to sumvolo emfanizetai %d fores\n", y);
puts(f);
                 c[80]= pr(f);
puts© ;
}
Δημοσ. (επεξεργασμένο)

 

 

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

char pr(char x[80])
{
	char y[80], *p1, *p2;
	int i, o,n;
	
	n = strlen(x);
	o = n - 1;
	
	for (i = 0; i < n; i++) {
		p1 = &x[i];
		y[o] = *p1;
		o--;
	}
	for (i = 0; i < n; i++)
		x[i] = y[i];
	
	return (x);
}

 
main()
{
	char f[80], x, c[80];
	int i, y = 0, n = 0;

	printf("Grapse mia grammatoseira\n");
	gets(f);
	scanf("%c", &x);
	n = strlen(f);

	for (i = 0; i < n; i++) {
	        if (f[i] == x)
	        y++;
	}

	printf("to sumvolo emfanizetai %d fores\n", y);
	puts(f);
	c[80]= pr(f);
	puts(c);
}

 

 

 

Αρχικά έχω να κάνω κάποιες vital παρατηρήσεις όσον αφορά τον κώδικα.

 

Αναγνωσιμότητα

Το πρώτο βήμα για ένα αναγνώσιμο πρόγραμμα είναι η στοίχιση.

Όπως βλέπεις παραπάνω ένα σωστά στοιχισμένο πρόγραμμα,

είναι πιο ευχάριστο στο μάτι και αυτό είναι καλό για διάφορους λό-

γους. Ένας λόγος είναι ότι θέλεις να ξέρεις πως δουλεύει το πρό-

γραμμά σου και μετά από ένα μήνα. Δε θες να κάθεσαι να σπατα-

λάς χρόνο διαβάζοντάς το για να καταλάβεις τί στο καλό έκανες τό-

τε. Εδώ θα έρθουν να κολλήσουν οι επόμενες παρατηρήσεις που

αφορούν την αναγνωσιμότητα. Πρέπει να βάζεις ονόματα τα οποία

είναι ευκολοδιάβαστα και να έχουν νόημα. Μονογραμματισμοί, δι-

γραμματισμοί και τέτοιου είδους ονοματισμοί προκαλούν μόνο

#$#%$%@. Θα βάζεις λέξεις. Τέλος κάνε ορθή χρήση σχολίων

(0 && 1 && 2). Τα τρία αυτά άρθρα λένε αρκετά για να ξεκινήσεις.

 

EDIT: Στην αναγνωσιμότητα θα σου πρότεινα (από προσωπικό

πόνο) να βάζεις curled braces σε κάθε περίπτωση ακόμη κι αν

πρόκειται για μία εντόλη κάτω από την if ή την for.

 

C

Κάνουμε compile με τα Warnings ενεργοποιημένα: 

gcc -g3 -Wall -Wextra -o my_exe my_file.c
        ~^~~~~~^~~~~~

Η main πλέον επιστρέφει έναν integer οπότε θα την γράφεις έτσι:

int main(void)   // or int main(int argc, char *argv[])
{
        // ....

        return 0;
}

H gets είναι κακή. Αν δεις εδώ:

 

Never use gets(). Because it is impossible to tell without knowing the data

in advance how many characters gets() will read, and because gets() will

continue to store characters past the end of the buffer, it is extremely dangerous

to use. It has been used to break computer security. Use fgets() instead.

 

Συγκεκριμένα έχει χρήση της για ένα είδος exploitation που ονομάζεται

buffer overflow. Μπορείς να δεις εδώ ένα παράδειγμα σε C.

Είναι πολύ σημαντικό αυτό το σημείο. Πρέπει να δώσεις βάση όσο είναι

νωρίς. Πολλοί μεγαλώνουν, δουλεύουν σε σημαντικές θέσεις και δεν

τα προσέχουν αυτά. Πχ πέρυσι ένα παιδάκι hack-αρε καταλάθως το

Xbox Online λογαριασμό του πατέρα του κάνοντας buffer overflow.

 

Το πρόγραμμά σου

Γρήγορη εξήγηση:

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

Συγκεκριμένα επιστρέφει τη διεύθυνση του πίνακα x.  Κάνοντας μετά

εσύ αυτό: c[80] = pr(f), πας και αναθέτεις τη διεύθυνση του x στη θέση

80 του πίνακα c. Αν ενεργοποιούσες τα warnings θα το είχες καταλάβει

αυτό. Άρα πρέπει να παίξεις εκεί.

 

Προτεινόμενη λύση:

 

 

void pr(char *dest, char x[80])
{
	char y[80], *p1, *p2;
	int i, o,n;

	n = strlen(x);
	o = n - 1;

	for (i = 0; i < n; i++) {
		p1 = &x[i];
		dest[o] = *p1;
		o--;
	}
}

int main(void)
{
	...

        if (NULL == (c = malloc(81 * sizeof(char))) {
                puts("Memory allocation error. Exiting.");
                exit(EXIT_FAILURE);
        }
	pr(c, f);
	puts(c);

	return 0;
}

 

 

Να φτιάξεις τη συνάρτησή σου ώστε να παίρνει ένα δείκτη

σε μνήμη δεσμευμένη για το αποτέλεσμα και να αναθέτει

κατευθείαν σε αυτή. Αν κάνεις τις παραπάνω μετατροπές

το πρόγραμμα θα δουλέψει, αλλά θέλει αρκετό patch-άρισμα

για να είναι σωστό σύμφωνα με τα κριτήρια που ανέφερα

παραπάνω και δη σε αυτό με το buffer overflow. Κάποια

στιγμή αργότερα, αν βρω λίγο χρόνο θα σου ανεβάσω και

μία δικιά μου ολοκληρωμένη εκδοχή.

Επεξ/σία από gon1332
Δημοσ.

Ορίστε και μία δική μου εκδοχή. Πολλά σημεία θα μπορούσαν

να είναι διαφορετικά, αλλά προσπάθησα να μην μπω στον πει-

ρασμό:

 

 

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

#define MAX_INPUT_LENGTH 80

void string_reverse(char *dst, const char *src)
{
    if (src == NULL) {
        return;
    }

    const char *src_start = src;
    char *dst_end = dst + strlen(src)-1;
    while ((*dst_end-- = *src_start++)) {
        ;
    }
}


int main(void)
{
    /* ===  User input  =============================== */
    char input[MAX_INPUT_LENGTH+1] = { '\0' };
    printf("Please enter a string: ");
    fgets(input, MAX_INPUT_LENGTH, stdin);  // notice that fgets includes '\n'

    // ΕΔΩ ΠΕΡΙΜΕΝΩ ΤΟΝ MIGF1 ΝΑ ΔΩΣΕΙ ΛΙΓΗ ΧΑΡΑ. ΤΟ ΑΦΗΝΩ ΓΙΑ ΣΕΝΑ. 

    size_t input_length = strlen(input);
    input[--input_length] = '\0';       // erase '\n' from input string *and*
                                        // therefore decrease the string length

    char char_to_search;
    printf("Please enter a character to search for: ");
    scanf("%c", &char_to_search);


    /* ===  Search for *char_to_search* in *input*  === */
    size_t occurrences = 0;
    for (size_t i = 0; i < input_length; i++) {
        occurrences += (char_to_search == input[i]);
    }

    printf("\nCharacter \'%c\' appears %lu times in \"%s\".\n", char_to_search,
                                                                occurrences,
                                                                input);

    /* ===  Reverse the input string  ================= */
    char *reversed_input = malloc((input_length+1) * sizeof(char));
    if (NULL == reversed_input) {
        puts("malloc failed: Aborting execution.\n");
        exit(EXIT_FAILURE);
    }

    string_reverse(reversed_input, input);

    printf("\nReversed \"%s\" looks like \"%s\".\n", input, reversed_input);

    return 0;
}
 

 

 

 

Ορίστε κι ένα ενδεικτικό output:

Please enter a string: Nipson anomimata mh monan opsin
Please enter a character to search for: i

Character 'i' appears 3 times in "Nipson anomimata mh monan opsin".

Reversed "Nipson anomimata mh monan opsin" looks like "nispo nanom hm atamimona nospiN".
Δημοσ.

Ευχαριστώ..απλά είναι άσκηση για την σχολή και δεν έχουμε μάθει πολύπλοκα οπως αυτα που εχεις κάνει και δεν τα καταλαβαίνω ολα...μεχρι #include stdio Και string εχουμε κάνει..έχω συγκεκριμένες οδηγίες απο την άσκηση..και εχω κολλήσει στο κομμάτι του να καλώ την συνάρτηση με την βοήθεια δεικτών..(η αναστροφη γίνεται όπως θέλει ο καθένας) και έχω θέμα με την εντολη c[80]=pr(f);καμια ιδέα? :/
γιατι οταν την συναρτηση την ετρεξα ξεχωριστα σε αλλο προγραμμα (με 1-2 εντολες παραπανω οπως gets) και τη main σε άλλο όλα δούλευαν ρολόι..αλλα όταν τα ένωσα...η συνάρτηση ήταν σαν να μήν υπήρχε

Δημοσ.

Ευχαριστώ..απλά είναι άσκηση για την σχολή και δεν έχουμε μάθει πολύπλοκα οπως αυτα που εχεις κάνει και δεν τα καταλαβαίνω ολα...μεχρι #include stdio Και string εχουμε κάνει..έχω συγκεκριμένες οδηγίες απο την άσκηση..και εχω κολλήσει στο κομμάτι του να καλώ την συνάρτηση με την βοήθεια δεικτών..(η αναστροφη γίνεται όπως θέλει ο καθένας) και έχω θέμα με την εντολη c[80]=pr(f);καμια ιδέα? :/

Αν δεις το την γρήγορη εξήγηση που δίνω καθώς και την προτεινόμενη λύση

θα καταλάβεις πως αυτή η εντολή κάνει κάτι εντελώς άσχετο από αυτό που

θέλεις να κάνεις. Είναι βασισμένη στο πρόβλημά σου.

 

Έχετε κάνει δυναμική δέσμευση μνήμης;

Δημοσ.

οχι δεν έχουμε κάνει ουτε την εντολη fgets ήξερα

απλά πανω στον τροπο που την έχω χτύσει εκτός από την gets τι αλλο έχει λαθος..πως διορθώνω το c[80]=pr(f)

Δημοσ.

Το μόνο που μένει να διορθώσεις τότε είναι η δήλωση του c,

η κλήση της συνάρτησης και το signature της συνάρτησης:

 

 

#include <stdio.h>
#include <string.h>
 
char *pr(char x[80])
{
	char y[80], *p1;
	int i, o,n;
	
	n = strlen(x);
	o = n - 1;
	
	for (i = 0; i < n; i++) {
		p1 = &x[i];
		y[o] = *p1;
		o--;
	}
	for (i = 0; i < n; i++)
		x[i] = y[i];
	
	return (x);
}
 
 
int main()
{
	char f[80], x, *c;
	int i, y = 0, n = 0;
 
	printf("Grapse mia grammatoseira\n");
	gets(f);
	scanf("%c", &x);
	n = strlen(f);
 
	for (i = 0; i < n; i++) {
	        if (f[i] == x)
	                y++;
	}
 
	printf("to sumvolo emfanizetai %d fores\n", y);
	puts(f);
	c = pr(f);
	puts(c);
	
	return 0;
} 

 

 

Δημοσ.

Το μόνο που μένει να διορθώσεις τότε είναι η δήλωση του c,

η κλήση της συνάρτησης και το signature της συνάρτησης:

 

 

#include <stdio.h>
#include <string.h>
 
char *pr(char x[80])
{
	char y[80], *p1;
	int i, o,n;
	
	n = strlen(x);
	o = n - 1;
	
	for (i = 0; i < n; i++) {
		p1 = &x[i];
		y[o] = *p1;
		o--;
	}
	for (i = 0; i < n; i++)
		x[i] = y[i];
	
	return (x);
}
 
 
int main()
{
	char f[80], x, *c;
	int i, y = 0, n = 0;
 
	printf("Grapse mia grammatoseira\n");
	gets(f);
	scanf("%c", &x);
	n = strlen(f);
 
	for (i = 0; i < n; i++) {
	        if (f[i] == x)
	                y++;
	}
 
	printf("to sumvolo emfanizetai %d fores\n", y);
	puts(f);
	c = pr(f);
	puts(c);
	
	return 0;
} 

 

 

se xilioeuxaristw file!!! doulevei! :) :) :) :)

Δημοσ.

se xilioeuxaristw file!!! doulevei! :) :) :) :)

Τίποτα. ;)

 

Θα σου πρότεινα όμως να δώσεις προσοχή σε αυτά

που σου είπα παραπάνω καθώς είναι πολύ σημαντικά.

 

Καλή πρωτοχρονιά!

  • Like 1
Δημοσ.

Ορίστε και μία δική μου εκδοχή. Πολλά σημεία θα μπορούσαν

να είναι διαφορετικά, αλλά προσπάθησα να μην μπω στον πει-

ρασμό:

#define MAX_INPUT_LENGTH 80
...
int main(void)
{
    /* ===  User input  =============================== */
    char input[MAX_INPUT_LENGTH+1] = { '\0' };
    printf("Please enter a string: ");
    fgets(input, MAX_INPUT_LENGTH, stdin);  // notice that fgets includes '\n'

    // ΕΔΩ ΠΕΡΙΜΕΝΩ ΤΟΝ MIGF1 ΝΑ ΔΩΣΕΙ ΛΙΓΗ ΧΑΡΑ. ΤΟ ΑΦΗΝΩ ΓΙΑ ΣΕΝΑ. 

    size_t input_length = strlen(input);
    input[--input_length] = '\0';       // erase '\n' from input string *and*
                                        // therefore decrease the string length
 ...

 

Χεχε :) Άντε να μη σου χαλάσω το χατήρι.

 

Έχεις δυο μικρές αβλεψίες στον κώδικα.

 

1. Κόβεις τον strlen()-1 χαρακτήρα του input, ακόμα κι όταν δεν είναι '\n' (όταν δηλαδή επιχειρηθεί overflow του input στην είσοδο). Δηλαδή, δεν ελέγχεις αν όντως υπάρχει '\n' μέσα στο input πριν το αντικαταστήσεις με '\0'.

 

2. Στην fgets() κόβεις έναν χαρακτήρα από το full-potential του input string. Η fgets() κόβει έτσι κι αλλιώς έναν χαρακτήρα από το νούμερο που της περνάς ως MAX_INPUT (για να προσθέσει τον '\0' στο τέλος), οπότε στον κώδικά σου θα χρησιμοποιήσει MAX_INPUT-1 χαρακτήρες, ενώ σύμφωνα με τον ορισμό του input που κάνεις, θα μπορούσε να χρησιμοποιήσει MAX_INPUT.

 

Μια καλύτερη υλοποίηση (η χρήση προσωρινού δείκτη δεν είναι απαραίτητη, απλώς βολεύει εμένα καλύτερα):

#define MAX_INPUT (80+1)
...
char input[MAX_INPUT] = { '\0' };
...
fgets( input, MAX_INPUT, stdin );
char *cp = strchr(input, '\n');  /* returns a pointer to the 1st '\n' found in input */
if ( cp ) {                      /* or NULL if no '\n' was found */
  *cp = '\0';
}
...
Το πρόβλημα είναι πως η fgets() διατηρεί το '\n' (δηλαδή το τελικό ENTER που πατάει ο χρήστης στην είσοδο) μέσα στο input (και αμέσως μετά βάζει το '\0').

 

ΕΚΤΟΣ αν αυτό που πληκτρολογεί ο χρήστης στην είσοδο έχει μήκος (σε χαρακτήρες) μεγαλύτερο από MAX_INPUT-1. Σε αυτή την περίπτωση, η fgets() βάζει μέσα στο input τους πρώτους MAX_INPUT-2 χαρακτήρες από αυτούς που πληκτρολόγησε ο χρήστης, και στη θέση MAX_INPUT-1 βάζει τον '\0'.

  • Like 2

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

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

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

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

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

Σύνδεση

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

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