freestuff.gr αρχική σελίδα
 FAQFAQ    ΑναζήτησηΑναζήτηση   Λίστα ΜελώνΛίστα Μελών   Ομάδες ΜελώνΟμάδες Μελών   <b>Εγγραφή Μέλους</b>Εγγραφή Μέλους 
 ΠροφίλΠροφίλ   Επιλογές μέλους Επιλογές   Τα bookmarks μου Τα bookmarks μου   Προσωπικά μηνύματαΠροσωπικά μηνύματα 
  διαφήμιση  

Καλώς ήρθατε στο forum μας! Για να συμμετάσχετε στις συζητήσεις θα πρέπει να είσαστε μέλος. Γίνετε μέλος τώρα!.

Δείκτες - γενικά


 Forum index » Δημιουργία Web Sites, Γραφικών & Προγραμματισμός » Γλώσσες Προγραμματισμού » C, C++
Moderators:  Super-Moderators, WebDev Moderators
Εισαγωγή νέου Θέματος   Απάντηση στο Θέμα Σελίδα 1 από 2 [26 Μηνύματα]      Bookmarks Tags: γενικα Mark the topic unread :: Προηγούμενο θέμα :: Επόμενο θέμα
Σελίδα:  1, 2 Επόμενο
ΑποστολέαςΜήνυμα
vassilism


Μέλος από: 17 Μαρ 2007
Βοηθήματα: 7
Templates: 1
Scripts: 4
Μηνύματα: 256+


View users profile Visit posters website
ΜήνυμαΣτις: 20 Οκτ 2008 22:05    Θέμα: Δείκτες - γενικά Απάντηση με παράθεση  Mark this post and the followings unread

Παιδιά καλησπέρα σας.

Μετά από αρκετά χρόνια ξεθάβω πάλι την θεωρία της C και μου δημιουργούνται ξανά απορίες τις οποίες δεν είχα κατανοήσει στο παρελθόν.

Η ερώτησή μου έχει να κάνει με δείκτες.

Με τους δείκτες μπορούμε να έχουμε άμεση προσπέλαση στη μνήμη.
Επίσης μπορούμε να δούμε ποια είναι η θέση μνήμης μιας μεταβλητής.
Ωραία μέχρι εδώ.

Αυτό που δεν έχω καταλάβει είναι σε ποιες περιπτώσεις τους χρησιμοποιούμε.
Μπορούν να κάνουν ένα πρόγραμμα γρηγορότερο?
Μπορεί να δώσει κάποιος ένα παράδειγμα με απλά λόγια μήπως και το καταλάβω?

_________________
Αγγελίες - Aggelia.eu
bxenos


Μέλος από: 18 Αυγ 2008
Μηνύματα: 53

View users profile
ΜήνυμαΣτις: 21 Οκτ 2008 11:36    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Καταρχήν σε C++ έχουν απλοποιηθεί οι διαδικασίες με τις "αναφορές" και δεν είναι τόσο απαραίτητοι οι pointers.

π.χ.
κώδικας:

//ακολουθεί κωδικας C
struct {
          double x,y;
          char description[32];
} point;

void move(point *p,double dx,double dy){
        p->x += dx;
        p->y += dy;
}

//ακολουθεί κωδικας C++
void move(point& p,double dx,double dy){
        p.x += dx;
        p.y += dy;
}


για να περάσεις π.χ. ένα ολόκληρο struct σε μια συνάρτηση που θα το αλλάξει περνάς μόνο
τον pointer (ή την αναφορά του). Αλλιώς (αν δεν υπήρχαν) θα έπρεπε να περάσεις το struct ολόκληρο και να το επιστρέψεις πίσω αλλαγμένο (με return), δηλαδή δύο φορές αντιγραφή όλων των περιεχομένων του αντί για 4 bytes (ενός pointer) (βέβαια το 4 είναι ανάλογα με την υλοποίηση).

άλλο παράδειγμα η αριθμιτική με pointers
π.χ.
κώδικας:

      char s[256],*p,*d;
      int diff;
      strcpy(s,"he.........llo world");
      p = strchr(s,"he");
      d = strchr(s."lo");
      diff = d - p + 2;
      printf("ανάμεσα στο he και στο lo παρεμβάλονται %d χαρακτήρες\n",diff);


αυτά για ξεκίνημα.
vassilism


Μέλος από: 17 Μαρ 2007
Βοηθήματα: 7
Templates: 1
Scripts: 4
Μηνύματα: 256+


