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

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

Δημοσ.

Χωρίς recursion και μόνο με 4 (στο σύνολο) συγκρίσεις, όταν το πλήθος των στοιχείων είναι πάνω από 2.

 

 

>
void scan_for_largest(int theArr[], int theSize, int* larg1, int* larg2)
{
   if ( theArr == (int*) NULL )
   {
       *larg1 = *larg2 = 0;
       return;
   }

   if ( theSize <= 2)
   {
       if ( theSize == 1)
       {
           *larg1 = theArr[0];
           *larg2 = 0;
       } else {
           *larg1 = (theArr[0] > theArr[1]?theArr[0]:theArr[1]);
           *larg2 = (*larg1 == theArr[0]?theArr[1]:theArr[0]);
       }
   } else {

       *larg1 = (theArr[0] > theArr[1]?theArr[0]:theArr[1]);
       *larg2 = (*larg1 == theArr[0]?theArr[1]:theArr[0]);

       register unsigned char indx = 2;

       for (; indx < theSize; indx++)
       {
           if (theArr[indx] <= *larg2)
           {
               continue;
           }

           if (theArr[indx] > *larg1)
           {
               *larg2 = *larg1;
               *larg1 = theArr[indx];
           } else {
               *larg2 = theArr[indx];
           }
       }
   }
}

 

 

Ωραίος, μπήκα στον πειρασμό να το δοκιμάσω με κάποια test - scenarios που χρησιμοποίησα όταν έγραφα το δικό μου.

 

Όμως στην περίπτωση που έχουμε a[3] = { 16, 15, 16 } τότε larg1 = larg2 = 16 (σε C++ Builder πάντα).

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

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

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

>
int find_two_largest(int *ar, int n, int *res)
{
int i;
if(!ar || !res || !n)
return 1;
res[0] = INT_MIN;
res[1] = INT_MIN;
for(i = 0; i < n; i++)
{
if(ar[i] > res[0]) // first max
res[0] = ar[i];
else if(ar[i] > res[1]) // second max
res[1] = ar[i];
}
return 0;
}

 

edit

>
int find_two_largest(int *ar, int n, int *res)
{
int i;
if(!ar || !res || !n)
return 1;
res[0] = INT_MIN;
res[1] = INT_MIN;
for(i = 0; i < n; i++)
{
if(ar[i] > res[0]) // first max
{
res[1] = res[0];
res[0] = ar[i];
}
else if(ar[i] > res[1]) // second max
res[1] = ar[i];
}
return 0;
}

 

Και το τελευταιο

>
int find_two_largest(int *ar, int n, int *res)
{
int i;
if(!ar || !res || !n)
 return 1;
res[0] = INT_MIN;
res[1] = INT_MIN;
for(i = 0; i < n; i++)
{
 if(ar[i] > res[0]) // first max
 {
  res[1] = res[0];
  res[0] = ar[i];
 }

 else if(ar[i] > res[1] && ar[i] != res[0]) // second max
  res[1] = ar[i];
 
}
return 0;
}

Επεξ/σία από παπι
  • Like 2
Δημοσ.

 

 

Ωραίος, μπήκα στον πειρασμό να το δοκιμάσω με κάποια test - scenarios που χρησιμοποίησα όταν έγραφα το δικό μου.

 

Όμως στην περίπτωση που έχουμε a[3] = { 16, 15, 16 } τότε larg1 = larg2 = 16 (σε C++ Builder πάντα).

 

Σωστός.

 

Άρα λείπει ένα ">=" αντί για σκέτο ">" στο check για larg1.

 

 

edit:

Βέβαια... από την άλλη εάν απλά σου ζητάει τις μεγαλύτερες τιμές όχι τι τιμές έχουν τα στοιχεία που έχουν τις μεγαλύτερες τιμές, τότε η σωστή απάντηση είναι 16 και 15.

 

Όχι ότι το έκανα με αυτό το σκεπτικό... μετά και από την απάντηση σε εσένα μου έσκασε.

Δημοσ.

Το

 

>

int *p ;

*p = 2;

 

Θεωρειται λάθος εννοειται . Αλλα γιατι ολοι και ολα τα βιβλια το θεωρουν τοσο επικυνδινο?

ειναι πραγματικα τοσο επικυνδινο και στην πραξη ή το λενε τοσο για να αποφευγουν οι αρχαριοι την μαθητεια κακων πρακτικων προγραμματισμου?

 

Το Virtual address space δεν παρεχει process isolation ωστε μια διεργασια Α (εστω ο κωδικας του παραπανω προγραμματος)

να γράψει και να τροποποιήσει δεδομένα μιας Β ?

 

Υπαρχει ποτε περιπτωση να τροποποιησεις δεδομενα που ανηκουν στο OS? Το θεωρω απιθανο

