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

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

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

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

Δημοσίευσηαπό Ilias95 » 23 Μαρ 2012, 21:05

Δεν χρησιμοποιώ χαρακτηριστικά ονόματα σε τόσο μικρά παραδείγματα χάριν συντομίας. (edit: ναι ίσως θα ήταν καλύτερα να χρησιμοποιούσα ονόματα όπως t1, t2)
Δεν έκανα λάθος αναθέσεις τελικά. Απλά περνούσα λάθος argument στην printf().

Αντί για:
Κώδικας: Επιλογή όλων
printf("%s\n", *z);

Πρέπει να γίνει:
Κώδικας: Επιλογή όλων
printf("%s\n", z);
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 23 Μαρ 2012, 21:13

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

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

Δημοσίευσηαπό migf1 » 23 Μαρ 2012, 21:16

@Σταματίου: Σου έγραψα τον κώδικα για να τον συγκρίνεις με τον δικό σου.

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

#define MAXELEMS 9
#define MAXINPUT (255+1)

#define ERR_INTERNAL(msg) \
printf( "*** %s(): %s\n", __func__, (msg) ? (msg) : "Internal error!" )

/* ----------------------------------------------------------- */
void arr_sort_insertion( int *arr, int nelems )
{
int j;

/* sanity check */
if ( !arr || nelems < 2 || nelems > MAXELEMS ) {
ERR_INTERNAL( "invalid array or invalid array length!" );
return;
}

/* do the sorting */
for(int i=1; i < nelems; i++)
{
int key = arr[i];
j = i-1;
while (key < arr[j] && j >=0 )
{
arr[ j+1 ] = arr[j];
j = j-1;
}
arr[ j+1 ] = key;
}

}
/* ----------------------------------------------------------- */
void arr_print( const int *arr, int nelems )
{
/* sanity check */
if ( !arr || nelems < 1 || nelems > MAXELEMS ) {
ERR_INTERNAL( "invalid array or invalid array length!" );
return;
}

/* do the printing */
for (int i=0; i < nelems; i++)
printf( "%d ", arr[i] );
putchar('\n');

return;
}
/* ----------------------------------------------------------- */
void arr_get_elements( int *arr, int nelems )
{
char input[ MAXINPUT ] = {'\0'};

/* sanity check */
if ( !arr || nelems < 1 || nelems > MAXELEMS ) {
ERR_INTERNAL( "invalid array or invalid array length!" );
return;
}

for (int i=0; i < nelems; i++ ) {
printf( "Element #%d: ", i );
fgets( input, MAXINPUT, stdin );
arr[i] = atoi(input);
}

return;
}

/* ----------------------------------------------------------- */
int asklength( void )
{
int ret = 0;
char input[ MAXINPUT ] = {'\0'};

printf( "Give array length (2 - %d): ", MAXELEMS );
fgets( input, MAXINPUT, stdin );
ret = atoi(input);

return ret < 2 || ret > MAXELEMS ? 0 : ret;
}
/* ----------------------------------------------------------- */
int main( void )
{
// int array[ MAXELEMS ] = {2,4,6,8,9,1,5,3,7};
int *array = NULL;
int nelems;

/* get length from user */
while ( 0 == (nelems = asklength()) )
; /* void */

/* create the array */
if ( NULL == (array = calloc(nelems, sizeof(int)) ) ) {
ERR_INTERNAL("out of memory!");
exit( EXIT_FAILURE );
}

/* fill-in the array from the user & print it */
arr_get_elements( array, nelems );
arr_print( array, nelems );

/* sort the array & print it */
arr_sort_insertion( array, nelems );
arr_print( array, nelems );

free( array );

system("pause"); /* windows only */
exit( EXIT_SUCCESS );
}

ΥΓ. Ο αλγόριθμός σου με την insertion-sort δεν δούλευε σωστά, τον αντικατέστησα με έναν που βρήκα έτοιμο στο νετ.
Τελευταία επεξεργασία από migf1 και 23 Μαρ 2012, 21:40, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό Ilias95 » 23 Μαρ 2012, 21:21

Βασικά αυτό που προσπαθώ να κάνω είναι να τυπώσω ένα-ένα τα strings μιας array.

Με subscripting θα γινόταν έτσι:
Μορφοποιημένος Κώδικας: Επιλογή όλων
#include <stdio.h>

#define N 3

int main(void)
{
char table[N][100] = {"abc", "def", "ghi"};
int i;

for (i = 0; i < N; i++)
printf("%s\n", table[i]);

return 0;
}

Το πρόβλημα αν πάμε να το κάνουμε με pointer arithmetic είναι το πως θα πάμε απ' το ένα string στο άλλο.

Το υλοποίησα έτσι:
Μορφοποιημένος Κώδικας: Επιλογή όλων
#include <stdio.h>

#define N 3
#define STRINGLEN 100