View users profile Visit posters website
ΜήνυμαΣτις: 21 Οκτ 2008 12:43    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Φίλε bxenos ωραίο παράδειγμα.
Βέβαια ακόμα δεν έχω κατανοήσει την φιλοσοφία.
Για να καταλάβω λίγο καλύτερα η μεγαλύτερη ευελιξία που μας δίνουν είναι όταν χρησιμοποιούμε συναρτήσεις και θέλουμε να διαχειριζόμαστε καλύτερα τις τιμές των μεταβλητών τους?

_________________
Αγγελίες - Aggelia.eu
dva_dev
Script Master

Μέλος από: 16 Σεπ 2005
Μηνύματα: 256+

View users profile Visit posters website
blog deviantART facebook linkedin 
ΜήνυμαΣτις: 22 Οκτ 2008 02:00    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Πέρα από τη (απλή) χρήση των pointers που αναφέρθηκε ήδη, ένα πολύ δυνατό σημείο τους είναι ότι μπορούν να δώσουν δυναμικά χαρακτηριστικά στο πρόγραμμά μας αφού μπορούν να δείξουν σε functions (και στη C++ ακόμα περισσότερο σε classes αλλά μην το μπλέξουμε ακόμα περισσότερο αφού μπαίνει και η ένοια του interface). Εδώ έρχονται να μας βοηθήσουν οι (function) pointers. Αντί να δείχνουν δηλαδή σε κάποια δεδομένα και όταν τους προσπελάσουμε να πάρουμε την συγκεκριμένη τιμή, δείχνουν σε κάποια συνάρτηση και μπορούμε να καλέσουμε αυτή τη συνάρτηση (με ότι παραμέτρους θα την καλούσαμε και αν το κάναμε στατικά). Ενα απλό παράδειγμα είναι το εξής (το typedef χρησιμοποιείται γιατί απλοποιεί αρκετά τη σύνταξη ώστε να είναι κατανοητή):
κώδικας:
#include <stdio.h>

int MyAdd(int a, int b)
{
   return (a + b);
}
typedef int (*PFUNC)(int, int);

int main(void)
{
   PFUNC pF;

   printf("%d + %d = %d\n", 4, 5, MyAdd(4,5));
   pF = MyAdd; //Set pointer to function MyAdd
   printf("%d + %d = %d\n", 4, 5, pF(4,5));
   return 0;
}

Για να το προχωρήσουμε λίγο ακόμα, στο bubblesort ο αλγόριθμος ταξινόμησης είναι απλός και συγκεκριμένος. Το μόνο που μπορεί να αλλάζει είναι το σημείο που γίνεται η σύγκριση ώστε να βάζει τα στοιχεία με αύξουσα με φθίνουσα, ή με οποιαδήποτε άλλη σειρά φανταστούμε.
Αντί να φτιάχνουμε λοιπόν 100 διαφορετικές υλοποιήσεις για τις 100 διαφορετικές μορφές ταξινόμησης που μπορούμε να φανταστούμε (αύξουσα/φθίνουσα/πρώτα οι ζυγοί σε αύξουσα/πρώτα οι σύνθετοι σε φθίνουσα/...), θα μπορούσαμε να φτιάξουμε απλώς κάποιες functions που να κάνουν τη σύγκριση για να αποφασίσουν αν τα στοιχεία είναι στη σειρά ή όχι, και να περάσουμε παραμετρικά όποια από αυτές τις functions θέλουμε στην μία και μοναδική function που υλοποιεί το bubble sort.
Ενα απλό (ελπίζω) παράδειγμα (με αρκετή σαβούρα για να δείχνει τη διαφορά στο αποτέλεσμα που βγαίνει) και περνάει παραμετρικά το αν θα γίνει αύξουσα ή φθίνουσα ταξινόμηση φαίνεται παρακάτω.
κώδικας:
#include <stdio.h>

//Επιστρέφουν 1 αν είναι στην σωστή σειρά αλλιώς -1
int Ascending (int a, int b) { return (a <= b) ? -1 : 1; }
int Descending(int a, int b) { return (a >= b) ? -1 : 1; }

//pointer σε function που επιστρέφει int και παίρνει δύο παραμέτρους (int, int)
//Και η Ascending και η Descending ακολουθούν αυτό το πρότυπο.
typedef int (*PSORTFUNC)(int, int);