Δημοσ.

Δεν μπορεις να εχεις access σε OS μνημη επειδη ειναι σε αλλο ring (αν δε κανω λαθος ο CPU θα σου βγαλει κοκκινη καρτα)

 

Σε αλλη process μπορεις αλλα οχι ετσι. Γενικα οτι pointer και να βαλεις δεν θα χτυπισεις την μνημη αλλης process επειδη πολυ απλα η διευθυνση 0 εως 0x7f ff ff ff ειναι ολη δικη σου

  • Like 1
Δημοσ.

Ναι τα θυμαμαι τα rings. Eιμαι και σε αλλο runlevel αλλωστε που τρεχουν συγκεκριμενες υπηρεσιες του λειτουργικου.

 

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

 

Καμια καλη πηγη που να εξηγει απλα το semgents : offset παιζει ?

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

Το

 

>

int *p ;

*p = 2;

 

Θεωρειται λάθος εννοειται . Αλλα γιατι ολοι και ολα τα βιβλια το θεωρουν τοσο επικυνδινο?

ειναι πραγματικα τοσο επικυνδινο και στην πραξη ή το λενε τοσο για να αποφευγουν οι αρχαριοι την μαθητεια κακων πρακτικων προγραμματισμου?[..]

 

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

 

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

 

Αυτού του είδους τα σφάλματα (εγγραφή σε τμήματα μνήμης της εφαρμογής που δεν πρέπει) οδηγούν συνήθως στο περίφημο σφάλμα εξόδου "NULL pointer assignment" (--EDIT:ή και "Access Violation" με άμεση διακοπή της εκτέλεσης του προγράμματος) που μπορεί να ταλαιπωρήσει αρκετά μέχρι να επιλυθεί.

 

..

Στα παλαιότερα Λ. Σ. δίχως προστασία μνήμης κλπ (βλ. DOS) με τέτοια κόλπα (+ I/O Ports) μπορούσες να διαβάσεις διάφορες εσωτερικές δομές δεδομένων (συνήθως undocumented) ή τμήματα άλλων εφαρμογών για διάφορους αγαθούς ή μη σκοπούς.

Επεξ/σία από Directx
  • Like 1
Δημοσ.

Ναι αλλα ο κώδικας του προγραμματος σου βρισκεται στο TEXT που ειναι το code segment και περιεχει τον εκτελεσιμο κώδικα.

Το οποιο ειναι ROM και δεν μπορει να γινει overwritten απο το προγραμμα. Ειδικα στο λινουξ θυμαμαι οτι δεν υποστηριζεται η αυτο-τροποποιηση απο το ιδιο το προγραμμα.

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

 

???

 

τι παιζει ?

Δημοσ.

Ναι αλλα ο κώδικας του προγραμματος σου βρισκεται στο TEXT που ειναι το code segment και περιεχει τον εκτελεσιμο κώδικα.

Το οποιο ειναι ROM και δεν μπορει να γινει overwritten απο το προγραμμα. Ειδικα στο λινουξ θυμαμαι οτι δεν υποστηριζεται η αυτο-τροποποιηση απο το ιδιο το προγραμμα.

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

 

???

 

τι παιζει ?

 

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

 

Αυτό αν και καταστροφικό είναι ταυτόχρονα και σωτήριο διότι σου παρέχει μια ιδέα που προέκυψε σφάλμα (ώστε να ξέρεις που να ψάξεις) αν όμως έχεις την ατυχία ο pointer να δείχνει σε κάποια σελίδα που είναι writable και τροποποιήσεις κάτι που δεν πρέπει τότε ή δεν θα το μάθεις ποτέ (δίχως ειδικά εργαλεία) είτε το πρόγραμμα θα λειτουργεί ιδιόρρυθμα (ώρες - ώρες) ή θα λάβεις το σφάλμα "NULL pointer assignment!" κατά την έξοδο (ή ένα συνδυασμό των τριών κλπ).

 

Από εκεί και πέρα, το WinAPI παρέχει μια σειρά από συναρτήσεις και διαδικασίες που επιτρέπουν την τροποποίηση των περιεχομένων ενός εκτελούμενου PE (για λόγους Debugging φυσικά) με αρκετά ευέλικτο τρόπο (αρκεί να ζητήσεις την κατάλληλη άδεια για αυτό τον σκοπό).

 

Με το LINUX δεν έχω ασχοληθεί ιδιαίτερα και δεν μπορώ να συνεισφέρω.

Δημοσ.

...

Και το τελευταιο

 

>
int find_two_largest(int *ar, int n, int *res)
{
int i;
if(!ar || !res || !n)
return 1;
res[0] = INT_MIN;
res[1] = INT_MIN;
for(i = 0; i < n; i++)
{
if(ar[i] > res[0]) // first max
{
res[1] = res[0];
res[0] = ar[i];
}

else if(ar[i] > res[1] && ar[i] != res[0]) // second max
res[1] = ar[i];

}
return 0;
}

 

 

 

