Jump to content



σε C : καταχώρηση των δεδομένων του αρχείου σε δομή


Sophoclis

Recommended Posts

Γεία σας,

έχω ενα αρχείο και 8ελω να παρω τις πληροφορίες και να τις βάλω σε μια δομή... Το προβλημα μου είναι ότι δεν δικαιούμαι να χρησιμοποιήσω συναρτήσεις της βιβλιοθήκης stdio.h όποτε πρεπει να χρησιμοποιήσω μόνο system calls, ετσι έχω προβλημα με την μνήμη και μου κτυπά segmentation fault ....

Αν υπάρχει κάποιος να με βοηθήσει, τότε να ανεβάσω τον κώδικα μου μαζί με το αρχείο ....

Link to comment
Share on other sites

Ε, τότε θέλει ένα ξερό memcpy με απλό casting και το size του structure, αρκεί το alignment του compiler του προγράμματος που έσωσε το αρχείο να είναι ίδιο με το alignment του compiler του προγράμματος που θα το διαβάσει, για να μην έχει προβλήματα...

Link to comment
Share on other sites

Ευχαριστώ για την απάντηση

αυτό είναι τα περιεχόμενα του αρχείου, Στο αρχείο τα κενά αντίς space είναι tab !! :

1. Distributed Systems 1234 Achieving Less Bugs with More FUN in CS601 63 1

2. Distributed Systems 5678 Distributed Systems for Dummies 85 1

3. College Life 9876 Surviving UCY 42 1

4. College Life 5432 How to avoid work 38 1

Και αυτός ο κώδικας μου:

#include <stdio.h> //For I/O

#include <unistd.h>

#include <stdlib.h>

#include <string.h>

#include <strings.h>

#include <fcntl.h>

main()

{

char *filename="database.txt",c,*temp;

int filefd,bytes,i,j,count;

typedef struct{

char *ch;

char *category;

char *code;

char *title;

char *cost;

char *stock;

} book;

int howManyBooks=4;

book *books;

//copy database.txt to shared memory

if ((filefd = open(filename, O_RDONLY|O_CREAT, 0600)) < 0 )

error("ERROR open file");

lseek(filefd,0,SEEK_SET);

i=0;

count=0;

do

{

j=0;

do

{

bytes=read(filefd,&c,1);

temp[j]=c;

j++;

if (c == '\t')

{

count++;

switch (count)

{

case 1:

strcpy(books.ch,temp);

break;

case 2:

strcpy(books.category,temp);

break;

case 3:

strcpy(books.code,temp);

break;

case 4:

strcpy(books.title,temp);

break;

case 5:

strcpy(books.cost,temp);

break;

case 6:

strcpy(books.stock,temp);

break;

}//end of switch (count)

}//end of if (c == '\t')

j=0;

}while (c != '\n');

i++;

count=0;

}while (bytes > 0);

for (i=0; i<howManyBooks; i++)

{

printf("%s Category:%s Code:%s Title:%s Price:%s Stock:%s\n",books.ch, books.category,

books.code, books.title, books.cost, books.stock);

}

close(filefd);

}

το πρόβλημα αρχικά ήταν segmentation fault, Λυθηκε με το να ορισω τις μεταβλητες της structure απο pointer σε char[100]

typedef struct{

char ch[100];

char category[100];

char code[100];

char title[100];

char cost[100];

char stock[100];

} book;

int howManyBooks=4;

book books[4];

Τώρα το πρόβλημα είναι ότι δεν περνανε τα περιεχόμενα στην structure..

Link to comment
Share on other sites

Εϊναι λίγο χαοτικός ο κώδικας...

Πρέπει να διαβάσεις τι είναι οι pointers. Τους χρησιμοποιείς σα να κάνουν αυτόματα allocation την μνήμη που χρειάζεται, ενώ δεν ισχύει αυτό...

Σαν βασικός οδηγός είναι αυτό


#include <stdio.h> //For I/O
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>

typedef struct{
char ch[100];
char category[100];
char code[100];
char title[100];
char cost[100];
char stock[100];
} book;