void BubbleSort(PSORTFUNC pFunc, int* intArray, int arraySize)
{
   int i;
   while (arraySize > 1) {
      for (i=0; i<arraySize-1; ++i) {
         //Καλούμε την συνάρτηση (Ascending ή Descending) μέσω του pointer
         if ( pFunc(intArray[i], intArray[i+1]) > 0 ) {
            int tmp;
            tmp = intArray[i];
            intArray[i] = intArray[i+1];
            intArray[i+1] = tmp;
         }
      }
      --arraySize;
   }
}

void PrintArray(int* intArray, int arraySize)
{
   int i;
   for (i=0; i<arraySize; ++i) printf("%d ", intArray[i]);
   puts("");
}

void SimpleTestFunctions(PSORTFUNC pFunc)
{
   int array1[] = {3, 2, 4, 9, 8, 5, 1};

   PrintArray(array1, 7);
   BubbleSort(pFunc, array1, 7);
   PrintArray(array1, 7);
}

int main(int argc, char** argv)
{
   puts("Test with Sort Ascending");
   SimpleTestFunctions( Ascending );
   puts("Test with Sort Descending");
   SimpleTestFunctions( Descending );

   return 0;
}

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

Μέχρι εδώ έχουμε δεί πως μπορεί να αξιοποιηθεί η δυναμική κλήση συναρτήσεων, αλλά θα πει κάποιος ότι μπορούμε με κάποιες άλλες τεχνικές να πετύχουμε το ίδιο αποτέλεσμα χωρίς να πάμε μέσω pointers και ίσως με πιο απλό/πιο δομημένο/πιο ... τρόπο. Η δύναμη όμως που κρύβει αυτή η τεχνική είναι ότι μπορούμε από το πρόγραμμα μας να καλέσουμε άλλες βιβλιοθήκες που έχουμε φτιάξει εμείς (σπάνια περίπτωση) ή έχει το λειτουργικό σύστημα ή έχει υλοποιήσει κάποιος άλλος. Ακόμα περισσότερο δίνει τη δυνατότητα να δημιουργήσουμε σημεία επέκτασης η παραμετροποίησης της εφαρμογής μας, ώστε να πάει κάποιος τρίτος και ακολουθώντας συγκεκριμένους κανόνες να δημιουργήσει δικά του modules/libraries/plug-ins που θα μπορούν να προστεθούν πάνω στην εφαρμογή μας και να την επεκτείνουν ή να αλλάξουν τη λειτουργικότητα της χωρίς να χρειαστεί να πειράξουμε τον source κώδικα ο ένας του άλλου. Για την ακρίβεια πέρα από τους κανόνες που πρέπει να τους γνωρίζουμε και εμείς και ο άλλος, δεν χρειάζεται να έχουμε ο ένας τον source κώδικα του άλλου, και όταν βάλουμε μαζί το εκτελέσιμο της εφαρμογής και την βιβλιοθήκη αυτά τα δύο θα μπορούν να συνεργάζονται. Βάζοντας μετά την βιβλιοθήκη κάποιου άλλου η εφαρμογή θα μπορεί να επεκταθεί ακόμα περισσότερο ή να τροποποιηθεί η συμπεριφορά της. Χαρακτηριστικό παράδειγμα σχετικό με το forum είναι ο apache και η php με τα δεκάδες modules και plugins που έχουν δημιουργήσει developers άσχετοι με αυτούς που ασχολούνται με τον apache και την php.

Αυτό προσπαθεί να επιδείξει η παρακάτω εφαρμογή (που παρότι έχει μπεί ο κώδικας που χρειάζεται το linux έχει δοκιμαστεί μόνο σε windows). Αυτό που κάνει είναι να φορτώσει ένα plugin δυναμικά σε run time και να καλέσει μια function που κάνει κάποιους πολύπλοκους υπολογισμούς με τον αριθμό που θα δώσει σαν παράμετρο και κατόπιν αφού το plugin κάνει όλη την επεξεργασία η εφαρμογή τυπώνει το αποτέλεσμα. Επιπλέον ζηταει η εφαρμογή το version string του plugin, τα credits των δημιουργών του και τα τυπώνει (όχι τίποτα βασικά αλλά να υπάρχει κάτι για επίδειξη).

Εχουν δημιουργηθεί δύο βιβλιοθήκες που καλούνται δυναμικά (γιατί μόνο ένα δεν δείχνει τη διαφορά) και υλοποιούν τις εξής συναρτήσεις τις οποίες θέλει η εφαρμογή να καλέσει:
Calculate (η function με τους υπολογισμούς)
Version (η function που μας δίνει το version string)
Credits (η function που μας δίνει τα ονόματα των δημιουργών του plugin)

