nik324 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Σου απάντησε ο defacer πως γίνεται. Την C δεν τη νοιάζει πόσα στοιχεία έχει ο πίνακάς σου (ή ακόμη και αν είναι πίνακας ή τον μεταχειρίζεσαι εσύ σαν πίνακα). Ας πάρουμε το απλό σενάριο που έχουμε ένα πίνακα ακεραίων (πχ int k[10]) και ότι ο τύπος int έχει μέγεθος 4. Όταν εσύ δήλωσες τον πίνακα δεσμεύτηκε για αυτόν μια περιοχή μνήμης και από εκεί και πέρα είναι γνωστό ότι η μεταβλητή k αντιστοιχεί στην διεύθυνση Χ. Όταν εσύ πας να προσπελάσεις το 4ο στοιχείο και γράφεις k[3] = 5, η διαδικασία που γίνεται είναι να παίρνει την διεύθυνση X που αντιστοιχεί στο 1ο στοιχείο και να προσθέτει 3 φορές 4 bytes που καταλαμβάνει ο κάθε ακέραιος. Έτσι δηλαδή προσπελαύνεις την διεύθυνση X+12. Αν γράψεις x[30] = 5, θα πάει και θα γράψει στην διεύθυνση X+120 χωρίς να νοιάζεται που αυτή η διεύθυνση είναι εκτός του πίνακά σου. Αν αυτή η περιοχή μνήμης ανήκει στο πρόγραμμά σου και έχεις δικαιώματα εγγραφής, θα γράψει εκεί κανονικά σβήνοντας ότι υπάρχει εκεί που μπορεί να είναι σημαντικό. Αν δεν έχεις δικαιώματα εγγραφής, θα βαρέσει segmentation fault. hmmm καταλαβα....δηλαδη εγώ συνεχίζω να διαχειρίζομαι τον πίνακα σαν να έχει τα στοιχεία που έχω δηλώσει
defacer Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Aυτο που εστειλα ειναι το πρόβλημα μου...δεν είναι κατι άλλο σε αλλο κώδικα Πως γινετε να μου τυπώνει στοιχειο του πίνακα που δεν υπάρχει???? Πώς γίνεται να σου τυπώνει γενικά όταν ο κώδικας δεν έχει καμία εντολή που μπορεί να τυπώσει οτιδήποτε;
imitheos Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 hmmm καταλαβα....δηλαδη εγώ συνεχίζω να διαχειρίζομαι τον πίνακα σαν να έχει τα στοιχεία που έχω δηλώσει Ναι. Εσύ θα πρέπει να φροντίσεις να διαχειρίζεσαι τόσα στοιχεία όσα έχεις δηλώσει αλλιώς θα γράψεις σε περιοχές που δεν πρέπει. Όπως αν βάλεις ένα κουτί χωρητικότητας 1 λίτρου κάτω από τη βρύση και την αφήσεις ανοιχτή για ώρες αυτή θα συνεχίσει να τρέχει άσχετα που γέμισε το κουτί, έτσι και η C θα γράψει και πέρα από τον πίνακά σου αν έτσι της πεις γιατί εμπιστεύεται τη κρίση σου.
nik324 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Πώς γίνεται να σου τυπώνει γενικά όταν ο κώδικας δεν έχει καμία εντολή που μπορεί να τυπώσει οτιδήποτε; εεε ενταξ , δεν το εγραψα στον κωδικα που ανεβασα Ναι. Εσύ θα πρέπει να φροντίσεις να διαχειρίζεσαι τόσα στοιχεία όσα έχεις δηλώσει αλλιώς θα γράψεις σε περιοχές που δεν πρέπει. Όπως αν βάλεις ένα κουτί χωρητικότητας 1 λίτρου κάτω από τη βρύση και την αφήσεις ανοιχτή για ώρες αυτή θα συνεχίσει να τρέχει άσχετα που γέμισε το κουτί, έτσι και η C θα γράψει και πέρα από τον πίνακά σου αν έτσι της πεις γιατί εμπιστεύεται τη κρίση σου. οκ καταλαβα Ευχαριστω πολύ
Star_Light Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Σου απάντησε ο defacer πως γίνεται. Την C δεν τη νοιάζει πόσα στοιχεία έχει ο πίνακάς σου (ή ακόμη και αν είναι πίνακας ή τον μεταχειρίζεσαι εσύ σαν πίνακα). Ας πάρουμε το απλό σενάριο που έχουμε ένα πίνακα ακεραίων (πχ int k[10]) και ότι ο τύπος int έχει μέγεθος 4. Όταν εσύ δήλωσες τον πίνακα δεσμεύτηκε για αυτόν μια περιοχή μνήμης και από εκεί και πέρα είναι γνωστό ότι η μεταβλητή k αντιστοιχεί στην διεύθυνση Χ. Όταν εσύ πας να προσπελάσεις το 4ο στοιχείο και γράφεις k[3] = 5, η διαδικασία που γίνεται είναι να παίρνει την διεύθυνση X που αντιστοιχεί στο 1ο στοιχείο και να προσθέτει 3 φορές 4 bytes που καταλαμβάνει ο κάθε ακέραιος. Έτσι δηλαδή προσπελαύνεις την διεύθυνση X+12. Αν γράψεις k[30] = 5, θα πάει και θα γράψει στην διεύθυνση X+120 χωρίς να νοιάζεται που αυτή η διεύθυνση είναι εκτός του πίνακά σου. Αν αυτή η περιοχή μνήμης ανήκει στο πρόγραμμά σου και έχεις δικαιώματα εγγραφής, θα γράψει εκεί κανονικά σβήνοντας ότι υπάρχει εκεί που μπορεί να είναι σημαντικό. Αν δεν έχεις δικαιώματα εγγραφής, θα βαρέσει segmentation fault. albNik αυτο που λεει ο ημιθεος μπορει να ειναι και το παρακατω > #include<stdio.h> int main(void) { int i , a[3] = {0}; for(i = 0; i < 4 ; a[i++] = 2 ) printf(" %d ", i ); return 0; } Ακριβως και αυτο το παραδειγμα δειχνει πως μπορει μια υπερχειλιση στον πινακα να γράψει πανω σε σημαντικά δεδομένα. Το i οπως και να το κανεις σαν μετρητης ειναι σημαντικο για ενα loop. Πχ εδω παράγει ατέρμονα βροχο δημιουργοντας γενικοτερο προβλημα
migf1 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 To δοκιμασα ρε συ. Αλλα μου το βγαζει κανονικα... > #include<stdio.h> #include<string.h> int main( void ) { char str1[]="hello"; char str2[]="hellom"; strcpy(str1,str2); puts(str1); return 0; } OUTPUT: > hellom Κατα τύχη δουλευει. Για αυτο και δεν μπορεσα να εχω ξεκαθαρη εικονα. @ημιθεε οκ. Δοκίμασε με: char str2[] = "sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf";
Star_Light Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 @migf1 και παλι τα ιδια... κανονικα μου το βγαζει και παλι > Copied from insomnia sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf > #include<stdio.h> #include<string.h> int main( void ) { char str1[]="hello"; char str2[]="sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf"; strcpy(str1,str2); puts("Copied from insomnia"); printf("sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf\n"); printf("%s" , str1); return 0; } Δεν θα ζαλιζα το θρεντ αμα δεν υπηρχε λογος. Και το εβλεπα και απο μονος μου με 3-4 γραμμες κωδικα οπως ειπες και εσυ δεν ειναι καθολου δυσκολο. Tελοςπαντων προφανως και υπάρχει δικαιωμα εγγραφης για αυτο και "δουλευει" .
imitheos Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 @migf1 και παλι τα ιδια... κανονικα μου το βγαζει και παλι > Copied from insomnia sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf http://www.insomnia.gr/topic/437533-%CE%B5%CF%81%CF%89%CF%84%CE%AE%CF%83%CE%B5%CE%B9%CF%82-%CE%B3%CE%B9%CE%B1-c/page__st__1170#entry5119576 Τι τιμή έχει το i ?
Star_Light Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 http://www.insomnia....70#entry5119576 Τι τιμή έχει το i ? > #include<stdio.h> #include<string.h> int main( void ) { char str1[]="hello"; char str2[]="sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf"; int x=3 , y=4 , z=5; strcpy(str1,str2); puts("Copied from insomnia"); printf("sdjdslk jfs dfjdslkfj sdklfj dslkfj sdfj dsaf dsj hdsg sk hjhsg fdgsdf\n"); printf("%s" , str1); printf("%d , %d , %d " , x , y , z); return 0; } Τα x,y,z να δεις τι τιμες έχουν Τεσπα κανεις δεν αμφισβητει το overwrite .... το μονο που μου εκανε εξαρχης εντυπωση ειναι πως διαολο καταφερνει και "δουλευει" η puts /printf.... στο δικο μ συστημα τουλαχιστον.
migf1 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Δεν θα ζαλιζα το θρεντ αμα δεν υπηρχε λογος. Και το εβλεπα και απο μονος μου με 3-4 γραμμες κωδικα οπως ειπες και εσυ δεν ειναι καθολου δυσκολο. Tελοςπαντων προφανως και υπάρχει δικαιωμα εγγραφης για αυτο και "δουλευει" . Δοκίμασε να ορίσεις τα x,y,z μεταξύ ορισμού str1 & str2.
Star_Light Δημοσ. 11 Δεκεμβρίου 2012 Δημοσ. 11 Δεκεμβρίου 2012 > int read_line( char str[] , int n ) { int ch , i =0; while( (ch = getchar()!='\n') if( i < n ) str[i++] = ch; str[i]='\0'; return i; // Επέστρεψε τον αριθμο των χαρακτήρων που έχεις αποθηκεύσει στο str } Για την παρπάνω συνάρτηση δεν θα ήταν καλύτερο να βάζαμε το i<n μέσα στο while αντι να χρησιμοποιούμε μια εξτρα συνθηκη που φαινεται περιττή? > while( (ch= getchar() != '\n' && i<n )
migf1 Δημοσ. 12 Δεκεμβρίου 2012 Δημοσ. 12 Δεκεμβρίου 2012 Τι εννοείς ως "περιττή σύγκριση"; Και στις 2 περιπτώσεις 2 συγκρίσεις γίνονται, αλλά στη 2η περίπτωση γλιτώνεις περιττά iterations του loop... > #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXINPUT (2+1) /* ----------------------------------- */ int read_line( char str[] , int n ) { int ch, i=0; while ( '\n' != (ch = getchar()) ) { if ( i < n ) str[i++] = ch; putchar('*'); } str[i] = '\0'; putchar('\n'); return i; // Επέστρεψε τον αριθμο των χαρακτήρων που έχεις αποθηκεύσει στο str } /* ----------------------------------- */ int readline( char str[] , int n ) { int ch, i =0; while( '\n' != (ch = getchar()) && i < n ) { str[i++] = ch; putchar('*'); } str[i] = '\0'; putchar('\n'); return i; // Επέστρεψε τον αριθμο των χαρακτήρων που έχεις αποθηκεύσει στο str } /* ----------------------------------- */ int main( void ) { char input[MAXINPUT] = {'\0'}; printf( "%d\n", read_line(input, MAXINPUT) ); printf( "(%zu): %s\n", strlen(input), input ); printf( "%d\n", readline(input, MAXINPUT) ); printf( "(%zu): %s\n", strlen(input), input ); system("pause"); // Windows only return 0; } // INPUT/OUTPUT: 1234567890 ********** 3 (3): 123 1234567890 *** 3 (3): 123 Επίσης έτσι όπως τα έχεις τα loops, βγαίνεις εκτός ορίων του input όταν σου δίνουν στην είσοδο πλήθος χαρακτήρων >= n. Στο παράδειγμα θα έπρεπε να κρατάει το "12" και όχι το "123".
Star_Light Δημοσ. 12 Δεκεμβρίου 2012 Δημοσ. 12 Δεκεμβρίου 2012 migf1 ναι το βλεπω αυτο που λες..... τον κώδικα τον έχω πάρει απο τον King και του έχω βαλει κάποιες μικρες βελτιώσεις μεσα πχ να μην δεχεται αρνητικες ημερομηνιες . > #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX_REMIND 50 #define MSG_LEN 3 int read_line(char str[] , int n); int main( void ) { char reminders[MAX_REMIND][MSG_LEN+3]; char day_str[3] , msg_str[MSG_LEN+1]; int day , i , j , num_remind=0; for(;{ if( num_remind == MAX_REMIND) { printf("-- No space left --\n"); break; } printf(" Enter day and reminder : "); scanf("%2d", &day); if( day == 0 || day < 0) break; sprintf(day_str , "%2d" , day); read_line(msg_str, MSG_LEN); for(i=0; i < num_remind; i++) if(strcmp(day_str , reminders[i]) < 0 ) break; for(j=num_remind; j>i; j--) strcpy(reminders[j], reminders[j-1]); strcpy(reminders[i] , day_str); strcat(reminders[i] , msg_str); num_remind++; } if( !num_remind ) exit(1); printf("\nDay Reminder\n"); for(i=0; i < num_remind; i++) printf(" %s\n" , reminders[i]); return 0; } int read_line(char str[] , int n) { int ch , i =0 ; while( (ch= getchar()) !='\n' && i<n) //if( i < n ) str[i++]= ch; str[i]='\0'; return i; } Καμια διόρθωση σε αυτο που επισημαινεις υπάρχει ?
migf1 Δημοσ. 12 Δεκεμβρίου 2012 Δημοσ. 12 Δεκεμβρίου 2012 migf1 ναι το βλεπω αυτο που λες..... τον κώδικα τον έχω πάρει απο τον King και του έχω βαλει κάποιες μικρες βελτιώσεις μεσα πχ να μην δεχεται αρνητικες ημερομηνιες . > #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX_REMIND 50 #define MSG_LEN 3 int read_line(char str[] , int n); int main( void ) { char reminders[MAX_REMIND][MSG_LEN+3]; char day_str[3] , msg_str[MSG_LEN+1]; int day , i , j , num_remind=0; for(;{ if( num_remind == MAX_REMIND) { printf("-- No space left --\n"); break; } printf(" Enter day and reminder : "); scanf("%2d", &day); if( day == 0 || day < 0) break; sprintf(day_str , "%2d" , day); read_line(msg_str, MSG_LEN); for(i=0; i < num_remind; i++) if(strcmp(day_str , reminders[i]) < 0 ) break; for(j=num_remind; j>i; j--) strcpy(reminders[j], reminders[j-1]); strcpy(reminders[i] , day_str); strcat(reminders[i] , msg_str); num_remind++; } if( !num_remind ) exit(1); printf("\nDay Reminder\n"); for(i=0; i < num_remind; i++) printf(" %s\n" , reminders[i]); return 0; } int read_line(char str[] , int n) { int ch , i =0 ; while( (ch= getchar()) !='\n' && i<n) //if( i < n ) str[i++]= ch; str[i]='\0'; return i; } Καμια διόρθωση σε αυτο που επισημαινεις υπάρχει ? Δεν μπορώ να δω τώρα τον κώδικα, αλλά αν ρωτάς πως να το κάνεις να κρατάει το σωστό "12" αντί για το λάθος "123", τότε θελει i < n-1 αντί για i < n.
Star_Light Δημοσ. 12 Δεκεμβρίου 2012 Δημοσ. 12 Δεκεμβρίου 2012 Οκ. Ειναι απο το βιβλιο του King Σελ. 295 κανα καλο γρηγορο παραδειγμα και επεξηγηση για την sprintf έχεις ???? έχω ζαλιστει ..... p.s Παντως οταν ευκαιρησεις δες λιγο τον κωδικα.....
Προτεινόμενες αναρτήσεις