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

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

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

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

Δημοσίευσηαπό migf1 » 03 Απρ 2012, 13:53

Οκ, αφαίρεσα από το αρχείο input τα περιττά που είχε στην αρχή, και το πέρασα στον κώδικα που έδωσα παραπάνω...

Win7 Home 64bit, i3 M350 @ 2.27GHz
Κώδικας: Επιλογή όλων

Dell@Dell-Laptop /cygdrive/c/unix/mysrc/c/pdp
$ time ./pdp24.exe
-4999990 4999990

real 0m0.686s
user 0m0.031s
sys 0m0.015s
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 03 Απρ 2012, 23:04

migf1 έγραψε:
stamatiou έγραψε:Δηλαδή να έχω έναν μετρητή i στην αρχή του πίνακα και ένα στο τέλος του πίνακακαι να μετράνε και οι 2 προς το κέντρο; Δεν πολυκαταλαβαίνω το τρόπο λύσης....

Αυτό που είπε ο Σίμος είναι και η δική μου άποψη: http://ideone.com/Oq8aL

Το δοκίμασα μονάχα με τα παραδείγματα εισόδου της εκφώνησης. Το αρχείο input που δίνει, σε εμένα σε Windows το δείχνει ως binary. Κάνε δοκιμές χρόνου, κλπ και φτιάξε το να τυπώνει το αποτέλεσμα σε αρχείο (απενεργοποίησε και την buffer_print() για να μη σου τυπώσει 1.000.000 νούμερα).

Σε αυτό το σημείο:
Κώδικας: Επιλογή όλων
for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )

Μπορείς να μου εξηγήσεις τι ακριβώς ελέγχεις με το !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]);
Επίσης για το FCLOSE και το FREE γιατί χρησιμοποιείς ένα do while loop εφόσον ξέρεις πως η συνθήκη θα βγει false;
Τέλος, αυτό:
Κώδικας: Επιλογή όλων

if ( sum < 0 )
istart++;
else
iend--;

γιατί το κάνεις;
Off topic:
Μήπως μπορεί κανείς να βρει κανένα καλό tutorial για τον αλγόριθμο merge sort αλλά για C. Τον αλγόριθμο τον έχω καταλάβει αλλά δεν μπορώ να τον υλοποιήσω με κώδικα :(
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 03 Απρ 2012, 23:33

stamatiou έγραψε:
Σε αυτό το σημείο:
Κώδικας: Επιλογή όλων
for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )

Μπορείς να μου εξηγήσεις τι ακριβώς ελέγχεις με το !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]);

Το !feof(fp) ελέγχει να μην είναι έχει τελειώσει το αρχείο και το 1 == fscanf(fp, "%ld", &(*buf)[i] ελέγχει να μην έχει αποτύχει η fscanf().

έγραψε:Επίσης για το FCLOSE και το FREE γιατί χρησιμοποιείς ένα do while loop εφόσον ξέρεις πως η συνθήκη θα βγει false;

Διότι πρόκειται για macros και όχι για συναρτήσεις (το έχω εξηγήσει με παράδειγμα και στον Ηλία μερικές σελίδες πιο πριν).

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

if ( sum < 0 )
istart++;
else
iend--;

γιατί το κάνεις;

Διότι πρέπει να προχωρήσουν οι indexers, να πάνε στον επόμενο αριθμό. Από τη στιγμή που οι αριθμοί είναι ταξινομημένοι σε αύξουσα σειρά, αν το sum βγει αρνητικό σημαίνει πως αναφέρεται στον indexer που είχε ξεκινήσει από την αρχή του buf, ενώ αν είναι θετικό σημαίνει πως αναφέρεται στον indexer που είχε ξεκινήσει από το τέλος του buf.

έγραψε:Off topic:
Μήπως μπορεί κανείς να βρει κανένα καλό tutorial για τον αλγόριθμο merge sort αλλά για C. Τον αλγόριθμο τον έχω καταλάβει αλλά δεν μπορώ να τον υλοποιήσω με κώδικα :(

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

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

Δημοσίευσηαπό stamatiou » 04 Απρ 2012, 17:39

migf1 έγραψε:
stamatiou έγραψε:
Σε αυτό το σημείο:
Κώδικας: Επιλογή όλων
for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )

Μπορείς να μου εξηγήσεις τι ακριβώς ελέγχεις με το !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]);