Η εφαρμογή...
Sample.c
κώδικας:
#include <stdio.h>
#include "LibraryLoader.h"

//Signature for "Calculate"
typedef int (*PFUNC)(int);
//Signature for "Version", "Credits"
typedef const char* (*PSTRFUNC)(void);

int main(int argc, char** argv)
{
   void* dll;
   PFUNC pFunction;
   PSTRFUNC pStringFunction;
   const char* versionStr;
   const char* author;

   if (argc != 2) {
      printf("Syntax:\n %s <dynamic library path>\n", argv[0]);
      return -1;
   }

       //Φορτώνει την βιβλιοθήκη που περνάμε σαν παράμετρο
   dll = LibraryLoad( argv[1] );

       //Παίρνει τη διεύθυνση της Calculate από τη βιβλιοθήκη
   pFunction = (PFUNC)LibraryFunction(dll, "Calculate");
   printf("Calculate at %s returned %d\n", argv[1], pFunction(7));

        //Παίρνει τη διεύθυνση της Version από τη βιβλιοθήκη
   pStringFunction = (PSTRFUNC)LibraryFunction(dll, "Version");
        //Καλεί την Version και κρατάει τον pointer (το string) που επιστρέφεται
   versionStr = pStringFunction();
   
        //Παίρνει τη διεύθυνση της Credits από τη βιβλιοθήκη
   pStringFunction = (PSTRFUNC)LibraryFunction(dll, "Credits");
   author = pStringFunction();
   
   printf("The version number is: %s\n", versionStr);
   printf("Credits go to %s\n", author);

        //Κλείνει τη βιβλιοθήκη που είχε φορτώσει δυναμικά
   LibraryUnload(dll);

   return 0;
}

βοηθητικός κώδικας που φορτώνει δυναμικά μια βιβλιοθήκη (σε c++ θα μπορούσε να είναι μια πολύ ωραία class, αλλά η c δεν δίνει τέτοιες πολυτέλειες)
LibraryLoader.h
κώδικας:
#ifndef __LIBRARY_LOADER__
#define __LIBRARY_LOADER__

#ifdef WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif

void*   LibraryLoad(const char* libname);
void   LibraryUnload(void* handle);
void*   LibraryFunction(void* handle, const char* funcName);

#endif //__LIBRARY_LOADER__

LibraryLoader.c
κώδικας:
#include "LibraryLoader.h"

#ifdef WIN32 /* WINDOWS CODE */

void* LibraryLoad(const char* libname)
{
   return LoadLibrary(libname);
}

void LibraryUnload(void* handle)
{
   if (handle)
      FreeLibrary((HINSTANCE)handle);
}

void* LibraryFunction(void* handle, const char* funcName)
{
   return GetProcAddress((HINSTANCE)handle, funcName);
}

#else /* LINUX CODE - UNTESTED */

void* LibraryLoad(const char* libname)
{
   return dlopen(libname, RTLD_LAZY);
}

void LibraryUnload(void* handle)
{
   if (handle)
      dlclose(handle);
}

void* LibraryFunction(void* handle, const char* funcName)
{
   return dlsym(handle, funcName);
}

#endif


το πρώτο plugin: lib
lib.c
κώδικας:
const char* versionString = "version 2.3.0.0";
const char* creditsString = "Many, but none I know!";

int Calculate(int i)
{
   return i; //Do not calculate anything, just return it.
}

const char* Version()
{
   return versionString;
}

const char* Credits()
{
   return creditsString;
}

lib.def
κώδικας:
LIBRARY   lib
EXPORTS
   Calculate
   Version
   Credits

το δεύτερο plugin: lib2
lib2.c
κώδικας:
const char* versionString = "version 1.0.0.0";
const char* creditsString = "Various Authors...";

int Calculate(int i)
{
   return i * i; //Calculate i^2
}

const char* Version()
{
   return versionString;
}

const char* Credits()
{
   return creditsString;
}

lib2.def
κώδικας:
LIBRARY   lib
EXPORTS
   Calculate
   Version
   Credits

