Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 22:03

Star_Light έγραψε:
... Βεβαια ακομη με προβληματιζει διοτι και αυτο που ειχα διαβασει για 8 χαρακτηρες ονοματα ισως και να μην ισχυει διοτι πχ το δικο μου hostname ειναι παραπανω πχ

Κώδικας: Επιλογή όλων
kostas@kostas-SSL:~$ hostname
kostas-SSL
kostas@kostas-SSL:~$


εκτος βεβαια και αν εννοει το kostas απο τα αριστερα και οχι το kostas μαζι με το SSL απο την αλλη που ειναι γενικα το hostname και οχι το username :)

Αν το θυμάμαι καλά, το πλήθος χαρακτήρων το καθορίζεις στο αρχείο: /etc/default/login

έγραψε:
αααα οκ ναι το ειχες εξηγησει και παλαιοτερα τωρα καταλαβα! Αν ειχε οριστει σαν string literal θα ηταν char s[3]="abc"; ???

Αυτό δεν είναι ούτε string, ούτε string literal... είναι απλός πίνακας χαρακτήρων (δεν διάβασες το ποστ που τα εξηγώ αναλυτικά; )

έγραψε:
πολυ ενδιαφερον!!!!! Eπισης ποια η διαφορα των στάνταρ απο τις μη στάνταρ βιβλιοθήκες της γλώσσας?

Τις μη-στανταρ βιβλιοθήκες ή τις φτιάχνεις μόνος σου (σαν κι αυτή που σας είπα να φτιάξουμε για διαχείριση strings λίγο πιο πάνω) ή χρησιμοποιείς έτοιμες που έχουν φτιάξει άλλοι (με τον τρόπο που σου εξήγησα με αφορμή την mpfr).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 22:49

migf1 έγραψε:
Star_Light έγραψε:http://forum.ubuntu-gr.org/viewtopic.php?f=9&t=17977

oριστε μια προσπαθεια οδηγου για το buffer overflow που πηγα να κανω... εσυ σαν προγραμματιστης σιγουρα θα μου πεις αν μπορω να τον αφησω ή θελει κατεβασμα καθως παραπληροφορει τον κοσμο ή δεν ειναι σωστος , να βοηθησω θελω οχι να γραφω μπουρδες και να μην βοηθαω οποιον το διαβαζει.... οποτε ειναι σημαντικο αν μπορεις κοιταξε τον λιγο δεν ειναι μεγαλος!

Θα το κοιτάξω αύριο Κώστα, για να γράψω σήμερα για τους έξτρα ελέγχους που χρειάζεται να κάνουμε στην s_compare().


oK!!!!

ΜΟνοο δωσε μου 10-15 λεπτα να διαβασω το ποστ που εκανες με τα strings literal γιατι χθες εκεινη την ωρα δεν την πολυ - παλευα!

Π.Σ Οσο για το αρχειο login ετσι οπως μου το εδωσες δεν το βρηκα και στο μεταξυ δες εδω

Κώδικας: Επιλογή όλων
kostas@kostas-SSL:~$ locate login | wc -l
156
kostas@kostas-SSL:~$ locate login | cat -n
1 /bin/login
2 /etc/login.defs
3 /etc/alternatives/rlogin

....
152 /var/lib/dpkg/info/login.conffiles
153 /var/lib/dpkg/info/login.list
154 /var/lib/dpkg/info/login.md5sums
155 /var/lib/dpkg/info/login.postinst
156 /var/lib/dpkg/info/login.preinst


εδωσα μια διοχετευση για να μετρησω ποσα αρχεια υπάρχουν και εριξα και μια επιβεβαιωση με την cat με το flag -n για να μου τα βγαλει αριθμημενα... :?
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 23:02

Ναι οκ, δεν είμαι σίγουρος για το αρχείο. Πάντως μη τον μεγαλώσεις το όριο... μπορεί να έχεις προβλήματα μετά (8 είναι το default, μπορεί να πάει αρκετά παραπάνω, αλλά μην το αλλάξεις).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 23:07

migf1 έγραψε:Οκ λοιπόν, ας περάσουμε τώρα στο...

Κώδικας: Επιλογή όλων
char *s = "this is a test";