#define MAX_BUFF_SIZE 4096
#define MAX_NUM_OF_BOOKS 5

int main()
{
char *filename="./database.txt";
char filebuffer[MAX_BUFF_SIZE];
int nob = 0;
int i = 0;

int filefd; //file descriptor

//copy database.txt to shared memory
if ((filefd = open(filename, O_RDONLY)) <=0 ) {
fprintf(stderr, "ERROR open file\n");
exit(-1);
}

lseek(filefd,0,SEEK_SET); //set to SOF

nob = read(filefd, filebuffer, MAX_BUFF_SIZE-1); //read up to buffer size
filebuffer[nob] = 0; //terminate buffer

printf("number of bytes red: %d\n", nob);

while (filebuffer[i] != 0) {
//data manipulation
//printf("%c", filebuffer[i]);
i++;
};

close(filefd);
return EXIT_SUCCESS;
}

Στο data manipulation που λέει έχεις έναν buffer που έχει όλο το αρχείο μέσα, οπότε κάνεις τα ανάλογα...

Κανονικά θα πρέπει ο αριθμός των βιβλίων και ο rx buffer να είναι δυναμικά, αλλά τέλος πάντων...

Με αυτό μπορείς να συνεχίσεις...

Link to comment
Share on other sites

Ναι τα έχω κάνει μαντάρα με τους pointer, χρειάζομαι να τους διαβάσω ξανά!

η λύση σου όμως , αν κατάλαβα σωστά βάζεις το αρχείο στον filebuffer και μετά τυπώνεις όσο ο filebuffer έχει χαρακτήρες!

στο πρόβλημα μου εμένα είναι να βάλουμε το αρχείο στην struct ώστε για παράδειγμα όταν ο χρήστης ζητά ενα βιβλίο με το κωδικό του τοτε θα έχουμε ενα Loop με μέσα την struct που να ελέγχει το (strcmp(book.code,codeXristi)==0) τότε εμφάνισε ολα τα πεδια της struct με το i που αντιστοιχεί!

Link to comment
Share on other sites

οπως θα δείς έφυγα τους pointer και τα όρισα όλα char[100]

διαβάζω χαρακτηρα-χαρακτήρα απο το αρχείο μέχρι να βρώ το '\t' , ώστε μετα να μπορώ να τα χωρίσω τα strings του αρχείο σωστό στην δομή!!

Link to comment
Share on other sites

Ο κώδικας που σου έδωσα είναι για να τον συνεχίσεις δεν είναι η λύση... απλά στο σημείο που τυπώνει τα δεδομένα θα κάνεις parse τα δεδομένα για να τα βάλεις μέσα στα structures... δεν είχα σκοπό να σου δώσω την λύση στο πρόβλημα, απλά να σε διευκολύνω λίγο... γράψε τον κώδικά σου μέσα εκεί που τυπώνει τα δεδομένα...

Link to comment
Share on other sites

οκ να τελείωσω κάτι άλλο που γράφω και θα τα κάνω!! Θα σε ενημερώσω αν χρειαστώ περαιτέρω βοήθεια!!

Σε ευχαριστώ φίλε!!

σημ. Απλώς να σου αναφέρω εν συντομία περιτίνος πρόκειται , μιλάμε για πολλούς client για 3 servers όπου μεταφέρουν τα μηνύματα των client , ο τελευταίος επεξεργάζεται, ενημερώνει την βάσει και άλλα πόλλα όπως signal, alarma, signal handler για Ctrl^C, shared memory, semaphore....:wall:

Link to comment
Share on other sites

Αν θες να ασχοληθείς σοβαρά με unix programming ή να μάθεις αρκετά καλά, τότε σου προτείνω 3 βιβλία, τα οποία στις σχολές του εξωτερικού τα έχουν στην διδακτική τους ύλη.