Παραδείγματα αντίστοιχα με το παραπάνω τουλάχιστον στο linux θα έλεγα ότι αποτελούν όλες οι εφαρμογές που έχουν κάποιο configuration αρχείο και περιέχουν γραμμές που λένε ποιά modules θα φορτωθούν και ποιά όχι. Στα windows είναι μάλλον λίγο πιο πολύπλοκα τα πράγματα αφού χρησιμοποιείται αρκετά συχνά και η registry πέρα από τα configuration αρχεία(π.χ. COM objects, ActiveX) αλλά ας μην απλωθούμε ως εκεί, να δούμε πρώτα (κάποια στιγμή) τι μπορεί επιπλέον να κάνει η c++.

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

Μια προσπάθεια πάντως την έκανα... κι όσοι δεν κάνουν χαρακίρι τα ξαναλέμε.
bxenos


Μέλος από: 18 Αυγ 2008
Μηνύματα: 53

View users profile
ΜήνυμαΣτις: 22 Οκτ 2008 13:24    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Σωστό αυτό που αναφέρθηκε από τον dva_dev με τους pointer σε συνάρτηση (που στη C++ καλύπτετε εν μέρη με τις virtual functions), οπότε μια που προχωρά το πράγμα, να συμπληρώσω και το πιό χαμηλού επιπέδου setjmp.h το οποίο είναι μετάβαση σε οποιοδήποτε κομάτι κώδικα και όχι απλή κλήση σε συνάρτηση (π.χ. για υλοποίηση exceptions, parrallel processing, co-routines, κλειδωμάτων κτλ)

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

Παλιότερα (msdos εποχές) δίνοντας
κώδικας:

typedef void (* _far vfunc)(void);
vfunc reset = (vfunc)MK_FP(0xf000,0x0100);
(*reset)();
//βέβαια αν μετά απο τόσα χρόνια θυμάμε καλά την sergment διευθυνση του bios.

κάναμε reset στον υπολογιστή.
Και με
κώδικας:
unsigned char *vtxt = (unsigned char *)MK_FP(0xc800,0);
*vtxt = 'h';vtxt +=2;
*vtxt = 'e';vtxt +=2;
*vtxt = 'l';vtxt +=2;
*vtxt = 'l';vtxt +=2;
*vtxt = 'o';vtxt +=2;
γράφαμε στην οθόνη (color mode)

Τώρα δεν υπάρχει περίπτωση να λειτουργούν τα reset και οι εγγραφές σε οθόνη με την protected memory και το paging των λειτουργικών συστημάτων....
vassilism


Μέλος από: 17 Μαρ 2007
Βοηθήματα: 7
Templates: 1
Scripts: 4
Μηνύματα: 256+


View users profile Visit posters website
ΜήνυμαΣτις: 22 Οκτ 2008 17:30    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Καταρχήν παιδιά σας ευχαριστώ πολύ που μπήκατε στον κόπο να φτιάξετε τέτοια παραδείγματα και αφιερώσατε τόσο χρόνο.
Τι να πω είστε φοβεροί.

Πάντως να ξεκαθαρίσω ότι είμαι εντελώς αρχάριος και δεν έχω ιδέα από C, και αν δεν ήξερα λίγο php δεν θα καταλάβαινα τίποτα.
Όχι ότι τώρα κατάλαβα τους δείκτες αλλά μελετάω προσεκτικά τα όσα μου γράψατε και αρχίζω να μπαίνω στο νόημα.

bxenos ανέφερε:

Παλιότερα (msdos εποχές)

Εγώ αυτές τις DOS εποχές δεν τις πέτυχα, γιατί είμαι μικρός
Αλλά αυτό και αν είναι ενδιαφέρον!

Να ρωτήσω τώρα κάτι άσχετο (με τους δείκτες) που το είχα πάντα απορία I have a question...

Για να λειτουργήσει η printf που κατά συνέπεια μας επιτρέπει να τυπώνουμε μηνύματα στην οθόνη χρειάζεται να καλέσομε στο πρόγραμμα το αρχείο stdio.h.
Σωστά μέχρι εδώ?

Τώρα θέλω να σας πω πως έχω φανταστεί εγώ το όλο σκηνικό και θέλω να μου πείτε αν είναι σωστό ή λάθος.

Λοιπόν καταρχήν φαντάζομαι πως το αρχείο stdio.h περιέχει μέσα κώδικα (μάλλον σε C) το οποίο περιέχει πολλές functions.
Μια από αυτές είναι και η printf.
Αν τα παραπάνω είναι σωστά τότε μου δημιουργούνται οι εξής απορίες:
1 Η printf στην ουσία είναι function ή εντολή?
2 Είναι εφικτό να δώ στο αρχείο stdio.h το κομμάτι κώδικα που αναφέρετε στην printf?

