Jump to content



OutOfSchool Lessons C++


Dr.Paneas

Recommended Posts

  1. Hello World
  2. Namespace και Scope

  3. Character Strings
  4. Πλαίσια και string tips

-----

Παρακαλώ ΜΗΝ κάνετε post εδώ.

Για όποιες απορίες κάνετε νέο θέμα.

Όσοι θέλετε να δηλώσετε συμμετοχή, κάντε το εδώ

Link to comment
Share on other sites

Lesson 1

Ο στόχος αυτού του tutorial είναι να σας μάθει την μοντέρνα πλευρά της C++ . Δυστυχώς πολλές σχολές, μεταξύ αυτών Πανεπιστήμια, αγνοούν το γεγονός ύπαρξης των δύο συμβόλων "συν" ( βλ ++ ) και εξακολουθούν να μαθαίνουν στους σπουδαστές C++ σε στιλ C.

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

Γι αυτό τον λόγο θα ξεκινήσουμε από το πρώτο παράδειγμα χρησιμοποιώντας έννοιες που έχουν να κάνουν με την γλώσσα, αυτήν καθ' αυτήν. Όλα τα παραδείγματα είναι αρκετά αναλυτικά και έχουν να κάνουν με την StandardLibraryτης C++ και όχι με άλλες ξένες extensions.

Ας Αρχίσουμε

Το πρώτο πρόγραμμα με το οποίο θα ασχοληθούμε είναι το κλασσικό και γνωστό σε όλους "Hello World" . Αυτή την φορά όμως θα επικεντρωθούμε σε έννοιες που δεν έχετε σκεφτεί ότι υπάρχουν σε ένα τέτοιο μικρό πρόγραμμα. Έννοιες, βασικές που πρέπει να τις ξεκαθαρίσετε από την αρχή.


[I][COLOR=#9b00d3][FONT=Consolas]// ένα μικρό [/FONT][/COLOR][/I][I][COLOR=#9b00d3][FONT=Consolas]C[/FONT][/COLOR][/I][I][COLOR=#9b00d3][FONT=Consolas]++ πρόγραμμα
[/FONT][/COLOR][/I][COLOR=#00b050][FONT=Consolas]#[/FONT][/COLOR][COLOR=#00b050][FONT=Consolas]include[/FONT][/COLOR][COLOR=#00b050][FONT=Consolas] <[/FONT][/COLOR][COLOR=#00b050][FONT=Consolas]iostream[/FONT][/COLOR][COLOR=#00b050][FONT=Consolas]>[/FONT][/COLOR]
[COLOR=#004dbb][FONT=Consolas]int[/FONT][/COLOR][COLOR=#333333][FONT=Consolas] main[/FONT][/COLOR][COLOR=red][FONT=Consolas]()[/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas]
[/FONT][/COLOR][COLOR=red][FONT=Consolas]{[/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas]
[/FONT][/COLOR][COLOR=black][FONT=Consolas]std[/FONT][/COLOR][COLOR=red][FONT=Consolas]::[/FONT][/COLOR][COLOR=black][FONT=Consolas]cout[/FONT][/COLOR][COLOR=red][FONT=Consolas] << [/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas]"[/FONT][/COLOR][COLOR=#4f81bd][FONT=Consolas] hello world [/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas]" [/FONT][/COLOR][COLOR=red][FONT=Consolas]<<[/FONT][/COLOR][COLOR=black][FONT=Consolas]std[/FONT][/COLOR][COLOR=red][FONT=Consolas]::[/FONT][/COLOR][COLOR=black][FONT=Consolas]endl[/FONT][/COLOR][COLOR=red][FONT=Consolas];[/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas]
[/FONT][/COLOR][COLOR=#004dbb][FONT=Consolas]return[/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas] 0[/FONT][/COLOR][COLOR=red][FONT=Consolas];[/FONT][/COLOR][COLOR=#9b00d3][FONT=Consolas]
[/FONT][/COLOR][COLOR=red][FONT=Consolas]}[/FONT][/COLOR]

Πώς τρέχετε τον κώδικα ;

Εμείς χρησιμοποιήσαμε το IDE Code::Blocks για να κάνουμε compile και να τρέξουμε το συγκεκριμένο πρόγραμμα. Από δω και στο εξής, το Code::Blocks είναι αυτό που θα χρησιμοποιούμε για την εκτέλεση των προγραμμάτων μας. Παρακαλώ, είστε ελεύθεροι να χρησιμοποιήσετε όποιο πρόγραμμα θέλετε και ξέρετε να το δουλεύετε (πχ DevC, VisualC++ κλπ ).

Η επιλογή του Code::Blocks έγινε γιατί είναι Open Source και δουλεύει τόσο σε κλειστό λογισμικό όπως είναι τα Microsoft Windows όπως και σε *nix-οειδή λειτουργικά, πχ GNU/Linux, FreeBSD κλπ. Δηλαδή είναι Cross-Platform.

Αφού κάνετε εγκατάσταση του Code::Blocks, πάμε να δούμε την διαδικασία με την οποία θα τρέχετε των κώδικα που παράγετε.

  • Βήμα 1: File > New

[ATTACH]7245[/ATTACH]

  • Βήμα 2: Γράφουμε το όνομα του προγράμματος (πχ hello ) και πατάμε «Αποθήκευση».

[ATTACH]7246[/ATTACH]

  • Βήμα 2 [ Fixed ]: Μόλις κάνατε λάθος :D

Καλά ρε ; τι είπα πριν από λίγες γραμμές ; Δεν σας είπα ότι εδώ θα κάνουμε C plus plus ; Eεεε, βάλτε λοιπόν την κατάληξη
*.cpp
δίπλα από το “
hello
”.

[ATTACH]7248[/ATTACH]

Το λάθος αυτό έγινε εσκεμμένα, γιατί αν κάνετε
Save As
το
hello.c
τότε
δεν θα τρέχει καμία
Standard Library
την οποία θέλουμε να χρησιμοποιήσουμε κατά κόρον.

  • Βήμα 3:

Γράφετε τον κώδικα σαν γνήσιοι hackers του outofspecs που είστε
:p
:respect:]

[ATTACH]7247[/ATTACH]

Ο λόγος που κάναμε πρώτα το Save As ήταν για να πάρουμε αυτή την ωραία Highlighted εκδοχή του κώδικά μας This is Sparta

// ένα μικρό
C
++ πρόγραμμα

#
include
<
iostream
>

int
main
()

{

std
::
cout
<<
"
hello world
"
<<
std
::
endl
;

return
0
;

}

  • Βήμα 4:

Κάνετε
Build
.

Αν σας βρει λάθη τότε θα πρέπει να τα διορθώσετε. Όταν εκτελέσετε το πρόγραμμα χωρίς λάθη (σε τόσο μικρό πρόγραμμα, τα λάθη σας θα είναι το πιθανότερο τυπογραφικά), θα γράψει στο standard output ( δηλαδή στην έξοδο) :
hello
world
Για την εκτέλεση του προγράμματος πατάμε να κάνει
Compile
.

[ATTACH]7249[/ATTACH]

Για να κατανοήσετε το πρόγραμμα, θα το αναλύουμε γραμμή - γραμμή.

1. Σχόλια [ Comments ]

Η πρώτη γραμμή του προγράμματός μας είναι:


// ένα μικρό C++ πρόγραμμα

Οι χαρακτήρες // σημαίνουν ότι ξεκινάνε σχόλια μέχρι το τέλος της γραμμή. Δηλαδή είναι inline comments . Παρόλο που ο compiler τα αγνοεί (δεν τα βλέπει), τα χρησιμοποιούμε για να τα διαβάζουν οι προγραμματιστές και να κατανοούν καλύτερα τον κώδικά μας. Είναι πολύ βασικό να έχουμε καλά και σωστά σχόλια. Προσοχή όμως, μην γράψετε ένα πρόγραμμα όπου τα σχόλια είναι περισσότερα από τον ίδιο τον εκτελέσιμο κώδικα! Βάλτε σχόλια όπου εσείς θεωρείτε ότι χρειάζεται και κάντε τον κώδικά σας ένα όμορφο έργο documentation.

2. #include

Στην C++ υπάρχουν πολλές βασικές διευκολύνσεις, όπως το input-output (είσοδος-έξοδος), που είναι μέρος της standard library και όχι μέρος του πυρήνα της γλώσσας.

Αυτή η διαφορά είναι πολύ σημαντική επειδή το μέρος της γλώσσας που σχετίζεται με τον πυρήνα αυτής ( core language ) είναι προσπελάσιμο σε όλα τα C++ προγράμματα. Αλλά αν θέλετε να χρησιμοποιήσετε μέρη ή κομμάτια από την standard library (πχ το input-output) τότε πρέπει να τα ζητήσετε με τον κατάλληλο τρόπο.

Τα προγράμματα ζητούν μέρη ή κομμάτια ( διευκολύνσεις ) από την standard library χρησιμοποιώντας #include directives (οδηγίες).

Αυτές οι οδηγίες ( directives ) γράφονται κανονικά στην αρχή του προγράμματος πάνω-πάνω.

Το μόνο κομμάτι/μέρος που χρησιμοποιεί το πρόγραμμά μας από την standard library είναι το input-output. Το οποίο για να το καλέσουμε/ζητήσουμε γράφουμε:

#include <iostream> 

Το όνομα iostream σημαίνει input output stream, δηλαδή είναι το μέρος/το κομμάτι της standard library που της ζητάμε να μας το δώσει για να το χρησιμοποιήσουμε στο πρόγραμμά μας.

Αν δεν το ζητήσουμε, τότε δεν μπορούμε να το χρησιμοποιήσουμε, αφού το input output stream δεν αποτελεί κομμάτι του πυρήνα της γλώσσας C++ αλλά της standard library.

Για να ζητήσουμε λοιπόν ένα κομμάτι/μέρος από την standard library και να μπορούμε να το χρησιμοποιήσουμε στο πρόγραμμά μας γράφουμε:

#include <μέρος/κομμάτι της std library που ζητάμε>

Όπως είπαμε και πριν, το #include αποτελεί μία οδηγία ( directive ) για να τον compiler, που τον λέει ότι ζητάμε κάτι ( κάνουμε κάποιου είδους request ) από την standard library.

Έπειτα βάζουμε μέσα σε angle brackets( < και > ) το κομμάτι που θέλουμε να δανειστούμε από την standard library.

Αυτό το κομμάτι λέγεται standard header.

Παρόλο που η C++ δεν μας εξηγεί τι είναι οι standard headers, φροντίζει να μας δώσει τους ορισμούς για τον καθένα τους, έτσι ώστε να ξέρουμε ποιον χρειαζόμαστε να καλέσουμε και να χρησιμοποιήσουμε στο πρόγραμμά μας κάθε φορά ανάλογα με τις απαιτήσεις μας.

Συμπεριλαμβάνοντας λοιπόν standard header στο πρόγραμμά μας, είμαστε σε θέση να χρησιμοποιήσουμε τα κομμάτια/μέρη κώδικα της standard library που σχετίζονται με αυτόν.

Στην περίπτωσή μας, ο standard header που ζητάμε είναι ο iostream.

bananaΜπερδευτήκατε ; banana :confused: --> :) -->:D

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

- :confused:Θέλω να συμπεριλάβω στο πρόγραμμά μου input-ouput δυνατότητα.:D

- :confused:Δεν την έχει ήδη η C++ ; ; ;

- :)Όχι ! Δεν είναι κομμάτι της C++ Core Language, αλλά κομμάτι της Standard Library της C++. :cool:

- :confused:Και τι είναι αυτή ;

- :)Βιβλιοθήκη που έχει τέτοιες δυνατότητες, σαν αυτήν που θες.

- :confused:Μάλιστα. Και πώς μπορώ τελικά να χρησιμοποιήσω το input-output ;

- :)Πρέπει να το ζητήσεις με τον κατάλληλο τρόπο από την standard library.

- :confused:Πώς το "ζητάω" δηλαδή ;

- :)Χρησιμοποιείς την οδηγία #include και το όνομα του standard header που σε ενδιαφέρει.

-:confused: Τι είναι το #include;

- :)#include είναι μία όδηγία για τον compiler, που όταν την βλέπει αρχίζει να ψάχνει στην standard library για τον standard header που θέλεις να χρησιμοποιήσεις και να τον συμπεριλάβεις (εξού και το include= συμπεριλαμβάνω ) στο πρόγραμμά σου.

- :confused:Μάλιστα. Και τι είναι ο standard header είπαμε ;

- :)Δεν είπαμε γιατί δεν ξέρω ούτε γω .Ξέρω όμως ότι περιλαμβάνει τις δυνατότητες που θέλεις .

- :confused:Και ποιον stadard header χρειάζομαι για την δυνατότητα input-ouput ;

- :)Χρειάζεσαι τον iostream. Αυτός περιέχει το κομμάτι κώδικα που μπορείς να χρησιμοποιήσεις για input-output.

- :confused: Ωραία, ξέρω "πως" θα τον καλέσω και ξέρω "τι" θα καλέσω. Ποια είναι η σύνταξη ;

- :)Η σύνταξη είναι #include <iostream> , πάνω-πάνω στην αρχή του προγράμματος.

- :D Οκ, κατάλαβα.

3. Η συνάρτηση main

H συνάρτηση ( function ) είναι ένα κομμάτι του προγράμματος που έχει δικό του όνομα, και καλώντας αυτό το όνομα τότε ένα άλλο κομμάτι του προγράμματος αρχίζει να τρέχει και στο τέλος επιστρέφει μία και μόνο μία τιμή. Κάθε πρόγραμμα στην C++, πρέπει να περιέχει μία function που λέγεται main. Όταν καλούμε από την C++ να τρέξει το πρόγραμμά σας, η main function είναι αυτή που καλείται πρώτη.

H main function πρέπει να επιστρέψει έναν ακέραιο αριθμό ως αποτέλεσμα.

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

Για να ορίσουμε την main function γράφουμε:

int main()

έτσι λέμε ότι ορίζουμε ( κάνουμε define ) μία function με το όνομα main , η οποία επιστρέφει μία τιμή τύπου int ( integer = ακέραιος ) .

Το int είναι λέξη-κλειδί (keyword) της C++ που σημαίνει ακέραιος.

Οι παρενθέσεις που ακολουθούν διευκρινίζουν ότι πρόκειται για function - συνάρτηση (πχ στα μαθηματικά γράφουμε f(x) = 2x +3 - οπότε πάλι χρησιμοποιούμε παρενθέσεις ).

Γενικά οι παρενθέσεις χρησιμοποιούνται για να δώσουμε τις παραμέτρους στην function μας, εδώ όμως δεν έχουμε καμία παράμετρο αφού οι παρενθέσεις μας είναι κενές. Μην σας απασχολεί όμως αυτό, θα το δούμε σε άλλο κεφάλαιο.

Αρκεί να καταλάβετε ότι η main είναι η βασική function του κάθε C++ προγράμματος, είναι τύπου int και επιστρέφει ένα μηδενικό ( αν όλα πάνε καλά ).

4. Αγκύλες ( Curly braces )

Όπως είπαμε πιο πάνω, όταν καλούμε μία function, εκτελείται/τρέχει ένα άλλο κομμάτι κώδικα που σχετίζεται με αυτήν. Μέσα σε άγκιστρα/αγκύλες { } γράφουμε το κομμάτι κώδικα που θέλουμε να εκτελεστεί.

Το κομμάτι αυτό συνήθως αποτελείται από δηλώσεις ( statements). Για παράδειγμα ο ορισμός της main είναι:

int main()
{
[I]// αριστερό άγκιστρο
// εδώ γράφεται των κώδικα με τις δηλώσεις
// δεξιό άγκιστρο[/I]
}

Ο,τι δήποτε υπάρχει μεταξύ των δύο άγκιστρων συμπεριφέρεται σαν μία μονάδα - αυτό που λέμε code block και εκτελείται μόνο όταν καλέσουμε την συνάρτηση main.

Μόνο που όπως είπαμε η συνάρτηση main καλείται αυτόματα από κάθε πρόγραμμα C++.

Άρα η main αποτελεί τον κορμό, ή αν θέλετε το ίδιο μας το πρόγραμμα. Τα braces ( άγκιστρα ) δηλώνουν ότι: ό,τι υπάρχει ανάμεσά τους είναι κομμάτι της ίδιας της συνάρτησης και εκτελείται όταν την καλέσουμε.

5. Standard Library για output

Το πρώτο statement μέσα στα άγκιστρα, κάνει όλη την δουλειά του προγράμματός μας:

std::cout << "hello world" << std::endl;

Αυτή η δήλωση ( statements ) χρησιμοποιεί τον output operator, << , ο οποίος είναι μέρος της standard library. Την πρώτη φορά χρησιμοποιείται για να γράψει την φράση hello world στο standard output και την δεύτερη φορά για να γράψει την τιμή του std::endl.

Η λέξη μετά το std:: σημαίνει ότι το όνομα που ακολουθεί είναι μέρος ενός namespace που ονομάζεται std.

Namespace είναι μια συλλογή από παρόμοια ονόματα.

Η standard library χρησιμοποιεί το std για να περιλάβει όλα τα ονόματα που ορίζει. Για παράδειγμα, όπως είπαμε χρησιμοποιούμε την standard library για την υποστήριξη του input output, και για αυτό καλούμε το iostream που είναι o standard header που χρειαζόμαστε από δ'αυτην.

Οι εντολές/ονόματα που περιέχει το iostream πρέπει να οριστούν κάπου ώστε να μπορούμε να τις χρησιμοποιήσουμε ( πχ το cout και το endl ). Αφού λοιπόν, η standard library χρησιμοποιεί το namespace std για να αποθηκεύσει/ορίσει τα ονόματα/εντολές που χρειάζεται, έτσι λοιπόν και ο iostream ώς standard header χρησιμοποιεί το ίδιο namespace για να ορίσει τις εντολές του, πριν τις χρησιμοποιήσουμε. Για αυτόν τον λόγο, γράφουμε std::cout και std::endl.

Όπως είπαμε std είναι το όνομα του namespace και cout , endl είναι οι εντολές που έχουν οριστεί σε αυτό. Για να χρησιμοποιήσουμε στο πρόγραμμά μας τις εντολές αυτές πρέπει να γράφουμε την ακριβή τοποθεσία τους .

std::cout

και όχι σκέτο cout.

Το όνομα std::cout αναφέρεται στο standard output stream όπου είναι το κομμάτι που χρησιμοποιεί η standard library για το συνηθισμένο output των προγραμμάτων της.

Για παράδειγμα σε ένα τυπικό C++ πρόγραμμα που εκτελείται σε Windows λειτουργικό σύστημα, το std::cout θα εμφανιστεί στο μαύρο παράθυρο του MSDOS.

Γράφοντας την τιμή std::endl τερματίζει την τρέχουσα γραμμή του output. Πιο απλά: αλλάζει σειρά, έτσι ώστε αν γράφατε ένα πρόγραμμα με περισσότερο output να το εμφανίζει σε καινούρια γραμμή.

Endl = End Line :cool:

6. Return

Το κλασσικό return statement είναι:

return 0;

Αυτό που κάνει είναι να τερματίσει την function και να επιστρέψει την μηδενική τιμή (που λέγαμε) πίσω στο πρόγραμμα μαζί με το κλείσιμο της συνάρτησης. Η τιμή που επιστρέφει πρέπει να είναι συμφωνεί με τον τύπο της συνάρτησης.

Για παράδειγμα στην περίπτωσή μας, η main είναι η συνάρτησή μας και είναι τύπου int ( δηλαδή ακέραια ). Το return της main επιστρέφει την τιμή μηδέν που είναι εξίσου ακέραια. Άρα όλα καλά.

Επειδή η main είναι η μοναδική συνάρτηση στο πρόγραμμα, τερματίζοντας την main θα τερματιστεί και το πρόγραμμά μας. Γενικότερα, όταν τερματίζει η main, τερματίζει και το πρόγραμμα.

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

/chucknorris

post-928-1414343386,7083_thumb.png

post-928-1414343386,7161_thumb.jpg

post-928-1414343386,7403_thumb.png

post-928-1414343386,7477_thumb.png

post-928-1414343386,77_thumb.png

Link to comment
Share on other sites

LESSON 2

Για ρίξτε μια ματιά

Το πρόγραμμα που φτιάξαμε ( Hello World ) μας εισάγει σε δύο πολύ βασικές έννοιες που κυριαρχούν στην C++ :

[1] Expressions ( μτφ. Εκφράσεις )

[2] Scope (μτφ. Σκοπιά )

Τι είναι expression ;

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

Για παράδειγμα 3+4 είναι μία μαθηματική έκφραση, της οποίας το αποτέλεσμα είναι 7.

Ο κώδικας είναι γεμάτος από εκφράσεις διαφόρων ειδών τις οποίες τις χρησιμοποιείτε συνέχεια, γιατί μέσω αυτών «εκφράζετε» την επιθυμία σας στο πρόγραμμα ( του λέτε τι θέλετε να κάνει για εσάς). Οπότε ο όρος Expression ταιριάζει αρκετά στην περίπτωση.

Στην C++, οι expressions έχουν και άλλα αποτελέσματα τα οποία επηρεάζουν το πρόγραμμα. Για παράδειγμα το 3+4 μέσα στον source code δεν μας λέει κάτι. Είναι μία απλή expression.

Όμως το:

std::cout << "Hello, world!" << std::endl;

είναι μία έκφραση η οποία έχει αυτό που ονομάζουμε side effects ( παράπλευρα αποτελέσματα). Αυτό, πρακτικά σημαίνει ότι τούτη εδώ η expression επηρεάζει το πρόγραμμά μας.

Δηλαδή, γράφει το Hello World! στο Output Stream και στην συνέχεια δηλώνει το τέλος της γραμμής (με το endl). Κάνει δηλαδή κάτι το οποίο δεν περνάει απαρατήρητο, όπως το 4+3.

Operators & Operands

Αφού λοιπόν έχετε κατανοήσει τι είναι expression πάμε να δούμε τι είναι τελεστές (operators) και τελεστέοι (operands). Σκεφτείτε ότι είστε σε ένα εργοστάσιο και πρέπει να δώσετε οδηγίες. Έχετε χωρίσει το εργατικό δυναμικό σε ομάδες με συγκεκριμένες λειτουργίες.

Πχ η ομάδα Α γεμίζει με νερό την δεξαμενή και η ομάδα Β αδειάζει την δεξαμενή. Εσείς είστε ο operator, αυτό που διευθύνει τι θα γίνει. Οι ομάδες Α και Β είναι οι operands που αποτελούν τις λειτουργίες τις οποίες μπορείτε εσείς ως operator να χειριστείτε.

Στο πιο πάνω παράδειγμα, έχουμε:

Operator: << και >>

Operands: std::cout, "Hello World!", std::endl

Κάθε operator έχει ένα type που τον αντιπροσωπεύει. Δεν μπορεί να χειριστεί ( operate ) τα πάντα όλα. Δεν μπορείς να βάλεις έναν χειριστή ντοματοσαλάτας στην θέση ενός πιλότου αεροσκάφους. Όπως δεν μπορείς να βάλεις έναν πιλότο στην θέση ενός χειριστή μιάς εγχείρισης. Ο καθένας τους χειρίζετε διαφορετικά πράγματα. Έτσι λοιπόν, στην C++ ο τύπος ( type ) ενός operator εξαρτάται αποκλειστικά από αυτά που καλείτε να ελέγξει – δηλαδή τους τελεστέους ( operands ). Ό,τι τύπου είναι οι operands, ίδιου τύπου πρέπει να είναι και ο operator.

Στο πρόγραμμά μας, ο operand std::cout έχει τύπο [noparse]std::ostream [/noparse] (παρέχει streamed output ).

Ο << operator

Αυτός ο φίλος μας, παίρνει δύο operands. Έναν στα αριστερά του και έναν θα δεξία του.

Αριστερός_operand << Δεξιός_operand

Ορίστε:

std::cout << "Hello, world!"
Στα αριστερά έχουμε το std::cout το οποίο είναι μία εντολή, treated ως operand στην expression, ο οποίος δε operand είναι τύπου [noparse]std::ostream[/noparse].

Στα δεξία έχουμε το "Hello,world!" το οποίο ένα string literal (δηλ. ένα απλό κείμενο) τύπου ( ; ; ; μυστήριο ) , το οποίο είναι treated operand στην expression.

Ο << operator είναι left-associative, πράγμα που σημαίνει ότι ο τελεστής κοιτάει πάντα τον τύπο του operand που βρίσκεται στα αριστερά.

Τώρα θα μου πείτε … «ωραία όλα αυτά, ΑΛΛΑ ΤΙ ΚΑΝΕΙ ;»

… και θα σας απαντήσω: Ο << ή αλλιώς Output Operator γράφει αυτό που είναι στα δεξιά του, σ’ αυτό που βρίσκεται στα αριστερά του. Γράφει/Μεταφέρει τον δεξίό_operand στον αριστερό_operand.

Συγκεκριμένα, στο παράδειγμά μας, γράφει το "Hello world" στο output stream ( το οποίο αντιπροσωπεύει το DOS ή αλλιώς το terminal της οθόνης μας). Σωστά ; (ρητορική ερώτηση, φυσικά και είναι σωστά :D ).

ΠΡΟΣΟΧΗ

Έχω κάνει ένα φάουλ και εσείς δεν το έχετε προσέξει. Είπα, πριν ότι ο << operator δέχεται δύο operands. Μήπως μπορείτε να μου εξηγήσετε γιατί στο παράδειγμα έχω 2 << operators και 3 operands ; Δείτε την εικόνα και θα καταλάβετε ;)

[ATTACH]7332[/ATTACH]

Ο δεύτερος << operator έχεις ως αριστερό όρισμα το αποτέλεσμα του πρώτου, το οποίο είναι τύπου [noparse]std::ostream[/noparse]. Και ως δεξι όρισμα έχει το [noparse]std::endl[/noparse].

είναι σαν να έχετε γράψει:

( std::cout << "hello, world!" ) << std::endl

Το std::endl είναι ένας χειριστής ( manipulator ) που ελέγχει το streaming ( κυρίως το output ). Αντιγράφοντας τον std::endl manipulator στο [noparse]std::ostream[/noparse] σημαίνει ότι τερματίζουμε την περεταίρω εισαγωγή χαρακτήρων στην ίδια γραμμή. Ως αποτέλεσμα επιστρέφει το ίδιο το stream τροποποιημένο . Για παράδειγμα ίσως δείτε τον cursor στην από κάτω γραμμή ή αν είχατε βάλει ένα ακόμα string literal μετά το std::endl με χρήση ενός ακόμα output operator, θα βλέπατε ότι θα εμφανιζόταν στην από κάτω γραμμή.

Για να επανέλθουμε στην αρχή, όλο αυτό:

std::cout << “Hello, world!” << std::endl;

είναι μία expression η οποία έχει προφανώς side effects, τα οποία είναι να γράψει Hello World! στο [noparse]std::ostream[/noparse] και κατόπιν να τερματίσει την τρέχουσα γραμμή με τον manipulator std::endl.

Όπως βλέπετε υπάρχει ένα ελληνικό ερωτηματικό --->; ή αλλιώς μία άνω-τελεία για τους ξένους. Αυτό δηλώνει το τέλος μίας expression αλλά και κάτι ακόμη που λίγοι το γνωρίζουν. Η παρουσία του semi-colon ( ; ) λέει στον compiler να αγνοήσει την τιμή της expression και να ασχοληθεί μόνο με το side effect. Η τιμή που θα πάρει, ποιος θα την πάρει, πού θα πάει και τι θα γίνει, ΔΕΝ μας ενδιαφέρει. Το 4+3 έχει κάποιο νόημα έτσι ; Το παραπάνω παράδειγμά (αναφέρομαι στο Hello world), δεν έχει κάποια αριθμητική τιμή. Είναι μια αλληλουχία από ενέργειες πάνω στο standard output stream. Συνεπώς αυτό που μας ενδιαφέρει είναι το αποτέλεσμα αυτού – δηλ το side effect της expression. Γι αυτό τον λόγο βάζουμε στο τέλος κάθε expression το σύμβολο semi-colon.

Εδώ να σας πω κάτι που την έχουν πατήσει αρκετά άτομα. Καταρχάς να ξέρετε ότι το να ξεχνάτε το semi-colon είναι το πιο κοινό λάθος στον προγραμματισμό της C++ . Κατά δεύτερον να χρησιμοποιείτε πάντα το αγγλικό layout στο πληκτρολόγιο. Εγώ είχα βάλει το ελληνικό ερωτηματικό και συνέχιζε να μου πετάει σφάλμα ο debugger ότι απουσιάζει το semi-colon από την expression. Αυτό συμβαίνει γιατί ο compiler ( g++ ) δέχεται μόνο αγγλικό semi-colon. Σε άλλους μπορεί να παίξει, σε άλλους πάλι όχι. Εγώ έχω το καθήκον να σας το επισημάνω πριν τραβήξετε τα μαλλιά σας και αναρωτιέστε «μα γιατί».

Η δεύτερη έννοια ( scope )

Scope είναι η ονομασία που δίνουμε σ’ ένα μέρος/τμήμα του κώδικά . Αυτό το τμήμα πρέπει να έχει κάτι το κοινό, γι αυτό και άλλωστε θα του δώσουμε ένα όνομα. Αποτελεί το lifetime των εντολών που έχουν να κάνουν με το τμήμα αυτό καθ’αυτό. Για παράδειγμα ο πρώτος scope που συναντήσαμε είναι το namespace. Το namespace είναι ένας χώρος στην standard library όπου τμηματοποιούνται οι εντολές.

Πχ το cout και το cin είναι εντολές του std namespace που σχετίζονται με το Input / Output. Συνεπώς όταν γράφουμε

std::cout 

λέμε ότι είναι qualified name, το οποίο χρησιμοποιεί τον :: operator. Ο :: operator είναι γνωστός ως scope operator, όπου δηλώνει ότι εδώ έχουμε να κάνουμε με εντολή που προέρχεται από ένα scope ( συγκεκριμένα από το namespace std ). Το αριστερό μέρος είναι το qualified name του scope ( std ) και το δεξί είναι το όνομα που έχει γίνει defined μέσα στο namespace για την συγκεκριμένη λειτουργία. Κάπως έπρεπε να τον ονομάσουν, να ονομάσουν την εντολή που να είχε σχέση με το Output, το οποίο είναι μέρος του std namespace , και όπως κάθε namespace, από την στιγμή που μοιράζεται ένα κοινό χαρακτηριστικό/γνώρισμα και αποτελεί ένα τμήμα, αποτελεί ταυτόχρονα και scope. Οι εντολές ζούν μέσα στο scope και όχι έξω από αυτό. Αν γράψετε cout χωρίς το std θα είναι λάθος. Επίσης το stdcout πάλι είναι λάθος γιατί δεν αναφέρετε πουθενά στον compiler ότι το std είναι qualified name ενός scope με τον operator :: . πχ το

forum::ban << Kostas  

θα μπορούσε να πει κανείς ότι forum είναι ένα qualified name, δηλαδή ένα qualified name του OOS ( outofspecs ) και το ban αποτελεί το όνομα την εντολή που χρησιμοποιούμε για να τιμωρήσουμε κάποιον, πχ τον χρήση Kostas.

Είπαμε ότι scope είναι ένα τμήμα προγράμματος που περιέχει όμοια χαρακτηριστικά και είναι αναπόσπαστο. Ένας τρόπος για να αναγνωρίζετε scope είναι οι αγκύλες { } γνωστές ως curly braces. Η συνάρτηση main() αρχίζει και τελειώνει με αγκύλες, συνεπώς είναι ένας scope. Όλες οι συναρτήσεις αποτελούν τον δικό τους scope αφού οι μεταβλητές και ότι άλλο υπάρχει ανάμεσα στις δύο αγκύλες «ζει» μόνο μέσα στην συνάρτηση. Συνεπώς όλες οι functions αποτελούν έναν scope. ;)

Περίληψη

Προς το παρών, έχουμε κάνει μόνο το Hello World σαν πρόγραμμα, αλλά όπως βλέπετε και οι ίδιοι υπάρχουν τόσα πολλά πράγματα που αρκετός κόσμος τα αγνοεί. Αυτά όμως είναι, πιστεύω, πολύ σημαντικά για την σωστή κατανόηση της C++. Θέλω να έχετε πλήρη κατανόηση ακόμα και του space που πατάτε στο πρόγραμμα. Να γνωρίσετε, το γιατί και το πώς και να μην αντιγράφετε ή παίρνετε έτοιμη μασημένη τροφή ( χμ, τουλάχιστον όχι για αρχή :p ).

Είδαμε τα σχόλια, τα οποία εισάγονται έτσι:

[B]// [/B][I]μπλα μπλα μπλα[/I]

Για να γράψετε multi-line σχόλια θα χρησιμοποιήσετε τα free-form comments: /*μπλα μπλα μπλα */

*/ Αυτό το πρόγραμμα έχει αναλαμβάνει να βάλει
Την κατάλληλη ποσότητα ταμπάσκό.
ΠΡΟΣΟΧΗ: Μπορεί να κάψετε τον υπολογιστή σας
ΠΡΟΣΟΧΗ: Σιγουρευτείτε ότι υπάρχει δροσερό νερό στα waterblocks */

Επίσης γνωρίσαμε μερικούς τύπους δεδομένων. Η C++ έχει δύο τύπους δεδομένων: built-in όπως είναι πχ το int, double, char κλπ και άλλους που έχουν γίνει define από την Standard Library, όπως πχ το [noparse]std::ostream[/noparse] και δεν έχουν να κάνουν με τον πυρήνα της γλώσσας.

Γνωρίσαμε τα namespaces ως έναν μηχανισμό συσκευασίας ονομάτων που έχουν σχέση μεταξύ τους. Τα ονόματα που προέρχονται από την standard library γίνονται define στο std namespace.

Είδαμε τα string literals, τα οποία, (δώστε προσοχή ) αρχίζουν και τελειώνουν με διπλά εισαγωγικά

 [B]"[/B] [I]κείμενο[/I] [B]"[/B]

Το String literal δεν μπορεί να σπάσει σε γραμμές.

Πχ είναι λάθος το

"σήμερα
Πήγα
Στην τουαλέτα"

Ενώ είναι σωστό το

"σήμερα πήγα στην τουαλέτα"

Υπάρχουν μερικοί special characters που έχουν ειδική μεταχείριση μέσα σε ένα string literal. Και οι πιο συχνά χρησιμοποιούμενοι είναι:

  • \n : Εισάγει νέα γραμμή
  • \t : Αφήνει περιθώριο ένα tab
  • \ “ : Μεταχειρίζεται το \ ως μέρος του κειμένου

Στην συνέχεια μιλήσαμε για την συνάρτηση main() και πώς αυτή επιστρέφει την τιμή 0, καθώς και ότι κάθε συνάρτηση πρέπει να αρχίζει και να τελειώνει με αγκύλες. Πράγμα που σημαίνει ότι αποτελεί έναν scope.

ΑΣΚΗΣΕΙΣ:

Για όσους είναι η πρώτη φορά που θα στείλουν εργασία, καλό θα ήταν να διαβάσουν αυτό πρώτα.

  1. Kάντε compile το πρόγραμμα hello world!
  2. Γράψτε ένα πρόγραμμα που θα γράφει τους στίχους από το Master Of Puppets των Metallica ή οποιδήποτε άλλο μουσικό τραγούδι σας αρέσει.
  3. Τι κάνει το παρακάτω statement: 3+4;
  4. Γράψτε ένα πρόγραμμα με tab κενό και πειραματιστείτε μαζί του. Βρείτε πόσα space ισοδυναμούν με το κενό ενός tab. Να φαίνεται στο πρόγραμμα!
  5. Είναι αυτό σωστό:


#include <iostream>

int main()

std::cout << "hello, world!"<< std::endl;


6. Αυτό ;


#include <iostream>

int main() {{{{{{ std::cout<< "Helo world!" << std::endl; }}}}}}


</blockquote>

7) Αυτό ;


#include <iostream>

int main()

{

/* Λοιπόν είστε σίγουροι

Ότι /* ισχύει /* το πρόγραμμα */

std::cout << "Johnny got his gun" <<std::endl;

return 0;

}


8) Αυτό ;


#include <iostream>

int main()

{

// Λοιπόν είστε σίγουροι

/* // ότι // ισχύει αυτό το

πρόγραμμα */ σίγουρα; */

std::cout << "Γκολάρα!!! "<<std::endl;

return 0;

}

9) Πιο είναι το πιο μικρό πρόγραμμα που παίζει χωρίς error;

10) Ξανα γράψτε το Hello World και όπου υπάρχει κενό στο string literal να το αντικαταστείτε με μία νέα γραμμή ( newline).

post-928-1414343391,8288_thumb.jpg

Link to comment
Share on other sites

  • 2 weeks later...

LESSON 3

Στα πρώτα δύο μαθήματα είδαμε πως με'ενα κυριολεκτικά μικροσκοπικό πρόγραμμα μπορούμε να εισάγουμε βασικές έννοιες στην C++ : σχόλια, standard headers, scopes, namespaces, expressions, statements, string literals και έξοδο. Σ'αυτό το κεφάλαιο θα δούμε με την ίδια παρόμοια μεθοδολογία ενός μικρού προγράμματος, τα character strings. Στην διάρκεια του μαθήματος, θα μάθουμε να κάνουμε declare τις variables ( μεταβλητές ) και πώς να τις κάνουμε initialization ( αρχικοποίηση ), καθώς και να παίξουμε λίγο με την string βιβλιοθήκη της standard library. Τα προγράμματα σάυτό το κεφάλαιο είναι τόσο απλά τα οποία δεν χρειάζονται καν να γνωρίζεται δομές ελέγχου ( πράγμα που θα μάθουμε μεταγενέστερα ).

Αφού γράψουμε ένα κείμενο, η λογική σειρά που κάνουμε τα πράγματα μας λέει ότι το επόμενο βήμα είναι αν το διαβάσουμε/αναγνώσουμε. Για παράδειγμα, μπορούμε να προσαρμόσουμε το Hello World! πρόγραμμα να λέει hello σε ένα συγκεκριμένο άτομο.


// ask for a person's name and greet the person
#include <iostream>
#include <string>

int main()
{
//ask for person's name
std::cout << "Please enter your first name: ";

// read the name
std::string name; // define name
std::cin >> name; // read name

// write a greeting
std::cout << "Hello, " << name << "!" << std::endl;
return 0;
}

Επειδή αυτή τη στιγμή είμαι σε linux με το G++ Compiler και δουλεύω με το arch, η εντολή για να κάνετε compile είναι:


g++ onoma_arxeiou.cpp -o onoma_arxeiou
./onoma_arxeiou

Όταν το εκτελετε θα δείτε ότι το πρόγραμμα θα γράψει στην οθόνη σας:

Please enter your first name:
Αν απαντήσουμε, πχ γράφοντας
Paneas
τότε το πρόγραμμα θα γράψει:
Hello Paneas!
Ας ρίξουμε μια ματιά και αν δούμε τι γίνεται σ'αυτό το μικρό πρόγραμμα που μόλις εκτελέσαμε. Προκειμένου να διαβάσουμε ότι εισέρχεται από το πληκτρολόγιο, πρέπει πρώτα να φροντίσουμε να φτιάξουμε ένα μέρος όπου θα το βάλουμε. Αυτό το μέρος λέγεται μεταβλητή ( variable ). Μεταβλητή είναι μία θέση μνήμης μέσα στον υπολογιστή σας, συγκεκριμένα μέσα στην μνήμη ram, όπου την δευσμεύουμε και της αποθηκεύουμε τιμές τις οποίες μπορούμε στην συνέχεια να τςι σβήσουμε και να βάλουμε άλλες τιμές. Προγραμματιστικά θα λέγαμε ότι η μεταβλητή είναι ένα αντικείμενο το οποίο έχει ένα όνομα. Ένα όνομα, το οποίο κατοχυρώνεται στην μνήμη του υπολογιστή και έχει έναν δικό του τύπο αρχείων. Για παράδειγμα αν σκοπεύετε να αποθηκεύσετε αριθμητικές τιμές, θα φτιάξετε μια μεταβλητή που θα αποθηκεύονται αριθμητικές τιμές κλπ. Αυτό είναι μία πολύ σημαντική διαφορά ανάμεσα στα αντικείμενα και στις μεταβλητές. Υπάρχει πιθανότητα να έχουμε αντικείμενο χωρίς όνομα ( θα το δούμε πολύ αργότερα αυτό ). Αλλά, αντικείμενο + όνόμα = μεταβλητή .

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

Σ'αυτό το παράδειγμα η μεταβλητή μας είναι ονομασμένη με το όνομα name και είναι τύπου std::string. Όπως μάθαμε στα προηγούμενα μαθήματα, το std:: υποδηλώνει ότι το string είναι ένα μέρος της standard library και όχι μέρος του πυρήνα της γλώσσας C++. Όπως έχουμε πει, το std::string έχει εναν δικο του standard header ο οποίος δηλώνεται στην αρχή του προγράμματος <string> , με την οδηγία #include έτσι ώστε να ενσωματώσουμε την λειτουργία character string στο πρόγραμμά μας.

Θέλουμε να έχουμε characters string στο πρόγραμμά μας, συνεπώς τα ζητάμε από την standard library.

Το πρώτο statement του προγράμματος μας είναι:

std::cout << "Please enter your first name: ";

το οποίο πρέπει να σας είναι οικειο μέχρι τώτσ το τι κανει, αφού έχουμε δει παρόμοια cout statements. Αυτό που κάνει το συγκεκριμένο είναι να γράφει ένα μύνημα ζητώντας τον χρήστη να γράψει το username του. και στο τέλος όπως βλέπεται δεν υπάρχει ο manipulator για να κάνει end line, πράγμα που σημαίνει ότι το επόμενο I/O θα γραφτεί στην ίδια σειρά και όχι στην επόμενη. Μόλις εμφανιστεί λοιπόν το μύνημα, θα δείτε ότι βγαίνει ο cursor ή αλλιώς prompt ( όπως θέλετε μπορείτε να το λέτε ) και περιμένει να εισάγετε δεδομένα, συγκριμένα περιμένει να γράψετε το username του χρήστη.

Το έπομενο statement:

std::string name

Αυτό είναι κάτι που συναντάμε για πρώτη φορά και ονομάζεται definition ( ορισμός ). Εδώ φτιάχνουμε μια μεταβλητή, η οποία έχει όνομα name και τύπου std::string. Για να φτιάξουμε μια μεταβλητή, δηλαδή για την ορίσουμε, να την δημιουργήσουμε γράφουμε πρώτα τον τύπο της, και στην συνέχεια γράφουμε το όνομά της. πχ

int axladia

είναι μια μεταβλητή τύπου ( int --> ακέραια ) η οποία ονομάζεται axladia. Προς το παρών δεν έχουμε δώσει κάποια τιμή, αλλά όπως είπαμε έχουμε φτιάξει τον χώρο, το αντικείμενο το οποίο θα φιλοξενίσει τα δεδομένα τα οποία θα εισάγουμε στον υπολογιστή μας. Φαντάζεστε για ποια δεδομένα λέμε ( ; ) , για το username του χρήστη. Το username είναι μια σειρά από αλφαρηθμιτικούς χαρακτήρες οι οποίες θέλουμε να γίνουν treated ως string characters, συνεπώς ο σωστός τύπος για να το κάνουμε αυτό είναι std::string . Ο τύπος της μεταβλητής δεν μπορεί να αλλάξει. Δεν μπορείτε να έχετε int name αφού θα αποθηκεύσουμε κείμενο και όχι αριθμούς. Οπότε το μόνο μέρος του definition που μπορείτε να τροποιποιήσετε κατα βούληση είναι το όνομα της πχ

std::string username

. Είναι μία μεταβλητή τύπου std::string με όνομα username. Προγραμματιστικά θα λέγαμε ότι είναι μία θέση μνήμης στον υπολογιστή που δέχεται μέσα της δεδομένα string.

Επειδή η μεταβλητή αυτή βρίσκεται εντός της main function, ισχύει και υπάρχει όσο βρίσκεται μέσα στο scope της main. Όταν τερματίσει η main() τότε θα σβηστεί η μεταβλητή από την μνήμη του υπολογιστή μας και συνεπώς θα ελευθερωθεί ο χώρος που χρησιμοποιήθηκε από το πρόγραμμα. Αυτή η μεταβλητή που γίνεται define μέσα σε function λέγεται τοπική μεταβλητή ή αλλιώς local variable, για τον λόγο για τον οποίον "ζει" όσο το πρόγραμμα βρίσκεται εντός της function. Εδώ, η main function όταν τερμαίζεται, τερματίζει μαζί της και το ίδιο το πρόγραμμα, συνεπώς με το πέρας του προγράμματος σβήνεται και η μεταβλητή ;)

Δίνοντας ένα όνομα το object μας, το οποίο είναι τύπου std::string , αυτομάτως το μετατρέπουμε σε μεταβλητή. Έτσι όλες οι λειτουργίες που μπορούν να γίνουν με δεδομένα std::string , μπορούν να γίνουν αναφέροντας μόνο το όνομα της μεταβλητής. Δηλαδή το όνομα name. Οποιδήποτε επεξεργασία θα γίνει στο όνομα της μεταβλητής, το οποίο την αντιπροσωπεύει.

Το επόμενο λογικό βήμα είναι να αποθηκεύσουμε κάτι ανάλογο σ'αυτήν την μεταβλητή μας. Η standard library μας λέει ότι δεν πρέπει να έχουμε κενές std::string μεταβλητές συνεπώς το επόμενο μας βήμα θα είναι να της δώσουμε κάποια τιμή, κάποια δεδομένα να κρατάει. Αν δεν δώσουμε, τότε το string έχει κένους χαρακτήρες, και γίνεται αυτό που λέμε emtpy ή null string.

αφού λοιπόν έχουμε κάνει define το name δίνουμε:

std::cin >> name;

Αυτό το statement διαβάζει από το std::cin ( standard input ) τα δεδομένα και τα στέλνει στο name ( μεταβλητή τύπου std::string ). ανάλογα με τον << operator και το std::cout για το output τώρα έχουμε τον >> operator και το std::cin για το input. Σε αυτό το παράδειγμα το >> διαβάζει ένα string από το standard input το οποίο θα είναι το username που δώσαμε (πχ Paneas, Antonis, Hadji κλπ ) και το αποθηκεύει στο object name. Όταν ζητάμε από την standard library να διαβάσει ένα string αυτή αρχίζει να απορίπτει το whitespace ( χαρακτήρες όπως space, tab, backspace ή end of line) από το standard input και διαβάζει μέχρι μόνο να βρει whitespace ξανά. Αυτό σημαίνει πως αν γράψετε "Doctor Paneas" η standard library θα διαβάζει μόνο το doctor αφού μετά υπάρχει whitespace. Το paneas θα το απορρίψει, δεν το λάβει καν υπόψην της. Ετσι, όταν χρησιμοποιούμε το std::cin >> name στην ουσία θέλουμε να αποθηκεύσουμε μία και μόνο μία λέξη και όχι μία φράση ή 2 και παραπάνω λέξεις.

Η λειτουργία της εισόδους έχει ένα ακόμα side effect: Τον cursor ( prompt) να αναβοσβήνει και να περιμένει να εισάγετε δεδομένα από το πληκτρολόγιο. Γενικά να ξέρετε ότι η input - ouput library αποθηκεύει τα δεδομένα σε έναν εσωτερικό buffer, ο οποίος βελτιώνει το output και το προσαρμόζει στον υπολογιστή. Τα περισσότερα συστήματα χρειάζονται αρκετό χρόνο για να γράψουν χαρακτήρες σε μία συσκευή εξόδου, άσχετα από το πόσοι χαρακτήρες χρειάζονται. Για να αποφύγετε την επιβάρυνση του συστήματός σας η library χρησιμοποιεί τον buffer ως output device, μόνο όταν είναι απαραίτητο, και τον απελάσει ( flush ) γράφοντας νέα δεδομένα στην device.

Τον buffer τον κάνουμε flush σε τρεις μονάχα περιπτώσεις:

  • 1) Ο buffer μπορεί να είναι γεμάτος, στην περιτωση αυτή η C++ θα τον κάνει flush αυτόματα.
  • 2) Όταν ζητάτε από την library να διαβάσει από το standard input stream ( όταν κάνετε cin >> ) . Σε αυτή την περίπτωση η library κάνει flush αμέσως τον output buffer χωρίς να περιμένει να δει αν είναι γεμάτος ή όχι.
  • 3) Όταν ζητάμε εμείς να γίνει flush :D

Όταν το πρόγραμμά μας γράφει στο output, τότε χρησιμοποιεί τον cout buffer. Όταν μετά κάνουμε cin, τότε αδειάζει ο input buffer και o cout buffer ώστε ο χρήστης να δει ξανά για 2η φορά την prompt να αναβοσβήνει. Αυτό όπως έιπαμε γίνετε αυτόματα ( βλ 2 ).

Το επόμενο statement το οποιο παράγει τον τελικό χαιρετισμό σε μία γραμμή output είναι ένα cout statement. Αρχικά γίνεται flush o cout buffer και στην συνέχεια έχουμε το string literal " Hello, " το οποίο ακολουθείτε από την τιμή του string της μεταβλητής name, και τέλος με το std::endl . γράφοντας std::endl στο τέλος της εντολής, τελειώνει η τρέχουσα γραμμλη και επίσης γίνεται ξανά flush o buffer, έτσι αναγκάζεται το σύστημα να εμφανίσει τώρα τον output buffer αφού έχει λάβει αίτηση να τον κάνει flush.

Κάνοντας flush τους output buffers όταν και μόνο όταν χρειάζεται να το κάνετε χειροκίνητα είναι μία καλή συνηθεια. Σε μεγάλα προγράμματα που έχουν πολλές γραμμές κώδικα και παίζουν συνέχεια με output και input συχνά υπάρχει υπερχίληση των buffers λόγων λάθων στον κώδικα με αποτέλεσμα να ψάχνεται αν βρείτε το λάθος και να μην το βρίσκετε.

Ασκήσεις:

  1. Να εκτελέσετε σωστά τον παραπάνω κώδικα.
  2. Να γράψετε ένα πρόγραμμα που θα ζητάει τον αριθμό τον cores που έχετε στον CPU σας και στην συνέχεια να σας εμφανίζει κατάλληλο μήνυμα.
  3. Να διαμορφώσετε έτσι το αρχικό πρόγραμμα ώστε να μπορώ να δώσω ονοματεπώνυμο σε μία και μόνο σε μία μεταβλητή. Όσοι δεν τα καταφέρετε, δοκιμάστε με δύο μεταβλητές.
  4. Ζητείστε από τον χρήστη να σας πει πόσο χρονών είναι. Σε περίπτωση που αντί για νούμερο δώσει καταλάθος λάθος τιμή (πχ πατήσει ένα γράμμα), τότε να του εμφανιστεί μήνυμα ότι έκανε λάθος και να ξανα προσπαθήσει ( χρειάζεται γνώση loop για να το κάνετε ). Όσοι είστε αρχάριοι μην το δοκιμάσετε.

Link to comment
Share on other sites

  • 2 weeks later...

Lesson 4

Στα προηγούμενα προγράμματα ασχοληθήκαμε κυρίως με έναν απλό χαιρετισμό. Τώρα ήρθε η στιγμή να δούμε πως μπορείτε να κάνετε αυτόν τον χαιρετισμό ακόμα πιο περίτεχνο προσθέτοντας ένα πλαίσιο. Ο λόγος που θα το κάνουμε αυτό είναι γιατί καταρχάς θα παίξουμε λίγο ακόμα με strings για να υπάρχει μεγαλύτερη εξοικείωση. Κατά δεύτερον πιστεύω πως είναι ωραίο να δείχνετε την καλλιτεχνική σας φύση ακόμα και μέσα στον source code.

Το πρόγραμμα:

Να γράψει ο καθένας ένα πρόγραμμα για το username του μέσα σε ένα πλαίσιο από αστεράκια.

[ATTACH]7669[/ATTACH]

Το πρόγραμμα παράγει 5 γραμμές.

Η πρώτη γραμμή ξεκινάει το πλαίσιο το οποίο αποτελείται από μία σειρά αστερίσκων, τόσους όσο είναι το μήκος του username, συν μερικοί χαρακτήρες που να ταιριάζουν με τον χαιρετισμό ( "Hello, " ) συν ένα space και 1 αστεράκι σε κάθε άκρη.

Η δεύτερη γραμμή είναι μια σειρά αποτελούμενη από τον κατάλληλο αριθμό των spaces και 2 αστεράκια στο τέλος.

Η τρίτη γραμμή είναι ένας αστερίσκος *, ένα space και το μύνημα, ένα space και ένας ακόμα αστερίσκος *.

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

Μία βολική στρατηγική είναι να φτιάξετε ένα ευέλικτο Output ώστε να μπορείτε να το αναπροσαρμόσετε σε κάθε πρόγραμμα. Προφανώς μπορείτε να κάνετε cout ακριβώς το ίδιο μήνυμα copy paste. Αλλά τι θα γίνει αν θέλετε να αλλάζει για κάθε username ; Οπότε΄έχουμε μπροστά μας ένα έξυπνο πρόγραμμα εμφάνισης στο output με πιο κομψό τρόπο.

Ο κώδικας μας:


#include <iostream>
#include <string>

int main()
{
std::cout << "Please enter your Username: ";
std::string username;
std::cin >> username;

// build the message that we intend to write
const std::string greeting = "Hello, " + username ;

// build the seconds and forth lines
const std::string spaces(greeting.size(), ' ');
const std::string second = "* " + spaces + " *";

// build the first and fifth lines
const std::string first(second.size(), '*');

// write em all
std::cout << std::endl;
std::cout << first << std::endl;
std::cout << second <<std::endl;
std::cout << "* " << greeting << " *" << std::endl;
std::cout << second << std::endl;
std::cout << first << std::endl;

system("PAUSE");
return 0;
}

Η πρώτη γραμμή ζητάει το username του χρήση και το αποθηκεύει στην αντίστοιχη μεταβλητή usernameπου είναι τύπου string . Μετά κάνουμε define την μεταβλητή greeting η οποία είναι επίσης τύπου string και θα κρατάει το format του χαιρετισμού.

Προσέξτε πόσο έξυπνα χρησιμοποιούμε το τον operator + για να υλοποιήσουμε τα επιμέρους strings
:)
Όπως βλέπετε το
+
δεν έχει καμία σχέση με το 3+4 = 7, γιατί εδώ δ
εν προσθέτει αριθμητικές μεταβλητές, αλλά strings
πράγμα που σημαίνει ότι ο operator έχει μία διαφορετική λειτουργία.
Όπως είχαμε πει στο 2ο μάθημα
, ο operator έχει να κάνει με τους
Operands
που του δίνονται αριστερα και δεξία του. Ο operator 3 + 4 προφανώς θα εκτελέσει την πρόσθεση έχοντας ως operands αριθμητικές τιμές 3 και 4. Όμως στην περίπτωσή μας ο ίδιος πάλι operator + έχει ως operand 2
literals
.

Έτσι βλέπουμε πως μπορούμε να ενώσουμε 2 literals και να τα κάνουμε ένα string.

Ας δούμε όμως καλύτερα τι παίζει με αυτή την greeting για να καταλαβαίνουμε τι κάνουμε:


std::cout << greeting << std::endl;
std::cout << "Length: " << greeting.size() << std::endl;

Και το

Output:

Hello, Dr.Paneas

Length: 16

Εδώ θα κάνουμε μία στάση να μελετήσουμε το greeting.size() . Αυτός είναι ένας τρόπος να καλέσουμε μία member function. Μία function ( συνάρτηση ) η οποία ανήκει στην μεταβλητή greeting επειδή είναι string. Όλες οι string μεταβλητές έχουν μία member function με όνομα size(). Ο τρόπος για να καλέσουμε μία member function είναι γράφοντας τελείας, το όνομα της member function και τις παρενθέσεις (). πχ superman.powers() ή system.restart() κλπ κλπ. Η συνάρτηση επιστρέφει όπως έιχαμε πει ΜΙΑ τιμή. Η main επιστρέφει το 0, αν θυμάστε που το λέγαμε στο πρώτο μάθημα. Εδώ η συνάρτηση size επιστρέφει τον αριθμό των χαρακτήρων του string . Δηλαδή επιστρέφει έναν αριθμό: 16 στην συγκεκριμένη περίπτωση, έναν ακέραιο αριθμό - για να είμαστε απόλυτα ακριβείς.

Αφού είδαμε τι αποθηκεύσαμε στην greeting μεταβλητή, καθώς και το μήκος της, συνεχίζουμε με την μεταβλητή spaces. Εδώ έχουμε ένα ακόμα κόλπο των strings. Λέμε ότι η μεταβλητή spaces θα έχει μέσα της τόσους χαρακτήρες, όσους έχει η μεταβλητή greeting. Δηλαδή 16 χαρακτήρες. Τι χαρακτήρες όμως ;

Απ: κενά --> ' ' . Ανάμεσα στα δύο quotes ΄΄υπάρχει κενό.

Οπότε η μεταβλητή spaces αποτελείται από 16 κενά. Αν δίναμε διαφορετικό username πχ "Vagouridis" τότε θα άλλαζε το μήκος της greetings και κατα συνέπεια θα άλλαζε και το μήκος της spaces. Έτσι, έχουμε κάνει πολύ ευέλικτο τον κώδικά μας.

Βλέπετε έναν ακόμα τρόπο declaration μεταβλητής.


std::string spaces(greeting.size(), ' ');

Εμείς γνωρίζουμε:

const std::string spaces = " "  ; 

Αλλά έτσι θα πρέπει να γράψουμε 16 φορές το space, και πάλι θα φτιάξουμε πρόγραμμα αποκλειστικά μόνο για το Username Dr.Paneas.

με τον τρόπο: μεταβλητη(τιμή) μπορούμε να πετύχουμε διάφορα tricks και να το έχετε πάντα υπόψην σας. Γράφοντας λοιπόν:


std::string spaces(greeting.size(), ' ');

λέμε να βάλεις τόσα κενά, όσο είναι το μήκος της μεταβλητής string greeting. Αφού καταλάβαμε τι γίνετε εδώ, πάμε στην επόμενη γραμμή. Η επόμενη γραμμή αποτελεί μία σειρά από αστεράκια. Πώς είμαι θα την κάνουμε ευέλικτη ; Παρατηρούμε ότι αποτελείται από την μεταβλητή spaces που είναι 16 κενά, και επίσης μας μένουν 2 κενά και 2 αστεράκια αντίστοιχα στις άκρες. Στη αριστερή άκρη έχουμε αστεράκια και κενό, ενώ στην δεξία έχουμε κενό και αστεράκι.

Κάτι που ξεχάσαμε να αναφέρουμε είναι η παρουσία της εντολής const. Όταν μπαίνει η const μπροστά από τις μεταβλητές σημαίνει ότι οι μεταβλητές αυτές ΔΕΝ ΜΠΟΡΟΥΝ ΝΑ ΠΑΡΟΥΝ ΑΛΛΗ ΤΙΜΗ. Είναι πλέον σταθερές. Ο λόγος που το κάνουμε αυτό είναι γιατί δεσμεύουν ακόμα λιγότερο χώρο στην μνήμη, και αφού δεν έχουμε σκοπό να αλλάξουμε στην συνέχεια του προγράμματός μας τις μεταβλητές, τις κάνουμε const. Το πώς θα καταλαβένετε ποιες μεταβλητές θα κάνετε σταθερές είναι θέμα εμπειρίας ( πχ αν γράφετε ένα μαθηματικό πρόγραμμα θα ορίσετε το pi 3.14 ως const ή πχ την επιτάχυνση βαρύτητας με 10. ).

Τύπου δεδομένων που μάθαμε έμμεσα με αυτή την άσκηση:

  • char: Built-in τύπος ο οποίος κρατάει τους συνηθισμένους αλφαριθμητικούς χαρακτήρες.
  • wchar_t : Bult-in τύπος που έχει πρόθεση να κρατήσει μεγάλους χαρακτήρες, όπως πχ οι χαρακτήρες της Ιαπωνικής γλώσσας.
  • string: Έχει γίνει define στον standard header <string> . Είναι ένα αντικείμενο τύπου string που περιέχει μία σειρά από κανέναν ή περισσότερους χαρακτήρες. Αν το n είναι ένας ακέραιος, το c είναι ένας χαρακτήρας char, το is είναι το input stream και το os είναι το output stream, τότε το string περιλαμβάνει τις ακόλουθες λειτουργίες:

std::string s;

Ορίζει το s σαν μεταβλητή τύπου std::string η οποία είναι αρχικά κενή, χωρίς χαρακτήρες μέσα της.

std::string t = s

Ορίζει το t σαν μεταβλητή τύπου std::string η οποία περιέχει τους ίδιους χαρακτήρες με την μεταβλητή s που είναι επίσης string ή θα μπορούσε να ήταν ένα string literal.

std::string z(n,c)

Ορίζει το z σαν μεταβλητή τύπου std::string η οποία αρχικά περιέχει n φορές τον χαρακτήρα που περιέχει στην μεταβλητή c. Το c πρέπει να είναι αποκλειστικά char και όχι τύπου string ή string literal.

os << s

Γράφει τους χαρακτήρες που περιέχονται στην μεταβλητή s, χωρίς κάποιες αλλαγές στο Output stream.

is >> s

Διαβάζει χαρακτήρες από τον χρήστη ως εισοδο και σταματάει μόνο όταν δώσουμε 'κενό' / space .

s + t

Το αποτέλεσμα είναι ένα std::string το οποίο περιέχει τα δύο αυτά strings ενσωματωμένα σ'ένα, κολλητά. Μπορεί είτε το t είτε το s να είναι char ή literal αλλά ΠΟΤΕ και τα δύο μαζί ταυτόχρνα. Το ένα πρέπει να είνα οπωσδήποτε std::string.

s.size()

Ο αριθμός των χαρακτήρων του s

ΑΣΚΗΣΕΙΣ

  1. Τρέξτε το παραπάνω πρόγραμμα και κατανοήστε πως λειτουργεί.
  2. Είναι σωστές οι ακόλουθες προτάσεις:

    const std::string hello = "Hello";
    const std::string message = hello + ",world" + "!";


  3. Είναι σωστές οι ακόλουθες προτάσεις:

    const std::string exclam = "! ";
    const std::string message = "Hello" + ",world" + exclram;


  4. Είναι σωστές ; Αν ναι, τι κάνει το πρόγραμμα ; Αν όχι, τι φταίει ;

    #include <iostream>
    #include <string>

    int main()
    {
    {
    const std::string s = "ema string";
    std::cout << s << std::endl;
    }

    {
    const std::string s = "ena allo string";
    std::cout <<s << std::endl;
    }

    system("PAUSE");
    return 0;
    }


  5. Είναι σωστές ; Τι θα γίνει αν αλλάξω το }} σε };} ;

    #include <iostream>
    #include <string>

    int main()
    {
    {
    const std::string s = "ema string";
    std::cout << s << std::endl;

    {
    const std::string s = "ena allo string";
    std::cout <<s << std::endl;
    }}

    system("PAUSE");
    return 0;
    }


  6. Είναι σωστές ; Αν ναι, τι κάνει το πρόγραμμα ; Αν όχι, ξαναγράψτε το πρόγραμμα σωστα και πείτε πιο ήταν το λαθος.

    #include <iostream>
    #include <string>

    int main()
    {
    { std::string s = "ena string";
    { std::string x = s + "; ali8eia einai string ? ";
    std::cout << s << std::endl; }
    std::cout << x << std::endl;
    }

    system("PAUSE");
    return 0;
    }


  7. Γράψτε ένα πρόγραμμα με δικό σας framing, και να είναι το ίδιο ευέλικτο. Να ζητάει όσα στοιχεία θέλετε.

post-928-1414343414,2468_thumb.png

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

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

Important Information

Ο ιστότοπος theLab.gr χρησιμοποιεί cookies για να διασφαλίσει την καλύτερη εμπειρία σας κατά την περιήγηση. Μπορείτε να προσαρμόσετε τις ρυθμίσεις των cookies σας , διαφορετικά θα υποθέσουμε ότι είστε εντάξει για να συνεχίσετε.