Εδώ βασικά ΔΕΝ έχουμε string, έχουμε ένα string literal ή αλλιώς, μια σταθερά τιμή τύπου string, σαν να την είχαμε ορίσει με #define...

Κώδικας: Επιλογή όλων

#define STR_LITERAL "this is a test"

int main( void )
{
char *s = STR_LITERAL;
...
}

Ο πιο γρήγορος τρόπος για να καταλάβετε σε αυτό το παράδειγμα πως το s δεν είναι string αλλά απλός δείκτης, είναι να κάνετε ένα: sizeof( s ); και να διαπιστώσετε πως το μέγεθός του δεν είναι το πλήθος των χαρακτήρων του string + 1 για τον μηδενικό χαρακτήρα, αλλά είναι 4 bytes (ή 8 bytes στις 64μπιτες πλατφόρμες) που απεικονίζει το μέγεθος του δείκτη s, που είναι ίδιο για όλους τους δείκτες!

Κατόπιν, μπορείτε να δοκιμάσετε να κάνετε κάτι τέτοιο:

Κώδικας: Επιλογή όλων
s[1] = 'a;'

ή κάτι τέτοιο:
Κώδικας: Επιλογή όλων
*s = 'a;'

και να διαπιστώσετε πως ο compiler δεν θα παραπονεθεί, αλλά το πρόγραμμα θα κρασάρει!!! Ο λόγος είναι πως τα string literals ΔΕΝ μπορούμε να τα αλλάξουμε, μόνο να τα διαβάσουμε ή να τα χρησιμοποιήσουμε απείραχτα (read only).

Αν θέλουμε ντε και καλά να φτιάξουμε ένα string ορίζοντάς το ως δείκτη και όχι ως πίνακα, τότε πρέπει εκτός από τον ορισμό του δείκτη να δεσμεύσουμε και μνήμη για το μέγιστο πλήθος των χαρακτήρων που θέλουμε να φιλοξενεί + 1 για τον μηδενικό χαρακτήρα. Θα μπορούμε κατόπιν να το διαχειριστούμε σαν κανονικό string, αλλά πριν τερματίσουμε το πρόγραμμά μας θα πρέπει να απελευθερώσουμε τη μνήμη που δεσμεύσαμε...

Κώδικας: Επιλογή όλων