Αυτά

_________________
Αγγελίες - Aggelia.eu
bxenos


Μέλος από: 18 Αυγ 2008
Μηνύματα: 53

View users profile
ΜήνυμαΣτις: 22 Οκτ 2008 19:18    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Οτιδήποτε υπάρχει στα αρχεία *.h (π.χ. string.h,stdio.h,stdlib.h...) είναι γενικά declaration (αναφορές) σε συναρτήσεις που είναι συχνά χρησιμοποιούμενες (π.χ. printf,strcpy), σταθερές, μικρές inline (ψεύδο)συναρτήσεις (π.χ. getc,putc).

Δεν υπάρχει ο κώδικας της printf μέσα στο stdio.h. Υπάρχει μόνο μια αναφορά για τον compiler να ξέρει ότι υπάρχει μια συναρτηση με όνομα printf, να μάθει τι τιμή επιστρέφει και τι ορίσματα χρειάζεται (ώστε να μας βοηθήσει να γλυτώσουμε λάθη από αμέλεια μας).
Οι συναρτήσεις αυτές υπάρχουν μέσα στις βιβλιοθήκες της C σε object μορφή.
π.χ.
κώδικας:
void foo(int a,double b); //αναφορά συνάρτησης (declaration)

void foo(int a,double b) { //κώδικας/ορισμός συνάρτησης (definition)
   b = a;
}

Παλιά (πρίν το ansi πρότυπο) δεν ήταν απαραίτητο να κάνεις include τίποτα (ευτυχώς αυτό πέρασε).

Αν θέλεις τον κώδικα κάποιας συνάρτησης ψάξτον στο google (π.χ. printf.c) για την συνάρτηση printf. Δεν θα σε συμβούλεβα να αρχίσεις από την printf, είναι βαριά. Δες την strlen,strcpy, strchr,strstr,atoi ... και υπάρχουν και πολλά tutorial για C/C++ κατατοπιστικά για ξεκίνημα.

Καλό διάβασμα!
vassilism


Μέλος από: 17 Μαρ 2007
Βοηθήματα: 7
Templates: 1
Scripts: 4
Μηνύματα: 256+


View users profile Visit posters website
ΜήνυμαΣτις: 22 Οκτ 2008 19:49    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Πολύ κατατοπιστικό.
Ευχαριστώ πολύ

_________________
Αγγελίες - Aggelia.eu
chief


Μέλος από: 14 Οκτ 2008
Μηνύματα: 49

View users profile Visit posters website
ΜήνυμαΣτις: 24 Οκτ 2008 14:08    Θέμα: Pointers για σύγκριση αρχείων
Περιγραφή θέματος: Εργασία με pointers και άνοιγμα - διάβασμα αρχείων
Απάντηση με παράθεση  Mark this post and the followings unread

Και από εδώ αρπάζω την ευκαιρία για να πω τους προβληματισμούς μου, βασικά είμαι στην εκπόνηση μιας εργασίας για το Παν. Μου. Είναι σε C και γενικά ζορίζομαι .. και έχω χάσει και λίγο την μπάλα αλλά αναγκαστικά ακόμα προσπαθώ.
Η εργασία είναι να δημιουργήσω ένα πρόγραμμα fcompare, το οποίο θα συγκρίνει 2 αρχεία ASCII και θα έχει 3 παραμέτρους.

/nc : Αγνόησε διάκριση κεφαλαίων-πεζών στη σύγκριση
/s : Επίστρεψε μόνο την πρώτη και την τελευταία γραμμή από ένα σύνολο συνεχόμενων διαφορετικών γραμμών
/ln : Τύπωσε και τους αριθμούς των διαφορετικών γραμμών στην έξοδο.

Για αρχή κατανοώ - και μετά από ψάξιμο - ότι χρειάζομαι τους παρακάτω headers.

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

Στην συνέχεια για τα ορίσματα θα πρέπει να τα δηλώσω στην εντολή main. Ακολούθως έχουμε:

int main(int argc, char *argv[])

Μετά δηλώνω του pointers για τα αρχεία που θα ανοίγονται.

FILE *inFile1Ptr;
FILE *inFile2Ptr;

Επανέρχομαι στην εντολή argc – argv

Περιορίζω τις επιλογές των ορισμάων μαζί και την εντολή fcompare και έχω

if(argc<3 || argc >6 ).
printf("usage:fcompare [options] file1 file2, options: /nc /s /ln" );

else if ((inFile1Ptr=fopen()argv[1],"r")!=NULL){
}
else if
((inFile2Ptr=fopen()argv[2],"r")!=NULL)){

}
else if
((inFile2Ptr=fopen()argv[3],"r")!=NULL)){

}
else if
((inFile2Ptr=fopen()argv[4],"r")!=NULL)){

}
else if
((inFile2Ptr=fopen()argv[5],"r")!=NULL)){

}

Από εδώ και πέρα το ψάχνω, τίποτα συμβουλές και ιδέες;
bxenos


Μέλος από: 18 Αυγ 2008
Μηνύματα: 53

View users profile
ΜήνυμαΣτις: 24 Οκτ 2008 15:23    Θέμα: Re: Pointers για σύγκριση αρχείων
Περιγραφή θέματος: Εργασία με pointers και άνοιγμα - διάβασμα αρχείων
Απάντηση με παράθεση  Mark this post and the followings unread

chief ανέφερε:

if(argc<3 || argc >6 ).

α) δηλαδή το fcompare /s /s /s /s /s /s /s /s /s xxx1 xxx2
είναι λάθος;


chief ανέφερε:
else if ((inFile1Ptr=fopen()argv[1],"r")!=NULL){

β) εδώ δεν έχεις syntax error με τις παρενθέσεις;
γ) τι νομίζεις ότι περιέχουν τα argv[0],argv[1],argv[2],...argv[n];
δ) τι νομίζεις ότι κάνει η συνάρτηση fopen();
ε) πόσο καιρό κάνεις C;
στ) μέχρι εδώ τα σκέφτηκες μόνος σου;
chief


Μέλος από: 14 Οκτ 2008
Μηνύματα: 49

View users profile Visit posters website
ΜήνυμαΣτις: 26 Οκτ 2008 13:57    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Καταρχάς ευχαριστώ για την απάντηση σου.
Στο πρώτο ερώτημά σου ναι είναι λάθος οι χρήση άσχετων παραμέτρων και η χρήση πάνω από 2 φορές της ίδιας παραμέτρου. οι παραπάνω παράμετροι ή οι ανύπαρκτοι θα πρέπει να αγνοούνται από το πρόγραμμα.
Στο δεύτερο σου ερώτημα φαντάζομαι ότι αναφέρεσαι στο fopen() εν γνώσει μου το άφησα κενό …ακόμα δεν ξέρω τη θα βάλω μέσα……
rgv[0],argv[1],argv[2],...argv[n]; Περιέχουν (συμβολίζουν) τις παραμέτρους …. εάν δεν κάνω λάθος.
Η fopen ανοίγει αρχείο
Με την C ασχολούμαι περίπου 1 μήνα, κάτι λιγότερο από μήνα.
Από παραδείγματα έχω πάρει κομμάτια κώδικα και προσπαθώ να α προσαρμόσω στην άσκησή μου, ξέρω ότι καμιά φορά δεν είναι και πολύ αποδοτικό αλλά… δεν υπάρχει και πιο σύντομος τρόπος εν μέσω πίεσης χρό χρόνου
bxenos


Μέλος από: 18 Αυγ 2008
Μηνύματα: 53

View users profile
ΜήνυμαΣτις: 27 Οκτ 2008 03:43    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Οπότε, δουλειά...

ναι, τα argv[] περιέχουν παραμέτρους, αλλά ο τρόπος που τις δίνει ο χρήστης
του προγράμματος δεν είναι καθορισμένος. Πάρε μιά ιδέα από το πιό κάτω παράδειγμα

αν δοθεί η εντολή
κώδικας:
fcompare /s /e xxx1 xxx2 /t/y/u


το argv[0] περιέχει το "c:\...\fcompare.exe" δηλαδή την διαδρομή για το πρόγραμμα
το argv[1] το "/s"
το argv[2] το "/e"
το argv[3] το "xxx1"
το argv[4] το "xxx2"
το argv[5] το "/t/y/u"

άρα για τα argv[] δεν μπορείς εκ των προτέρω να ξέρεις ποιά είναι παράμετροι τύπου /x και ποιά ονόματα αρχείων, άρα θέλει κάποια δουλειά στην αρχή για να βρείς ποιά ξεκινάνε με '/' και πόσες παραμέτρους έχουν (π.χ. "/t/y/u" σε ένα argv[]).

