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

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

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

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

Δημοσίευσηαπό Star_Light » 04 Φεβ 2012, 04:02

btw σαν καθαρόαιμο λαγωνικό της C που είμαι και δεν χαμπαριάζω :

Εικόνα

Uploaded with ImageShack.usέκατσα και διάβασα μερικά πράγματα και μονος μου οπως μου ειπε ο migf1 και έχω να παραθέσω αυτη τη φορά 2 παραδείγματα τα οποια ελπίζω να ειναι εντάξει και οχι μπερδεμένα πάμε :

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

#include<stdio.h>
int main()
{
int **ipp;

int i = 5, j = 6 , k = 7;
int *ip1 = &i, *ip2 = &j;

ipp = &ip1; /* Eπειδή ειναι διπλός δείκτης καταρχην θα πρεπει
να αρχικοποιηθεί με την διεύθυνση ενος άλλου δείκτη
για να δείχνει σε αυτόν , τωρα δείχνει στον ip1 που δειχνει
στην θέση μνήμης η οποία έχει δεσμευτεί για την i μεταβλητή
σχηματικά θα έχουμε : ipp -> ip -> i */

printf("\n %d \t ", **ipp); //Εκτύπωση του 5

*ipp = ip2; /* Με δεδομένο οτι ο ipp έχει ήδη αρχικοποιηθεί με ip1
Το *ipp δηλαδη τα περιεχόμενα του ip1 θα πρέπει να δείχνουν
εκει που δείχνει και ο ip2 (δηλαδή στο j) τα περιεχόμενα του ip1
ειναι πλεον η διεύθυνση της j για αυτο στην πιο κάτω εκτύπωση παιρνουμε 6 */

if(*ipp == ip1)
printf(" \n You did it \t "); // Απλός έλεγχος οτι ο δείκτης του ipp ειναι ο ip1

printf("%d", **ipp); // Εκτύπωση του 6

*ipp = &k; /*O ipp απο πριν ειναι αρχικοποιημένος με ip δηλαδη ipp -> ip1
Στα περιεχόμενα του ipp (εκει που δείχνει στον ip1) βάζουμε
την διεύθυνση της k επομένως πλεον θα ειναι
ipp -> ip -> k σε αυτο το σημείο βεβαια ο ip συνεχίζει να δείχνει
στην j πραγμα που αποδεικνύεται μιας και αμα τον απο-αναφοροποιήσουμε
με τον τελεστή * θα δώσει την τιμή που έχει αποθηκευτεί στην μεταβλητή j
*/

printf ("\n%d \t" , *ip1); // Εκτύπωση του 7

printf("%d", *ip2); // Εκτύπωση του 6

printf("\t %d", **ipp); // Εκτύπωση του 7 με τον διπλό



return 0;
}


και το 2ο :

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


#include<stdio.h>
int main()
{
int **p

, *p2 , b=1 , a=2 , *p3 ;

p=NULL;
p2=NULL;
p3=NULL;

p3=&b;

p = &p3; /* Στον p επειδή ειναι διπλός δείκτης βάζεις σαν δεξιά τιμή την διεύθυνση του p3 (πως θα τον "βρει" αλλιώς?)
O p δείχνει στον p3 που δείχνει στην b σχηματικά p -> p3 -> b
για αυτο λέμε άλλωστε πως ειναι ένας δείκτης σε δείκτη */

p2=(*p); /* Μπορείς να αρχικοποιήσεις εναν μονό με έναν διπλό δείκτη έτσι.
Ο p2 δείκτης δείχνει όπου και ο p με την διαφορά οτι το *p ειναι τα περιεχόμενα
του p που επειδη ειναι δείκτης ειναι η διεύθυνση μνήμης του p3 επομένως μιας και δείχνουν
στο ίδιο σημείο θα δείχνουν στο b. Αυτο σημαίνει πως με απο-αναφοροποιήση του p2 παίρνω
τα περιεχόμενα της μνήμης που έχει δεσμευτεί για την b δηλαδη το 1
O p έχει σαν περιεχόμενα του την διεύθυνση μνήμης του *p */

if(*p == p3)
printf("\n OK"); //Αποδεικνύεται οτι το *p φέρει περιεχόμενα διεύθυνσης του p3

printf("%d", *p2); // Εκτύπωση του 1

*p=&a; /* Μπορείς και έτσι να αρχικοποιήσεις εναν διπλό με την διεύθυνση
μιας άλλης μεταβλητής. Οπότε τωρα ο *p δείχνει στην περιοχή της μνήμης
που έχει δεσμευτεί για το a επομένως αν απο-αναφοροποιήσω τον δείκτη *p
προσθέτοντας αλλο ενα αστεράκι παίρνω τα περιεχόμενα αυτης της περιοχής */

printf("%d", **p); // Εκτύπωση του 2



return 0;
}


Aντε καληνύχτα -.-
Γνώσεις ⇛ 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 » 04 Φεβ 2012, 16:49

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

Στην συντριπτική πλειοψηφία των casual προγραμμάτων χρησιμοποιείς δείκτες είτε για να περνάς ορίσματα by-reference σε συναρτήσεις, είτε για να κάνεις προσωρινές λειτουργίες ή σύντομο housekeeping (συνήθως τοπικά μέσα σε συναρτήσεις) είτε για την κατασκευή & διαχείριση δομών δεδομένων και πινάκων.

Σε πιο προχωρημένο επίπεδο τους χρησιμοποιείς π.χ σε callback συναρτήσεις, σε αντικειμενοστραφή προγραμματισμό μέσω C, σε GUI προγραμματισμό, κλπ. Αυτά όμως είναι για πολύυυυυυυ μετά.

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

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

Δημοσίευσηαπό Star_Light » 04 Φεβ 2012, 17:33

Δηλαδη καποιος που δεν εχει αρχικα ιδεα απο δεικτες θα παει απευθειας να δει κωδικα που χρησιμοποιει δείκτη σε δομη
και μετα τον περναει σε συνάρτηση? :S

Το παραδειγμα που έβαλα ειναι για καποιον που δεν εχει ξαναδει δεικτες πχ.

Στο λεω αυτο για να μην ξεκινησουμε παλι κανα προτζεκτ με αρχη - μεση και τελος οπως οι διευθυνσιογραφοι
και μου πεις... "Αστο , ακυρο τελικα... πρεπει να δεις πραγματα που δεν ξερεις -μεμονωμενα- " :roll:

εγω τον ελεφαντα δεν μπορω να τον φαω ολοκληρο... πρεπει να τον κοψω κομματακια πρωτα και να εξετασω
καθε κομματι ξεχωριστα και αφου καταλαβω τι γινεται μετα θα το κολλησω και με τα αλλα. Δεν ξερω που ακριβως παμε
να διαφωνησουμε σε αυτο.
Γνώσεις ⇛ 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 Φεβ 2012, 01:55

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

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

Δημοσίευσηαπό stamatiou » 05 Φεβ 2012, 14:13

Χίλια συγνώμη και πάλι για την πολυήμερη απουσία μου, πορσπαθούσα να στήσω ένα FreeBSD VM και τα κατάφερα!
Λοιπόν, τι έχασα; Τίποτα σημαντικό;
Επίσης, σκέφτηκα να κάνω ένα function που να διαβάζει από ένα array και να το αποθηκεύει σε ένα 2D array αλλά ανά σειρά, δλδ αν έχουμε ένα array έτσι:
Κώδικας: Επιλογή όλων
abc\nabc

θα το αποθηκεύσει έτσι:
Κώδικας: Επιλογή όλων

1. abc
2. abc

Έχω φτάσει μέχρι εδώ: http://ideone.com/rmVSx
αλλά έχω τα παρακάτω σφάλματα στο compiling:
Κώδικας: Επιλογή όλων
read_per_line.c:4:34: error: array type has incomplete element type
read_per_line.c:18:29: error: array type has incomplete element type
read_per_line.c: In function ‘main’:
read_per_line.c:37:2: error: type of formal parameter 2 is incomplete
read_per_line.c:38:2: error: type of formal parameter 1 is incomplete

Τι σημαίνουν αυτά; :D
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 05 Φεβ 2012, 15:00

Εχεις ορίσει 2 συναρτήσεις οι οποίες δεν επιστρέφουν τιποτα .... μονο ενα return 0? Τι ειναι αυτο ? :S
Το 0 το επιστρεφει η main στο λειτουργικο συστημα οταν το προγραμμα τερματισει επιτυχως.
Αυτο φυσικα δεν ειναι το προβλημα που σου πεταει συντακτικα λάθη.

ΑΝ βάλεις μεσα στα ορισματα των συναρτήσεων τα μεγέθη στους πίνακες θα ειναι οκ αλλα μετα δεν θα κανει τιποτα
λογω του παραπανω ζητηματος. :/
Γνώσεις ⇛ 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 Φεβ 2012, 15:11

με δεικτες πρεπει να κανεις αυτο που θες σταματιου :P

Δείκτες Δείκτες Δείκτες Δείκτες .
Γνώσεις ⇛ 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 Φεβ 2012, 16:24

stamatiou έγραψε:
...
Έχω φτάσει μέχρι εδώ: http://ideone.com/rmVSx
αλλά έχω τα παρακάτω σφάλματα στο compiling:
Κώδικας: Επιλογή όλων
read_per_line.c:4:34: error: array type has incomplete element type
read_per_line.c:18:29: error: array type has incomplete element type
read_per_line.c: In function ‘main’:
read_per_line.c:37:2: error: type of formal parameter 2 is incomplete
read_per_line.c:38:2: error: type of formal parameter 1 is incomplete

Τι σημαίνουν αυτά; :D

Καλησπέρα,

σημαίνουν ότι το dbuf δεν μπορείς να το περνάς σε συναρτήσεις χωρίς να δηλώνεις το μέγεθος των διαστάσεών του (20χ20 στην περίπτωσή σου). Για να μπορείς να το περνάς χωρίς αναφορά στις διαστάσεις του, θα πρέπει να το έχεις ορίσει ως δυναμικό πίνακα: char **dbuf και να το έχεις κάνεις malloc/calloc στις διαστάσεις που χρειάζεσαι, κι απο εκεί και πέρα θα μπορείς να το περνάς σε όποια συνάρτηση θέλεις χωρίς διαστάσεις, ως: char **dbuf.

Πέρα όμως από αυτό, ο κώδικάq σου έχεις διάφορα άλλα προβλήματα. Π.χ. δεν τερματίζεις τα επιμέρους strings του dbuf με '\'0' στην read_line(), ενώ αναζητάς το '\0' ως σηματοδότη τέλους όταν πας να τα τυπώσεις στην print_double_array(). Επίσης δεν ελέγχεις πουθενά να μην δημιουργηθούν πάνω από 20 strings μέσα στον dbuf στην read_line(). Και διάφορα άλλα... π.χ. το \n μέσα σε ένα αρχείο είναι 2 χαρακτήρες: ο '\' και ο 'n' και όχι ένας αλλαγής γραμμής... ο χαρακτήρας αλλαγής γραμμής μέσα στο αρχείο μπαίνει όπου αλλάζει γραμμή στα περιεχόμενα του αρχείου. Ακόμα, το αρχείο αντί για ανάγνωση το ανοίγεις για εγγραφή, επίσης δεν κάνεις πουθενά fclose() τον δείκτη που έχεις κάνει fopen() :P ... κλπ, κλπ.

Σου παραθέτω κώδικα που κάνει αυτό που προσπαθείς να κάνεις, με στατικούς ορισμούς και των 2 πινάκων, αλλά με αλλαγμένα ονόματα (τα θεωρώ πιο κατανοητά) και με διαχωριστή (separator) τον χαρακτήρα ';'

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

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

#define MAXSTRLEN (100+1)
#define NSTRINGS 20

#define SEPARATOR ';'

/* ------------------------------------------------------ */
int print_arrstr( char arrstr[NSTRINGS][MAXSTRLEN] )
{
int i;

for (i = 0; i < NSTRINGS && arrstr[i][0] != '\0'; i++)
printf( "%d: %s\n", i, arrstr[i] );

return 0;
}

/* ------------------------------------------------------ */
int tokenize_str( char str[], char arrstr[NSTRINGS][MAXSTRLEN] )
{
int bi=0, i=0, j=0;

for (bi=0;
i < NSTRINGS && bi < MAXSTRLEN && str[bi] != '\0' && str[bi] != '\n';
bi++)
{

if (str[bi] != SEPARATOR && j < MAXSTRLEN ) {
arrstr[i][j++] = str[bi];
}
else {
arrstr[i][j] = '\0';
i++;
j = 0;
}
}

arrstr[i][j] = '\0';

return 0;
}

/* ------------------------------------------------------ */
int main( void )
{
char str[ MAXSTRLEN ] = {'\0'}; /* c-string */
char arrstr[ NSTRINGS ][ MAXSTRLEN ] = { {'\0'} }; /* array of c-strings */
FILE *fp = fopen("test4.dat", "r");

if ( !fp ) {
fputs("*** fatal error: Could not open file!\n", stderr);
exit( EXIT_FAILURE );
}

fgets( str, MAXSTRLEN, fp);
puts( str );

tokenize_str( str, arrstr );
print_arrstr( arrstr );

fclose( fp );
exit( EXIT_SUCCESS );
}


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

1234;a;bcdefgh;56;7;ijk


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

1234;a;bcdefgh;56;7;ijk

0: 1234
1: a
2: bcdefgh
3: 56
4: 7
5: ijk


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

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

Δημοσίευσηαπό migf1 » 05 Φεβ 2012, 16:41

btw, let me google that for you
Θα βρεις πολύ περισσότερες λεπτομέρειες για το πέρασμα πολυδιάστατων στατικών πινάκων σε συναρτήσεις :)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 05 Φεβ 2012, 17:21

Να σαι καλά migf1 γιατί με τέτοια προγραμματιστική χαζομάρα που με δέρνει δεν ξέρω τι θα έκανα.... :D
Αυτό γίνεται και με seperator να έχω το \n; Νομίζω όμως πως έτσι θα υπάρχει πρόβλημα με την fgets στη main...
Επίσης γιατί δεν θέλουμε να συναντήσουμε \n στο for loop της tokensize_str;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

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