int main( void )
{
char *s = NULL;
s = calloc( μέγιστο_πλήθος_χαρακτήρων + 1, sizeof(char) );
...
printf("%lu\n", sizeof( s ) );
...
free( s );
return 0;

Σημειώστε πως στον παραπάνω κώδικα δεσμεύω τη μνήμη με calloc() και όχι με malloc(), διότι η calloc() γεμίζει με μηδενικά τη μνήμη που δεσμεύει, που στην περίπτωσή μας μας έρχεται... ταμάμ, διότι ισοδυναμεί με γέμισμα του string s με μηδενικούς χαρακτήρες σε όλο του το μήκος.

Ανεξάρτητα με την ευεργετική αυτή ιδιότητα σε strings που δημιουργούμε δυναμικά, να προτιμάτε πάντα την calloc() έναντι της malloc() για οποιονδήποτε τύπο δεικτών.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Και για να κλείσουμε το κομμάτι των ορισμών, στη C τα string literals μπορείτε να τα χρησιμοποιείται και απευθείας, είτε οριζοντάς τα με #define είτε όχι.

Π.χ.
Κώδικας: Επιλογή όλων

int main( void )
{
if ( "this is a test"[ 1 ] == 'h' )
...
else
...

return 0;
}

ή πιο όμορφα...
Κώδικας: Επιλογή όλων

#define MESSAGE "this is a test"
int main( void )
{
if ( MESSAGE[ 1 ] == 'h' )
...
else
...

return 0;
}

και προφανώς και με χρήση δείκτη, όπως είπαμε σήμερα...
Κώδικας: Επιλογή όλων

int main( void )
{
char *s = "this is a test";
if ( s[ 1 ] == 'h' )
...
else
...

return 0;
}

ή με συνδυασμό τους...
Κώδικας: Επιλογή όλων

#define MESSAGE "this is a test"

int main( void )
{
char *s = MESSAGE;
if ( s[ 1 ] == 'h' )
...
else
...

return 0;
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Τα strings literals λοιπόν τα χρησιμοποιούμε σαν READ ONLY σταθερές τιμές τύπου string.

Ακούω (τυχόν) απορίες, για να συνεχίσουμε.


1. Δυστυχως αυτα τα κομματια κωδικα... τα βλεπω πρωτη φορα και δεν τα καταλαβαινω... αυτα τα οποια περιεκλεισα με "-------"
ειδικα το "this is a test"[1]="h" δεν το εχω ξαναδει ποτε μου σαν ορισμο....

2. "Ο πιο γρήγορος τρόπος για να καταλάβετε σε αυτό το παράδειγμα πως το s δεν είναι string αλλά απλός δείκτης, είναι να κάνετε ένα: sizeof( s ); και να διαπιστώσετε πως το μέγεθός του δεν είναι το πλήθος των χαρακτήρων του string + 1 για τον μηδενικό χαρακτήρα, αλλά είναι 4 bytes (ή 8 bytes στις 64μπιτες πλατφόρμες) που απεικονίζει το μέγεθος του δείκτη s, που είναι ίδιο για όλους τους δείκτες!" αυτο λες.

Αλλα αρχικα δεν ξεκιναμε με εναν απλο δεικτη θελω να πω οτι ο δεικτης μας ειτε δειχνει εδω ειτε δειχνει εκει ειναι τοσο... επομενως αρχικα τον βάζω να δειχνει στον 1ο χαρακτηρα... μετα στον δευτερο... μετα στον τριτο κ.ο.κ ετσι ειχαμε πει τωρα πως θα αλλαξει ξαφνικα το μεγεθος του σε πληθος χαρακτηρων + 1 εκτος και αν εχουμε μιλησει για το αρχικο του μεγεθος....
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 23:09

migf1 έγραψε:Ναι οκ, δεν είμαι σίγουρος για το αρχείο. Πάντως μη τον μεγαλώσεις το όριο... μπορεί να έχεις προβλήματα μετά (8 είναι το default, μπορεί να πάει αρκετά παραπάνω, αλλά μην το αλλάξεις).


Αχα οκ δεν θα το πειραξω αλλα αυτο το παραδειγμα που εχω βαλει και στον οδηγο που θα δεις αυριο με εχει σκαλωσει... τελοςπαντων προς το παρον μην τα μπλεκουμε οπως θα ελεγες εσυ.... today is another day οπως ειχε πει και ο Ροκα στο never back down (το χετε δει?) φοβερο να το δειτε.
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 23:35

Star_Light έγραψε:
migf1 έγραψε:
...
1. Δυστυχως αυτα τα κομματια κωδικα... τα βλεπω πρωτη φορα και δεν τα καταλαβαινω... αυτα τα οποια περιεκλεισα με "-------"
ειδικα το "this is a test"[1]="h" δεν το εχω ξαναδει ποτε μου σαν ορισμο....

2. "Ο πιο γρήγορος τρόπος για να καταλάβετε σε αυτό το παράδειγμα πως το s δεν είναι string αλλά απλός δείκτης, είναι να κάνετε ένα: sizeof( s ); και να διαπιστώσετε πως το μέγεθός του δεν είναι το πλήθος των χαρακτήρων του string + 1 για τον μηδενικό χαρακτήρα, αλλά είναι 4 bytes (ή 8 bytes στις 64μπιτες πλατφόρμες) που απεικονίζει το μέγεθος του δείκτη s, που είναι ίδιο για όλους τους δείκτες!" αυτο λες.

Αλλα αρχικα δεν ξεκιναμε με εναν απλο δεικτη θελω να πω οτι ο δεικτης μας ειτε δειχνει εδω ειτε δειχνει εκει ειναι τοσο... επομενως αρχικα τον βάζω να δειχνει στον 1ο χαρακτηρα... μετα στον δευτερο... μετα στον τριτο κ.ο.κ ετσι ειχαμε πει τωρα πως θα αλλαξει ξαφνικα το μεγεθος του σε πληθος χαρακτηρων + 1 εκτος και αν εχουμε μιλησει για το αρχικο του μεγεθος....

Για αυτό ήθελα να το αφήσω ξεχωριστά αυτή την περίπτωση :)

Λοιπόν, για να τα απλοποιήσουμε λιγάκι, όταν θέλετε να ορίσετε strings να προτιμάτε τη σύνταξη πινάκων και για να είστε καλυμμένοι, να ορίζετε πάντα και το μέγιστο πλήθος χαρακτήρων τους μέσα στις αγκύλες, και για τον μηδενικό να γράφετε +1 για να καταλαβαίνεται αμέσως πόσοι είναι οι μέγιστοι ωφέλιμοι χαρακτήρες που μπορεί να φιλοξενήσει... όπως σας έχω δείξει...
Κώδικας: Επιλογή όλων

char s[100+1]; // 100 ωφέλιμοι + '\0'

Και να τα αρχικοποιείται πάντα...
Κώδικας: Επιλογή όλων

char s[100+1] = "bla bla";

Αν δεν θέλετε να τους δώσετε αρχική τιμή, τότε να τα αρχικοποιείτε με '\0' σε όλο το μέγιστο μήκος τους...
Κώδικας: Επιλογή όλων

char s[100+1] = { '\0' };

Αν κάνετε πάντα κάποιο από τα τελευταία 2 παραδείγματα, τότε είστε καλυμμένοι σε ότι αφορά τον ορισμό των strings, και θα σας δίνουν πάντα κατανοητό αποτέλεσμα οι sizeof() και strlen()

Τώρα, αν θέλετε να ορίσετε δυναμικά ένα string, να το κάνετε πάντα ως εξής:
Κώδικας: Επιλογή όλων

char *s = NULL;
s = calloc( 100+1, sizeof(char) );
...
if (s)
{
free(s);
s = NULL;
}

ή για πιο συνεπτυγμένα, ...
Κώδικας: Επιλογή όλων

char *s = calloc( 100+1, sizeof(char) );
...
if (s)
{
free(s);
s = NULL;
}

Και είστε καλυμμένοι :)