Και μετά μπορείς να ανοίξεις τα αρχεία
fopen(όνομα_αρχείου,τύπος_τρόπος)
όπου τύπος_τρόπος είναι "r" για ανάγνωση, "w" για εγραφή, ..., "b" για binary file,...
δώσε google στο fopen και θα βρείς τις πιθανές παραμέτρους (πιθανά θέλεις "r" σκέτο").

Οπότε κάνε το επόμενο βήμα και ποστάρισε το να το δούμε
good luck
chief


Μέλος από: 14 Οκτ 2008
Μηνύματα: 49

View users profile Visit posters website
ΜήνυμαΣτις: 27 Οκτ 2008 13:10    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Λοιπόν, καταρχάς καλή μέρα.
Μετά από πειράματα και προσπάθειες για κάτι πιο πολύπλοκο αποφάσισα να πηγαίνω γραμμή γραμμή για να καταλαβαίνω και τι κάνω.

Το πρόγραμμα θα έχει τη μορφή:
παράθεση:

Σύνταξη: fcompare [options] file1 file2

Options:

/nc : Αγνόησε διάκριση κεφαλαίων-πεζών στη σύγκριση
/s : Επίστρεψε μόνο την πρώτη και την τελευταία γραμμή από ένα σύνολο συνεχόμενων διαφορετικών γραμμών
/ln : Τύπωσε και τους αριθμούς των διαφορετικών γραμμών στην έξοδο


Για αρχή έγραψα τον κώδικα που παραθέτω, που πιστεύω για αρχή είναι σωστά.
Υπάρχει κάποια διόρθωση στο παρόν τμήμα κώδικα ή παρατήρηση;


παράθεση:

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

int main (int argc, char *argv[]){

int count;
if (argc >0 || argc<6)
{
for (count = 1; count < argc; argc++)
}


FILE *file_1;
FILE *file_2;
char c[120];


file_1=fopen("test11.txt","r");
file_2=fopen("test12.txt","r");


fclose(file_1);
fclose(file_2);
return 0;
}
bxenos


Μέλος από: 18 Αυγ 2008
Μηνύματα: 53

View users profile
ΜήνυμαΣτις: 27 Οκτ 2008 13:46    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

chief ανέφερε:

κώδικας:
   int count;
   if (argc >0 || argc<7);
***εδώ έβαλες μια εντολή που δεν κάνει τιποτα.

   {
      for (count=1; count<7; argc++)
   }
***τι κανεις εδώ;
καλύτερα χρησιμοποίησε ένα βρόγχο while για να επεξεργαστεις όλα τα arguments
που ξεκινάνε με '/'
Τα arguments που θα περισσέψουν θα είναι τα ονόματα αρχείων



τα υπόλοιπα δεν έχουν πρόβλημα
chief


Μέλος από: 14 Οκτ 2008
Μηνύματα: 49

View users profile Visit posters website
ΜήνυμαΣτις: 27 Οκτ 2008 15:50    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Το πλησιάζω καθόλου γιατί εδώ και 5 ώρες έχω βγάλει τα μάτια μου....

παράθεση:

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

int main (int argc, char *argv[]){
FILE *file_1, *file_2;

char c[120];

//file_1=fopen("test11.txt","r");
//file_2=fopen("test12.txt","r");

if(argc<0 || argc>6){
printf("Usage: fcompare [options] file1 file2, options: /nc, /s, /ln.\n")
}
else if {
if ((file_1 = fopen(argv[1],"r"))!=NULL){
if((file_2 = fopen(argv[2], "r"))!=NULL)
}
}


fclose(file_1);
fclose(file_2);
return 0;
Εμφάνιση Μηνυμάτων:   
Εισαγωγή νέου Θέματος   Απάντηση στο Θέμα Σελίδα 1 από 2 [26 Μηνύματα] Σελίδα:  1, 2 Επόμενο
Mark the topic unread :: Προηγούμενο θέμα :: Επόμενο θέμα
 Forum index » Δημιουργία Web Sites, Γραφικών & Προγραμματισμός » Γλώσσες Προγραμματισμού » C, C++
Τώρα είναι 09 Δεκ 2016 11:40 | All times are UTC + 2


Email This Page to Someone! add to Favorites

     Powered by p h p B B © 2001,2005 p h p B B Group
Για άμεση επικοινωνία με τον διαχειριστή του freestuff.gr στο email: freestuff.gr(παπάκι)gmail.com


Copyright © 1999-2013 Freestuff.gr All Rights Reserved  
Version Aegean, designed by N. Tsaganos