Το !feof(fp) ελέγχει να μην είναι έχει τελειώσει το αρχείο και το 1 == fscanf(fp, "%ld", &(*buf)[i] ελέγχει να μην έχει αποτύχει η fscanf().

έγραψε:Επίσης για το FCLOSE και το FREE γιατί χρησιμοποιείς ένα do while loop εφόσον ξέρεις πως η συνθήκη θα βγει false;

Διότι πρόκειται για macros και όχι για συναρτήσεις (το έχω εξηγήσει με παράδειγμα και στον Ηλία μερικές σελίδες πιο πριν).

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

if ( sum < 0 )
istart++;
else
iend--;

γιατί το κάνεις;

Διότι πρέπει να προχωρήσουν οι indexers, να πάνε στον επόμενο αριθμό. Από τη στιγμή που οι αριθμοί είναι ταξινομημένοι σε αύξουσα σειρά, αν το sum βγει αρνητικό σημαίνει πως αναφέρεται στον indexer που είχε ξεκινήσει από την αρχή του buf, ενώ αν είναι θετικό σημαίνει πως αναφέρεται στον indexer που είχε ξεκινήσει από το τέλος του buf.

έγραψε:Off topic:
Μήπως μπορεί κανείς να βρει κανένα καλό tutorial για τον αλγόριθμο merge sort αλλά για C. Τον αλγόριθμο τον έχω καταλάβει αλλά δεν μπορώ να τον υλοποιήσω με κώδικα :(

Πιστεύω πως αν ψάξεις στο google όλο και κάτι θα βρεις.

Εδώ:
Κώδικας: Επιλογή όλων
for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )

γιατί γράφεις fscanf(fp, "%ld", &(*buf)[i]) και όχι fscanf(fp, "%ld", &buf[i]);
έγραψε:Διότι πρέπει να προχωρήσουν οι indexers, να πάνε στον επόμενο αριθμό. Από τη στιγμή που οι αριθμοί είναι ταξινομημένοι σε αύξουσα σειρά, αν το sum βγει αρνητικό σημαίνει πως αναφέρεται στον indexer που είχε ξεκινήσει από την αρχή του buf, ενώ αν είναι θετικό σημαίνει πως αναφέρεται στον indexer που είχε ξεκινήσει από το τέλος του buf.

Εδώ δεν καταλαβαίνω γιατί αν είναι αρνητικό πρέπει να αυξηθεί το istart ενώ αλλιώς πρέπει να μειωθεί το iend....
Όσο για τα macros θα το ψάξω λίγο και αν έχω ερωτήσεις θα ποστάρω....
Off topic:
Να σε έχει ο Θεός καλά γιατί αν δεν με βοηθούσες στη C θα ήμουν αιώνες πίσω :D :bow:
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 04 Απρ 2012, 18:18

stamatiou έγραψε:
Εδώ:
Κώδικας: Επιλογή όλων
for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )

γιατί γράφεις fscanf(fp, "%ld", &(*buf)[i]) και όχι fscanf(fp, "%ld", &buf[i]);

Διότι το buf το περνάω by-reference στην συνάρτηση (ως διπλό δείκτη δηλαδή ή ως *[] αν το καταλαβαίνεις καλύτερα). Οπότε μέσα στην συνάρτηση, το buffer μας είναι το *buf και όχι το buf. Δηλαδή ο πίνακάς μας είναι ο *buf και το σκέτο buf είναι η διεύθυνση του πίνακα (δεν είναι η διεύθυνση του 1ου στοιχείου του πίνακα)

έγραψε:Εδώ δεν καταλαβαίνω γιατί αν είναι αρνητικό πρέπει να αυξηθεί το istart ενώ αλλιώς πρέπει να μειωθεί το iend....

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

έγραψε:Off topic:
Να σε έχει ο Θεός καλά γιατί αν δεν με βοηθούσες στη C θα ήμουν αιώνες πίσω :D :bow:

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

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

Δημοσίευσηαπό simosx » 04 Απρ 2012, 22:38

simosx έγραψε:
stamatiou έγραψε:Δηλαδή να έχω έναν μετρητή i στην αρχή του πίνακα και ένα στο τέλος του πίνακακαι να μετράνε και οι 2 προς το κέντρο; Δεν πολυκαταλαβαίνω το τρόπο λύσης....


Υπάρχουν αρκετές επιλογές όταν έχεις όλη τη λίστα των αριθμών σε έναν πίνακα.
Τι θα επέλεγες για να επιλύσεις το πρόβλημα, έχοντας όλους τους αριθμούς σε ένα πίνακα;


Θα πρότεινα να δοκιμάσεις να επιλύσεις το πρόβλημα με τις δικές σου δυνάμεις. Μπορούμε εδώ να συζητήσουμε σχετικά με το ζήτημα.
Ως πρώτη εργασία προτείνω να φτιάξεις πρόγραμμα που να διαβάζει το αρχείο εισόδου και να βάζει τα νούμερα σε ένα πίνακα.
Μόνο αυτό, ως πρώτο βήμα. Βάζεις και όσα printf() θέλεις ώστε να φαίνεται τι γίνεται κατά την εκτέλεση.
Μόλις το κάνεις, μπορούμε να δούμε πως θα γίνει η επεξεργασία του πίνακα για να εξαχθούν τα ζεύγη των αριθμών.
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 04 Απρ 2012, 23:14

simosx έγραψε:
simosx έγραψε:
stamatiou έγραψε:Δηλαδή να έχω έναν μετρητή i στην αρχή του πίνακα και ένα στο τέλος του πίνακακαι να μετράνε και οι 2 προς το κέντρο; Δεν πολυκαταλαβαίνω το τρόπο λύσης....


Υπάρχουν αρκετές επιλογές όταν έχεις όλη τη λίστα των αριθμών σε έναν πίνακα.
Τι θα επέλεγες για να επιλύσεις το πρόβλημα, έχοντας όλους τους αριθμούς σε ένα πίνακα;


Θα πρότεινα να δοκιμάσεις να επιλύσεις το πρόβλημα με τις δικές σου δυνάμεις. Μπορούμε εδώ να συζητήσουμε σχετικά με το ζήτημα.
Ως πρώτη εργασία προτείνω να φτιάξεις πρόγραμμα που να διαβάζει το αρχείο εισόδου και να βάζει τα νούμερα σε ένα πίνακα.
Μόνο αυτό, ως πρώτο βήμα. Βάζεις και όσα printf() θέλεις ώστε να φαίνεται τι γίνεται κατά την εκτέλεση.
Μόλις το κάνεις, μπορούμε να δούμε πως θα γίνει η επεξεργασία του πίνακα για να εξαχθούν τα ζεύγη των αριθμών.

Πήγα να κάνω μια υλοποίηση σε συνάρτηση αλλά κάποια χαζομάρα έχω κάνει με τους δείκτες:
Κώδικας: Επιλογή όλων

#include <stdio.h>

int store_buffer(long int **buffer, long int n) {
FILE *input = fopen("operators.in","r");
int i;
for(i = 0; i < n; i++)
fscanf(input,"%ld",&(*buffer)[i]);
return 0;
}

int main(void) {
long int array[5],n;
FILE *input = fopen("operators.in","r");
fscanf(input,"%ld",&n);
store_buffer(&array,n);
for(n = 0; n < 5; n++)
printf("%ld",array[n]);
return 0;
}

Τι του λέω να κάνει και μου βγάζει ο compiler:
Κώδικας: Επιλογή όλων

basic.c:15: warning: passing argument 1 of ‘store_buffer’ from incompatible pointer type
basic.c:3: note: expected ‘long int **’ but argument is of type ‘long int (*)[5]’
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό simosx » 04 Απρ 2012, 23:19

stamatiou έγραψε:note: expected ‘long int **’ but argument is of type ‘long int (*)[5]’


Ναι, δε φαίνεται να ταιριάζουν τα ορίσματα. Άλλο δηλώνεις και άλλο δίνεις στη συνάρτηση.

Προτείνω να τα βάλεις για τώρα όλα στη main(), οπότε δε χρειάζεται να καλέσεις κάποια συνάρτηση.
Αυτό θα απλοποιήσει και τον κώδικά σου, μιας και ανοίγεις παραπάνω το αρχείο δύο φορές.
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 04 Απρ 2012, 23:36

simosx έγραψε:
stamatiou έγραψε:note: expected ‘long int **’ but argument is of type ‘long int (*)[5]’


Ναι, δε φαίνεται να ταιριάζουν τα ορίσματα. Άλλο δηλώνεις και άλλο δίνεις στη συνάρτηση.

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

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

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

int main(void) {
int n,*array,i;
FILE *input;
if(!(input = fopen("operators.in","r"))) {
printf("Could not open input file\n");
return 1;
}
fscanf(input,"%d",&n);
if(!(array = (int *) malloc(n * sizeof(int)))) {
printf("Could not allocate space for array\n");
}
for(i = 0; i < n; i++)
fscanf(input,"%d",&array[i]);
for(i = 0; i < n; i++)
printf("%d ",array[i]);
putchar('\n');
return 0;
}
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό simosx » 04 Απρ 2012, 23:43

stamatiou έγραψε:
simosx έγραψε:
stamatiou έγραψε:note: expected ‘long int **’ but argument is of type ‘long int (*)[5]’


Ναι, δε φαίνεται να ταιριάζουν τα ορίσματα. Άλλο δηλώνεις και άλλο δίνεις στη συνάρτηση.

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

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

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

int main(void) {
int n,*array,i;
FILE *input;
if(!(input = fopen("operators.in","r"))) {
printf("Could not open input file\n");
return 1;
}
fscanf(input,"%d",&n);
if(!(array = (int *) malloc(n * sizeof(int)))) {
printf("Could not allocate space for array\n");
}
for(i = 0; i < n; i++)
fscanf(input,"%d",&array[i]);
for(i = 0; i < n; i++)
printf("%d ",array[i]);
putchar('\n');
return 0;
}


Ωραία. Για βάλε και μερικά printf() που να βγάζουν μηνύματα όπως:
Κώδικας: Επιλογή όλων

Σύνολο αριθμών: 10
Οι αριθμοί είναι:
-2 -1 0 1 2 3 4 5 6 9


Φαίνεται πιο ωραία έτσι.
Αφού το κάνεις, περιέγραψε έναν αλγόριθμο (ακόμα και αν είναι αργός), που να βγάζει τα ζευγάρια.
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

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

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