[ame=http://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551]1.[/ame] Unix Network Programming, Volume 1: The Sockets Networking API του μακαρίτη του Stevens

[ame=http://www.amazon.com/UNIX-Network-Programming-Interprocess-Communications/dp/0130810819/ref=pd_sim_b_1/189-4784506-5034407]2.[/ame] UNIX Network Programming, Volume 2: Interprocess Communications του Stevens

[ame=http://www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321525949/ref=pd_sim_b_2/189-4784506-5034407]3.[/ame] Advanced Programming in the UNIX Environment του Rago

Νομίζω ότι είναι τα 3 βιβλία που δεν πρέπει να λείπουν απ' όσους ασχολούνται με unix και γενικότερα posix. Είναι πολύ απλά στην κατανόηση και έχουν πολλές ιστορικές αναδρομές για το posix αλλά και την φιλοφία του unix... Τα είχα βρει μεταχ/μένα στο alibris.co.uk για ένα κομμάτι ψωμί. Προσπάθησε να τα βρεις αν μπορείς.

Έχουν μέσα όλα όσα αναφέρεις, με μόνο κενό (λόγο ηλικίας) τo multithreading, αν και έχουν κεφάλαια και γι' αυτό αλλά όχι με τα posix libraries που επικράτησαν τελικά όπως τα pthreads... Αλλά για posix multithreading βρίσκεις άπειρες πληροφορίες από τα documentation των APIs...

Link to comment
Share on other sites

Πολλοί καλά Jaco τα βιβλία που μου προτίνεις, είχα βρεί αναφορές σε αυτό...Θέλει πολλοί χρόνο φυσικά για να ασχοληθείς σε βάθος, όρεξη έχω , χρόνο θα δείξει....

Φίλε δούλεψα πάνω σε αυτό που μου έστειλες και αντιμετωπίζω segmentation fault..Αν γίνεται ρίξε του μια ματία και πες μου και εμένα να καταλάβω όσο γίνεται πού και γιατί συμβαίνει segmentation fault.. Ξέρω ότι έχει να κάνει με τον χειρισμό της μνήμης αλλά στο συγκεκριμένο πρόγραμμα δεν καταλάβω το γιατί

#include <stdio.h> //For I/O

#include <unistd.h>

#include <stdlib.h>

#include <string.h>

#include <strings.h>

#include <fcntl.h>

typedef struct{

char ch[100];

char category[100];

char code[100];

char title[100];

char cost[100];

char stock[100];

} book;

#define MAX_BUFF_SIZE 4096

#define MAX_NUM_OF_BOOKS 5

int main()

{

char *filename="./database.txt";

char filebuffer[MAX_BUFF_SIZE];

int nob = 0;

int i = 0;

int filefd; //file descriptor

int howManyBooks=4;

book books[4];

char temp[100];

int j=0;

int count=0;

//copy database.txt to shared memory

if ((filefd = open(filename, O_RDONLY)) <=0 ) {

fprintf(stderr, "ERROR open file\n");

exit(-1);

}

lseek(filefd,0,SEEK_SET); //set to SOF

nob = read(filefd, filebuffer, MAX_BUFF_SIZE-1); //read up to buffer size

filebuffer[nob] = 0; //terminate buffer

printf("number of bytes red: %d\n", nob);

while (filebuffer != 0) {

//data manipulation

if ((filebuffer != '\t') && (filebuffer != '\n'))

{

temp[j]=filebuffer;

j++;

}

if (filebuffer == '\t')

{

j=0;

count++;

switch (count)

{

case 1:

strcpy(books.ch,temp);

break;

case 2:

strcpy(books.category,temp);

break;

case 3:

strcpy(books.code,temp);

break;

case 4:

strcpy(books.title,temp);

break;

case 5:

strcpy(books.cost,temp);

break;

case 6:

strcpy(books.stock,temp);

break;

}//end of switch (count)

}//end if

if (filebuffer == '\n')

count=0;

//printf("%c", filebuffer);

i++;

};

for (i=0; i<howManyBooks; i++)

{

printf("%s Category:%s Code:%s Title:%s Price:%s Stock:%s\n",books.ch, books.category,

books.code, books.title, books.cost, books.stock);

}

close(filefd);

return EXIT_SUCCESS;

}

Link to comment
Share on other sites

Έχεις δρόμο ακόμα... καταρχήν θα πρέπει να σβήσεις το

#include <stdio.h>

Υποτίθεται ότι δεν πρέπει να το χρησιμοποιήσεις καθόλου... Οπότε θα δεις ότι έχεις και άλλα λάθη...

Σε αυτό που μπορώ να σε βοηθήσω είναι πως να διαβάσεις σε έναν buffer το αρχείο χωρίς να χρησιμοποιήσεις καθόλου την stdio, μιας και είναι το πιο δύσκολο κομμάτι, αλλά από εκεί και πέρα, επειδή είναι άσκηση δεν μπορώ να σου πω κάτι άλλο, πέρα απ' το ότι θα πρέπει να σπάσεις το πρόβλημα σε κομμάτια και να χρησιμοποιήσεις έναν debugger να δεις τα λάθη σου...

Το τελευταίο που μπορώ να σου δώσω είναι αυτό, από εκεί και πέρα, δεν μπορώ... Είμαι κατά των έτοιμων λύσεων, σίγουρα έχω φάει πολύ βρίσιμο γι' αυτό :p


#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#ifndef SEEK_END
#define SEEK_END 2
#endif

#ifndef STDOUT
#define STDOUT 1
#endif

#ifndef STDERR
#define STDERR 2
#endif

typedef struct{
char ch[100];
char category[100];
char code[100];
char title[100];
char cost[100];
char stock[100];
} tp_book;


#define PRINT_DBG(BUFF,BUFF_SZ) write(STDOUT,BUFF,BUFF_SZ) //for printing w/o stdio
#define PRINT_ERR(ERR_STR) write(STDERR,ERR_STR,sizeof(ERR_STR))

size_t BufferFromFile(const char * fname, char **buffer)
{
int fd; //file descriptor
size_t nob = 0; //number of bytes

//Open file
if ((fd = open(fname, O_RDONLY))) {

nob = (size_t) lseek(fd, 0L, SEEK_END); //set pointer to end of file //2 = SEEK_END
*buffer = (char*) malloc(sizeof(char) * (nob+1)); //create buffer and allocate memmory

lseek(fd, 0L, 0); //set again the pointer to start to read the file
read(fd, *buffer, nob); //read file

*(*buffer + nob) = 0; //terminate buffer just in case

close(fd); //close file
}

return(nob); //return the pointer to the buffer. MUST DELETE LATER!!!
}



int main()
{
char *filename="./database.txt";
char * buffer = NULL; //input buffer
size_t buff_size = BufferFromFile(filename, &buffer); //read file

if (buffer == NULL) {
PRINT_ERR("File read error!");
exit(-1); //catastrophic failure :p
}
else if (buff_size == 0) {
PRINT_ERR("Empty file");
exit(-2);
}

PRINT_DBG(buffer, buff_size); //debug print without stdio

//HERE parse buffer and fill tp_book structs

free(buffer); //delete buffer

return EXIT_SUCCESS;
}

Link to comment
Share on other sites

Ναι όντος το stdio.h το ξέχασα , από το προηγούμενο copy-paste

Kαι πάλι σε ευχαριστώ για ότι κάνεις που με βοηθάς

Δεν το βρίσκω το λάθος , έχει πάνω απο 2 χρόνια να γράψω σε C....

Ευχαριστώ πάντως!!!

Link to comment
Share on other sites

Οταν ξυπνήσεις ξεκούραστος με καθαρό μυαλό τότε βρίσκεις λύσεις :dance3:

Οπώς βλέπεις φίλε Jaco στο τέλος χρησιμοποιώ stdio.h printf γιατί δεν ξέρω πως να το τυπώσω με write(STDOUT_FILENO, , ) νομίζω μπορώ να χρησιμοποιήσω sprintf .... θα το ψάξω...

και πάλι ευχαριστώ!!!

σημ. Δεν νομίζω να χρησιμοποιήσω αυτό τον κώδικα με την function site_t γιατί πρώτη φορά την βλέπω αυτή την δήλωση , οπότε θα παω σε κάτι πιο απλό...όπως το 1η λύση!!!

#include <unistd.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <stdio.h>

#ifndef SEEK_END

#define SEEK_END 2

#endif

#ifndef STDOUT

#define STDOUT 1

#endif

#ifndef STDERR

#define STDERR 2

#endif

typedef struct{

char ch[100];

char category[100];

char code[100];

char title[100];

char cost[100];

char stock[100];

} tp_book;

#define PRINT_DBG(BUFF,BUFF_SZ) write(STDOUT,BUFF,BUFF_SZ) //for printing w/o stdio

#define PRINT_ERR(ERR_STR) write(STDERR,ERR_STR,sizeof(ERR_STR))

size_t BufferFromFile(const char * fname, char **buffer)

{

int fd; //file descriptor

size_t nob = 0; //number of bytes

//Open file

if ((fd = open(fname, O_RDONLY))) {

nob = (size_t) lseek(fd, 0L, SEEK_END); //set pointer to end of file //2 = SEEK_END

*buffer = (char*) malloc(sizeof(char) * (nob+1)); //create buffer and allocate memmory

lseek(fd, 0L, 0); //set again the pointer to start to read the file

read(fd, *buffer, nob); //read file

*(*buffer + nob) = 0; //terminate buffer just in case

close(fd); //close file

}

return(nob); //return the pointer to the buffer. MUST DELETE LATER!!!

}

int main()

{

char *filename="./database.txt";

char * buffer = NULL; //input buffer

size_t buff_size = BufferFromFile(filename, &buffer); //read file

int i=0,j=0,count=0,k=0;

char temp[100];

tp_book books[4];

if (buffer == NULL) {

PRINT_ERR("File read error!");

exit(-1); //catastrophic failure :p

}

else if (buff_size == 0) {

PRINT_ERR("Empty file");

exit(-2);

}

PRINT_DBG(buffer, buff_size); //debug print without stdio

printf("\n");

for (i=0; i<buff_size; i++)

{

if ((buffer != '\t') && (buffer != '\n'))

{

temp[j]=buffer;

j++;

}

if (buffer == '\t')

{

count++;

//temp[strlen(temp)]='\0';

switch (count)

{

case 1:

temp[j]='\0';

strcpy(books[k].ch,temp);

j=0;

break;

case 2:

temp[j]='\0';

strcpy(books[k].category,temp);

j=0;

break;

case 3:

temp[j]='\0';

strcpy(books[k].code,temp);

j=0;

break;

case 4:

temp[j]='\0';

strcpy(books[k].title,temp);

j=0;

break;

case 5:

temp[j]='\0';

strcpy(books[k].cost,temp);

j=0;

break;

//case 6:

// strcpy(books[k].stock,temp);

// break;

}//end of switch (count)

}//end if

if (buffer == '\n')

{

temp[j]='\0';

strcpy(books[k].stock,temp);

j=0;

count=0;

k++;

}

//printf("%c", filebuffer);

}

for (i=0; i<4; i++)

{

printf("%s Category:%s Code:%s Title:%s Price:%s Stock:%s\n",books.ch, books.category,

books.code, books.title, books.cost, books.stock);

}

free(buffer); //delete buffer

return EXIT_SUCCESS;

}

Link to comment
Share on other sites

Αντί για size_t μπορείς να βάλεις int ή καλύτερα unsigned int, είναι σχεδόν το ίδιο... ανάλογα τον compiler είναι είτε unsigned int ή umsigned long... είναι πολύ συνηθισμένος τύπος...

Πάντα να ψάχνεις τα definitions των τύπων για να μαθαίνεις την πλατφόρμα σου και τον compiler σου... Αυτοί οι τύποι λέγονται ψευδο-abstract και ο λόγος που χρησιμοποιούνται είναι για να κάνουν πιο εύκολο το porting ανάμεσα σε διάφορες πλατφόρμες και αρχιτεκτονικές... Για παράδειγμα σε έναν 32-bit πεξεργαστή και compiler το size_t μπορεί να είναι unsigned long, σε έναν 64-bit να είναι unsigned int και σε έναν 16/8-bit να είναι unsigned long long, αλλά όμως πάντα το αναφέρεις σαν size_t και ο compiler ανάλογα με το definition ξέρει να κάνει την σωστή μετατροπή...

Τώρα αυτό που κάνουν τα macros PRINT_DBG και PRINT_ERR είναι αντί να χρησιμοποιείς την printf γράφουν απ' ευθείας στον file descriptor της οθόνης...

Γενικά το terminal output ή standard output (stdout) είναι για το λειτουργικό σαν ένα αρχείο στο οποίο γράφει... Απλά στα unix συστήματα και γενικά σε όσα υποστηρίζουν το posix το stdout είναι πάντα το αρχείο με το id = 1, το stderr είναι το αρχείο με το id = 2 και το πληκτρολόγιο είναι πάλι ένα αρχείο με id = 0... Οπότε κάνεις αυτό που κάνει και ουσιαστικά η printf, απλά σε πιο low level programming... Επίσης παρατηρείς ότι δεν χρειάζεται να κάνεις πρώτα open τα stdout, stdin, stderr γιατί είναι πάντα ανοιχτά όταν τρέχει ένα πρόγραμμα... Γι' αυτό πρέπει πάντα να καλείς την open όταν θες να έχεις πρόσβαση σε ένα αρχείο, γιατί αυτή σου επιστρέφει πάντα το επόμενο ελεύθερο id (id= file descriptor) του συστήματος...

Αύριο θα τρέξω και τον κώδικά σου, γιατί τώρα δεν μου είναι εύκολο...

Link to comment
Share on other sites

Ευχαριστώ πολύ, μου έδωσες να καταλάβω συνοπτικά την χρήση της size_t η οποία φαίνεται πολύ χρήσιμη με σχέση αυτά που μου λές!! νομίζω αυτές τις λεπτομέριες και εις βάθος μόνο με τα βιβλία που μου πρότινες θα της μάθω, γιατί στην σχολη , ξέρεις τα βασικά μας μαθαίνου!!

Γνώριζω αυτά που λές ακριβώς όπως τα έγρψες για το stdout, stdin και stderr

αλλά δεν ξέρω πώς να τα χρησιμοποιήσω όταν θέλω να τυπώσω μήνυμα μαζί με μεταβλητή δηλαδή αυτό που κάνω στο τέλος του προγράμματος που τυπώνω την structure!!

Link to comment
Share on other sites

αυτό που θα ήθελα να σε ρωτήσω είναι:

1) γιατι προτίνεις να βάλουμε το αρχείο σε buffer αντίς να διαβάζουμε απευθείας από το αρχείο...?

2) Ποίος ο λόγος για define αφού είναι καθορισμένα by default :

#ifndef SEEK_END

#define SEEK_END 2

#endif

#ifndef STDOUT

#define STDOUT 1

#endif

#ifndef STDERR

#define STDERR 2

#endif

3) return(nob); //return the pointer to the buffer. MUST DELETE LATER!!! για θέμα μνήμης MUST Delete later ?

Link to comment
Share on other sites

Το buffer το χρησιμοποιείς γιατι αφου εχεις μια συνάρτηση και εναν pointer πρεπει κάπου να αποθηκεύσεις τα περιεχόμενα του δεν μπορεις να το χρησιμοποιήσεις ετσι.

Αυτο εχω καταλάβει , ειμαι ακομα σε πρώιμο σταδιο προχτες ασχολήθηκα με APΙ ,ελπιζω να βοήθησα λιγακι :)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Δημιουργία...

Important Information

Ο ιστότοπος theLab.gr χρησιμοποιεί cookies για να διασφαλίσει την καλύτερη εμπειρία σας κατά την περιήγηση. Μπορείτε να προσαρμόσετε τις ρυθμίσεις των cookies σας , διαφορετικά θα υποθέσουμε ότι είστε εντάξει για να συνεχίσετε.