int main(void)
{
char table[N][STRINGLEN] = {"abc", "def", "ghi"}, *p;

for (p = table[0]; p <= table[N-1]; p += STRINGLEN)
printf("%s\n", p);

return 0;
}

Υπάρχει κάποια καλύτερη λύση;
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 23 Μαρ 2012, 21:26

Ilias95 έγραψε:Υπάρχει κάποια καλύτερη λύση;

Μπορείς να το κάνεις με string-pointer απευθείας, όπως θα έκανες και με ένα char-pointer σε ένα string. Πριν 2-3 μέρες πόσταρα κάτι παρόμοιο εδώ: http://www.insomnia.gr/topic/432310-%cf ... p__4642920

ΥΓ. Το string-array το έχω επίτηδες NULL terminated (δηλαδή το τελευταίο του string το έχω NULL) έτσι ώστε να μη χρειάζεται να κρατάω το πλήθος των strings σε ξεχωριστή μεταβλητή. Βάζω τον string-pointer sp στην αρχή του string-array months, και διατρέχω το array μέχρι να βρω NULL ;)

Μορφοποιημένος Κώδικας: Επιλογή όλων
for ( sp = months; *sp; sp++ )
...
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 23 Μαρ 2012, 21:34

Να, δες το και στο δικό σου παράδειγμα...

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

int main( void )
{
char *sarr[] = { "abc", "defghi", "jk", "lmnopqrstu", "v", "wxyz", NULL };

for (char **sp = sarr; *sp; sp++ )
printf( "%s\n", *sp );

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

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

Δημοσίευσηαπό Ilias95 » 23 Μαρ 2012, 21:45

Θα δω σε λίγο το παράδειγμα στο insomnia.

Πάντως το τελευταίο παράδειγμα που ποσταρες εδώ χρησιμεύει μόνο όταν δεν σκοπεύουμε μελλοντικά να προσθέσουμε/αφαιρέσουμε strings στην sarr.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 23 Μαρ 2012, 21:47

Ilias95 έγραψε:Θα δω σε λίγο το παράδειγμα στο insomnia.

Πάντως το τελευταίο παράδειγμα που ποσταρες εδώ χρησιμεύει μόνο όταν δεν σκοπεύουμε μελλοντικά να προσθέσουμε/αφαιρέσουμε strings στην sarr.

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

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

Δημοσίευσηαπό Ilias95 » 23 Μαρ 2012, 21:51

migf1 έγραψε:σε στατικά ορισμένους πίνακες.

Στατικά ορισμένοι είναι έτσι; :
Κώδικας: Επιλογή όλων
*sarr[] = ...

Γιατί αν ο πίνακας ήταν ορισμένος έτσι:
Κώδικας: Επιλογή όλων
char sarr[20][100] = { "abc", "defghi", "jk", "lmnopqrstu", "v", "wxyz", NULL };

Θα μπορούσες να προσθέσεις ένα string. Αλλά θα έπρεπε να μετακινείς και το NULL.

Ή κάνω λάθος;
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 23 Μαρ 2012, 22:10

Στατικά ορισμένος σημαίνει πως κάνεις μια πρόβλεψη για το μέγιστο μήκος του, τον ορίζεις με αυτό το μήκος κι από εκεί και πέρα δεν μπορείς ούτε να το μικρύνεις ούτε να το μεγαλώσεις. Οπότε εννοούσες απλώς να τον ορίσεις με μήκος μεγαλύτερο της αρχικοποίησης, ώστε να μπορείς να γεμίσεις και τα υπόλοιπα στοιχεία του αργότερα. Σε αυτή την περίπτωση ναι, με το δικό μου παράδειγμα δεν μπορείς (βέβαια εσύ δημιουργείς έναν πίνακα μεγέθους 20 * 100 * sizeof(char) bytes, ανεξάρτητα από τον αν έχεις γεμισμένο όχι, ενώ εγώ δημιουργώ έναν πίνακα με μέγεθος 7 * sizeof(char *) + 26 * sizeof(char) bytes.

Αν θεωρήσουμε πως το sizeof(char) είναι 1 byte και το sizeof(char *) είναι 4 bytes, τότε εσύ δεσμεύεις 2000 bytes, κι εγώ 728 ;)

Το εναλλακτικό του στατικά ορισμένου πίνακα είναι ο δυναμικός πίνακας, που αρχικά τον ορίζεις ως απλό δείκτη και κατόπιν μπορείς και δεσμεύεις δυναμικά όση μνήμη χρειάζεσαι, όταν την χρειάζεσαι και μπορείς μάλιστα να την αυξομειώσεις όσο και όταν θέλεις.

Υπάρχει και μια ενδιάμεση κατάσταση, τα Variable Length Arrays (VLA) τα οποία όμως έχουν αρκετούς περιορισμούς (βέβαια σε ορισμένες περιπτώσεις είναι πολύ χρήσιμα).
Τελευταία επεξεργασία από migf1 και 23 Μαρ 2012, 22:19, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

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