Τέλος, αν θέλετε να χρησιμοποιήσετε string literals, τότε να τα ορίζετε ως σταθερές με #define στην αρχή, και μετά θα μπορείτε να χρησιμοποιείτε το όνομά του σαν να ήταν κανονικό string, με την προϋπόθεση πως δεν θα επιχειρήσετε να τροποποιήσετε τα περιεχόμενά του...
Κώδικας: Επιλογή όλων

#define MESSAGE "bla bla" // string literal
int main( void )
{
...
printf("size = %ld, length = %ld\n, sizeof( MESSAGE ), strlen( MESSAGE ) );
...
}

Είμαστε ΟΚ τώρα; Αν όχι, πες μέχρι να τα ξεδιαλύνουμε.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 23:49

Ορίστε κι ένα παράδειγμα που βολεύει να χρησιμοποιήσουμε string literal αντί για κανονικό string (μπορείς να το κάνεις και με κανονικό string όμως αν θέλεις)...

Κώδικας: Επιλογή όλων

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

#define VOWELS "aeiouyAEIOUY"

// ---------------------------------------------------------------
int is_vowel( const char c )
{
int i, length = strlen( VOWELS );

for (i=0; i < length; i++)
if ( c == VOWELS[i] )
return 1; // true

return 0; // false
}
// ---------------------------------------------------------------
int main( void }
{
char c;

printf("Enter a letter: ");
scanf("%c", &c );

if ( is_vowel( c ) )
puts("it was a vowel");
else
puts("it was a not vowel");

return 0;
}
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 23:58

οκ!
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 06 Σεπ 2011, 00:01

Προχωράμε κανονικά δηλαδή;
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 06 Σεπ 2011, 00:08

migf1 έγραψε:Προχωράμε κανονικά δηλαδή;


2 λεπτα... δηλαδη επειδη η C μας "αναγκαζει" να χειριζομαστε τα strings ειτε σαν πινακες χαρακτηρων ειτε σαν διαδοχικους χαρακτηρες στην μνήμη
τοτε για αυτο το ορίζουμε ετσι =>
Κώδικας: Επιλογή όλων
char s[100+1];
το string μας ε? Και θα πρεπει να το αρχικοποιουμε παντα γιατι φερει και δεικτες μεσα και ενας δεικτης ο οποιος δεν δειχνει καπου στην μνήμη δεν ειναι καλη τακτική ή μαλλον δειχνει αλλα δεν ξερουμε εμεις που δειχνει.... :D
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι