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

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

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

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

Δημοσίευσηαπό Ilias95 » 10 Μαρ 2012, 15:40

Να και η λύση μου στο programming project 6 στη σελίδα 239:

Μορφοποιημένος Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <stdlib.h> // exit()

#define STACK_SIZE 30

#define IS_FULL (top == STACK_SIZE)
#define IS_EMPTY (top == 0)
#define CLEAR_STACK (top = 0)

int operands_stack[STACK_SIZE];
int top = 0;

int read(void);
void push_to_stack(int x);
int pop_from_stack(void);
void compute(char ch);
void print_and_clear(void);
void stack_overflow(void);
void stack_underflow(void);


int main(void)
{
for (;;) {
printf("Enter an RPN expression: ");
if (read() == 1)
exit(EXIT_SUCCESS);
}
}

int read(void) {
char ch;

for (;;) {
scanf(" %c", &ch);
if (ch >= '0' && ch <= '9') {
int x = ch - '0';
push_to_stack(x);
}
else if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
compute(ch);
else if (ch == '=') {
print_and_clear();
break;
}
else
return 1;
}
return 0;

}

void push_to_stack(int x) {
if (IS_FULL)
stack_overflow();
else
operands_stack[top++] = x;
}

int pop_from_stack(void) {
if (IS_EMPTY) {
stack_underflow();
return 0;
}
else
return operands_stack[--top];
}

void compute(char ch) {
int a = pop_from_stack(), b = pop_from_stack();
switch (ch) {
case '+': push_to_stack(b + a); break;
case '-': push_to_stack(b - a); break;
case '*': push_to_stack(b * a); break;
case '/': push_to_stack(b / a); break;
}
}

void print_and_clear(void) {
printf("Value of expression: %d\n", operands_stack[top - 1]);
CLEAR_STACK;
}

void stack_overflow(void) {
printf("Expression is too complex.\n");
exit(1);
}

void stack_underflow(void) {
printf("Not enough operands in expression.\n");
exit(1);
}

Δύο πράγματα δεν μου αρέσουν.
1. Ότι πρέπει να δηλώνω κάθε φορά το prototype της κάθε function (αυτό γενικά στη γλώσσα, ανεξάρτητα απ' το πρόγραμμα).
2. Ότι αναγκάστηκα να χρησιμοποιήσω global μεταβλητές λόγο του ότι δεν μπορώ από μία συνάρτηση να επιστρέψω παραπάνω από μία τιμές.

Βέβαια έχω την εντύπωση ότι με χρήση pointers μπορείς να μεταβάλεις τις τιμές κάποιων local μεταβλητών μίας συνάρτησης μέσα από μια άλλη συνάρτηση.
Αλλά θα το δω παρακάτω αυτό. Ή υπάρχει άλλος τρόπος να αποφύγω την χρήση global variables σε ένα πρόγραμμα σαν το παραπάνω;
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 11 Μαρ 2012, 01:44

Στην Σελιδα 71 στην τελευταια ασκηση

Τα αποτελέσματα θα ειναι :

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


(a) i+=j; -> i = 3 , j = 2 το j μένει ως έχει ενω το i αυξάνεται κατα j φορες. Αρα 1 + j => 1 + 2 = 3

(b) i--; -> 2

(c) i * j/i ; -> Επειδη οι τελεστές * , / βρίσκονται στο ιδιο επίπεδο προτεραιότητας η εκτέλεση προκύπτει απο αριστερά προς τα δεξιά

Άρα 3 * 2 = 6 / 3 = 2

(d) i % ++ j = 1


Στο (d) δεν μπορω να καταλαβω το γιατι... πιστευω το ++j εκτελειται πρωτο και μετα έχουμε το υπολοιπο βεβαια
σε δοκιμες δικιες μου στον compiler έδινε 0 για i=2 και j=4 ενω κανονικα θα επρεπε 0 μιας και 2 / 5 δινει 0 υπολοιπο.
Γνώσεις ⇛ 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

Δημοσίευσηαπό Star_Light » 11 Μαρ 2012, 01:48

Ilias95 έγραψε:Να και η λύση μου στο programming project 6 στη σελίδα 239:

Μορφοποιημένος Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <stdlib.h> // exit()

#define STACK_SIZE 30

#define IS_FULL (top == STACK_SIZE)
#define IS_EMPTY (top == 0)
#define CLEAR_STACK (top = 0)

int operands_stack[STACK_SIZE];
int top = 0;

int read(void);
void push_to_stack(int x);
int pop_from_stack(void);
void compute(char ch);
void print_and_clear(void);
void stack_overflow(void);
void stack_underflow(void);


int main(void)
{
for (;;) {
printf("Enter an RPN expression: ");
if (read() == 1)
exit(EXIT_SUCCESS);
}
}

int read(void) {
char ch;

for (;;) {
scanf(" %c", &ch);
if (ch >= '0' && ch <= '9') {
int x = ch - '0';
push_to_stack(x);
}
else if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
compute(ch);
else if (ch == '=') {
print_and_clear();
break;
}
else
return 1;
}
return 0;

}

void push_to_stack(int x) {
if (IS_FULL)
stack_overflow();
else
operands_stack[top++] = x;
}

int pop_from_stack(void) {
if (IS_EMPTY) {
stack_underflow();
return 0;
}
else
return operands_stack[--top];
}

void compute(char ch) {
int a = pop_from_stack(), b = pop_from_stack();
switch (ch) {
case '+': push_to_stack(b + a); break;
case '-': push_to_stack(b - a); break;
case '*': push_to_stack(b * a); break;
case '/': push_to_stack(b / a); break;
}
}

void print_and_clear(void) {
printf("Value of expression: %d\n", operands_stack[top - 1]);
CLEAR_STACK;
}

void stack_overflow(void) {
printf("Expression is too complex.\n");
exit(1);
}

void stack_underflow(void) {
printf("Not enough operands in expression.\n");
exit(1);
}

Δύο πράγματα δεν μου αρέσουν.
1. Ότι πρέπει να δηλώνω κάθε φορά το prototype της κάθε function (αυτό γενικά στη γλώσσα, ανεξάρτητα απ' το πρόγραμμα).
2. Ότι αναγκάστηκα να χρησιμοποιήσω global μεταβλητές λόγο του ότι δεν μπορώ από μία συνάρτηση να επιστρέψω παραπάνω από μία τιμές.

Βέβαια έχω την εντύπωση ότι με χρήση pointers μπορείς να μεταβάλεις τις τιμές κάποιων local μεταβλητών μίας συνάρτησης μέσα από μια άλλη συνάρτηση.
Αλλά θα το δω παρακάτω αυτό. Ή υπάρχει άλλος τρόπος να αποφύγω την χρήση global variables σε ένα πρόγραμμα σαν το παραπάνω;


1. Οχι αν τις συναρτήσεις τις γράφεις - ορίζεις στην αρχή . Δηλαδη πανω απο την κεντρική συνάρτηση ( main )

2. Οχι. Οι συναρτήσεις στην C μπορούν να επιστρέψουν μοναχα μια τιμή καθε φορα . Για αυτο και δουλευεις με δεικτες μεσα στις συναρτήσεις
για να αλλάζεις τα περιεχόμενα της μνήμης σου εκ νέου. Αυτο που λες πιο μετα αναφέρεται σε προσομοίωση του call "by reference" στην C μεσω των δεικτων. Στην C δεν υπάρχουν πραγματικες αναφορες.

Btw θα μπορουσαμε να το συζητησουμε εκτενέστερα αλλα προχωραω πιο αργα οπως εχω αποφασισει εξαρχης.... δεν ξερω αν με ζημιώσει ή οχι αλλα ειναι καθαρα προιον δικης μου επιλογης. ;)
Γνώσεις ⇛ 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

Δημοσίευσηαπό migf1 » 11 Μαρ 2012, 03:14

Όπως είπε και ο Κώστας, για να μπορείς να μεταβάλεις τις τιμές των ορισμάτων μιας συνάρτησης, περνάς στην συνάρτηση τη διεύθυνση των μεταβλητών που αντιστοιχούν στα ορίσματα, και κατόπιν μέσα στη συνάρτηση δηλώνεις και διαχειρίζεσαι τα ορίσματα ως δείκτες

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

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

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

Δημοσίευσηαπό Ilias95 » 11 Μαρ 2012, 03:31

Star_Light έγραψε:Οχι αν τις συναρτήσεις τις γράφεις - ορίζεις στην αρχή . Δηλαδη πανω απο την κεντρική συνάρτηση ( main )

Απλά είδα τον King να προτείνει να γράφεται πάνω πάνω η main.
Πάντως κάποια στιγμή ούτως ή άλλως θα χρειαστούν τα prototypes.

Star_Light έγραψε:Για αυτο και δουλευεις με δεικτες μεσα στις συναρτήσεις για να αλλάζεις τα περιεχόμενα της μνήμης σου εκ νέου.

Ναι κάτι τέτοιο έχω καταλάβει. Απλά δεν έχω φτάσει ακόμα στους δείκτες.
Οπότε στο συγκεκριμένο παράδειγμα η χρήση των global variables ίσως ήταν μονόδρομος.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 11 Μαρ 2012, 03:45

Ilias95 έγραψε:
Ναι κάτι τέτοιο έχω καταλάβει. Απλά δεν έχω φτάσει ακόμα στους δείκτες.
Οπότε στο συγκεκριμένο παράδειγμα η χρήση των global variables ίσως ήταν μονόδρομος.

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

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

Δημοσίευσηαπό Ilias95 » 11 Μαρ 2012, 03:53

migf1 έγραψε:
Ilias95 έγραψε:
Ναι κάτι τέτοιο έχω καταλάβει. Απλά δεν έχω φτάσει ακόμα στους δείκτες.
Οπότε στο συγκεκριμένο παράδειγμα η χρήση των global variables ίσως ήταν μονόδρομος.

Οι πίνακες περνάνε έτσι κι αλλιώς by reference τα στοιχεία τους στις συναρτήσεις, οπότε εφόσον τη στοίβα (stack) την έχεις υλοποιημένη ως πίνακα, θα μπορούσες να την περνάς σαν όρισμα στις συναρτήσεις (και να γλίτωνες τις καθολικές μεταβλητές).

Σωστά. Υπάρχει και η μεταβλητή top όμως που είναι integer. Και κάποιες συναρτήσεις πρέπει να επιστρέψουν άλλη τιμή (όπως η pop_from_stack()).
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 11 Μαρ 2012, 03:59

@migf1 δηλαδη θεωρεις πως αν γνωρίζω οτι οι παρενθέσεις εκτελούνται πάντα πρωτες και ουσιαστικά άρουν την υπόλοιπη προτεραιότητα της συνολικής έκφρασης... ειμαι εντάξει??? Σε καποια σημεια γινομαι λεπτολόγος επειδη νομιζω πως θα εξασκήσω το μυαλο μου καλυτερα. Εχω αδικο κατα την γνωμη σου?
Τελευταία επεξεργασία από Star_Light και 11 Μαρ 2012, 03:59, έχει επεξεργασθεί 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

Δημοσίευσηαπό migf1 » 11 Μαρ 2012, 03:59

@Ilias: Ναι, αυτή δεν μπορείς να την αποφύγεις. Για δομές έχεις μιλήσει ή όχι ακόμα;
Τελευταία επεξεργασία από migf1 και 11 Μαρ 2012, 04:01, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 11 Μαρ 2012, 04:01

Star_Light έγραψε:@migf1 δηλαδη θεωρεις πως αν γνωρίζω οτι οι παρενθέσεις εκτελούνται πάντα πρωτες και ουσιαστικά άρουν την υπόλοιπη προτεραιότητα της συνολικής έκφρασης... ειμαι εντάξει??? Σε καποια σημεια γινομαι λεπτολόγος επειδη νομιζω πως θα εξασκήσω το μυαλο μου καλυτερα. Εχω αδικο κατα την γνωμη σου?

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

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

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