Μου άρεσε αυτή η υλοποίηση (αν και χρειάζεται έναν έλεγχο ακόμα, για την περίπτωση που του περαστεί πίνακας με 1 μόνο στοιχείο) ;)

 

Ναι αλλα ο κώδικας του προγραμματος σου βρισκεται στο TEXT που ειναι το code segment και περιεχει τον εκτελεσιμο κώδικα.

Το οποιο ειναι ROM και δεν μπορει να γινει overwritten απο το προγραμμα. Ειδικα στο λινουξ θυμαμαι οτι δεν υποστηριζεται η αυτο-τροποποιηση απο το ιδιο το προγραμμα.

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

 

???

 

τι παιζει ?

 

Δεν νομίζω πως είναι καλή ιδέα να παίρνεις ως δεδομένο το program memory layout, γιατί δεν είναι εγγυημένο πως ισχύει σε όλες τις πλατφόρμες.

 

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

Δημοσ.

Δεν το πηρα σαν δεδομενο οτι ισχυει για ολες τις πλατφορμες... αλλα αυτο ισχυει τουλαχιστον στο Linux.

Στα διαφορα βιβλια πιθανον να μην θέλουν να μπλέξουν με τέτοιου ειδους βάθος μιας και ειναι άσχετο με την C αλλα για το Linux ειναι σωστο το σκεπτικο μου. Εφοσον σε memory layout στο οποιο το code segment ειναι ROM δεν μπορεις να έχεις εγγραφη στον κωδικα του προγραμματος. Τελος :P αλλα στα Windows υπάρχει πιθανοτητα οπως εγραψε και ο DirectX πιο πανω.

 

http://www.thegeekst...-memory-layout/

 

Iσα ισα στα Windows δεν παιζει καν κ η fork και ο τροπος με τον οποιο θα δημιουργηθει μια καινουργια διεργασια.

 

DirectX τι ειναι το PE? Programm execute ???

 

P.S Πλεον διαβαζα καπου οτι οι developers των OS λογω της εξάπλωσης των δικτυων έχουν ή το κάνουν ηδη εδω και καιρο να περιοριζουν κάποιες σελιδες στην εικονικη μνημη για εγγραφη απο τους προγραμματιστες ωστε να βρεθει μια λυση στις κακοβουλες επιθεσεις. Επειδη παλιοτερα θυμαμαι ειχες πει πως μπορει να προκυψει θεμα στην σελιδοποιηση.

 

P.S2 Ολα αυτα ειναι άσχετα με την C. Μην τα διαβασει κανας πρωτοετης και παει και πει ποτε η σελιδοποιηση στην C :P

Δημοσ.
[..]DirectX τι ειναι το PE? Programm execute ???

 

Είναι τα αρχικά των λέξεων Portable Executable, το file format των εκτελέσιμων αρχείων (& DLL) των 32/64bit+ Windows, μια συνοπτική παρουσίαση του PE μπορεί να βρεθεί εδώ.

Δημοσ.

>

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

#define MAXINPUT 256

int main(int argc, char *argv[])
{

int num;
char text[MAXINPUT];

printf("?Num: ");
scanf("%d", &num);

printf("text: ");
fgets(text, MAXINPUT, stdin);

return 0;
}

γιατί κάτι τέτοιο δεν με αφήνει να γράψω στο text?? κάτι με τον buffer στο scanf παίζει ε; Διαβάζει και το \n ;

Δημοσ.

Ναι, μένει το \n στο input-buffer οπότε πρέπει να το καθαρίσεις, είτε μέσο fflush(stdin) που είναι όμως non standard και δεν δουλεύει σε κάθε Λ. Σ. ή με ένα while(getchar() != '\n'); (το θέμα αυτό έχει αναλυθεί από τον φίλο migf1 σε βάθος -αν θυμάμαι καλά- οπότε αξίζει να κάνεις μια αναζήτηση στο forum).

Δημοσ.

OK ευχαριστώ.. Αλλά και η fgets διαβάζει το \n και το αποθηκεύει.. μπορώ να το αποφύγω αυτό χωρίς το while;

 

>#include <stdio.h>

#define MAXINPUT 256

int main(int argc, char *argv[])
{

char text[MAXINPUT]={0};
char *dump = text;

printf("text: ");
fgets(text, MAXINPUT, stdin);

while(*dump != '\0')
printf("| %c |\n", *dump++);

return 0;
}

 

EDIT: και ποιος είναι τότε ο "ασφαλέστερος" τρόπος για να διαβάσουμε έναν αριθμό;

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

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