Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ. (επεξεργασμένο)

Έχω φάει ένα σκάλωμα εδώ και ώρα. Δεν είμαι σίγουρος αν αυτό που έχω κάνει λειτουργεί σωστά ή όχι. Σε επίπεδο μνήμης, όχι λογικής. Βάζω το κώδικα και εξηγώ.

int main (int argc, char *argv[]){
	char command[MAX_READ];
	char *tok[MAX_READ];
	int numberofArguments;

	while(1){

		read(STDIN_FILENO,command,MAX_READ);
		command[strcspn(command,"\n")]='\0';

		switch(parse(tok, command, &numberofArguments)){
.
.
.
int parse(char *res[], char *str, int *argc){

	char *temp;
	temp=strtok(str," ");
	int i=0;
	while(temp!=NULL){
		res[i]=temp;
		i++;
		temp=strtok(NULL, " ");
	}
.
.
.

Στα γρήγορα, αυτό που θέλω να κάνω είναι να διαβάζει μια εντολή από το πληκτρολόγιο και να τη σπάω σε λέξεις. Αποθηκεύω την εντολή στο command, τη περνάω στην parse() που μου επιστρέφει (χωρίς να πειράξει το command) στο res[] τα επιμέρους strings, το πόσα strings βρήκε και ένα int.

Το θέμα μου είναι στο res = temp. Αυτό δουλεύει? Το έκανα στα γρήγορα έτσι και δούλεψε. Τώρα που ξανακοιτάω το κώδικα ανησυχώ ότι απλά έτυχε/τυχαίνει. Αν καταλαβαίνω σωστά, κάνω τη διεύθυνση του res ίδια με του temp. Αλλά ο temp είναι προσωρινή μεταβλητή της parse(). Άρα μόλις φύγω από το scope της, θα αποδεσμευτεί. Κάνω λάθος?

Έκατσα και το έγραψα με malloc που μου φαίνεται πιο σωστό αλλά πρέπει να κάνω free από τη main που δε μου αρέσει για κάποιο λόγο :P.

 

 


int parse(char *res[], char *str, int *argc){

	char *temp;
	temp=strtok(str," ");
	int i=0;
	while(temp!=NULL){
		res[i] = (char*) malloc((strlen(temp)+1)*sizeof(char));
		strcpy(res[i],temp);
		temp=strtok(NULL, " ");
	}
.
.
.

 

 

Επεξ/σία από sir ImPeCaBlE
Δημοσ.

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

int main (int argc, char *argv[]){
	char command[MAX_READ];
	int numberofArguments;
	char *tok[MAX_ARGS];
	
	for(int i=0;i<MAX_ARGS; i++){
		tok[i]= (char*)calloc(MAX_READ,sizeof(char));
	}
                            
	while(1){

		read(STDIN_FILENO,command,MAX_READ);
		command[strcspn(command,"\n")]='\0';

		switch(parse(tok, command, &numberofArguments)){
.
.
.
int parse(char **res, char *str, int *argc){

	char *temp;  //break up string
	temp=strtok(str," ");
	int i=0;
	while(temp!=NULL){
		strcpy(res[i],temp);
		i++;
		temp=strtok(NULL, " ");
	}
.
.
.

 

Δημοσ. (επεξεργασμένο)
5 ώρες πριν, sir ImPeCaBlE είπε

Έχω φάει ένα σκάλωμα εδώ και ώρα. Δεν είμαι σίγουρος αν αυτό που έχω κάνει λειτουργεί σωστά ή όχι. Σε επίπεδο μνήμης, όχι λογικής. Βάζω το κώδικα και εξηγώ.


int parse(char *res[], char *str, int *argc){
	char *temp;
	temp=strtok(str," ");
	int i=0;
	while(temp!=NULL){
		res[i]=temp;
		i++;
		temp=strtok(NULL, " ");
	}

Το θέμα μου είναι στο res = temp. Αυτό δουλεύει? Το έκανα στα γρήγορα έτσι και δούλεψε. Τώρα που ξανακοιτάω το κώδικα ανησυχώ ότι απλά έτυχε/τυχαίνει. Αν καταλαβαίνω σωστά, κάνω τη διεύθυνση του res ίδια με του temp. Αλλά ο temp είναι προσωρινή μεταβλητή της parse(). Άρα μόλις φύγω από το scope της, θα αποδεσμευτεί. Κάνω λάθος? 

Γενικά ισχύει αυτό που λες για την parse, εδώ όμως γίνεται κάτι διαφορετικό. Αποθηκεύεις στα res την τιμή του temp. Τι τιμή έχει ο temp ? Ό,τι του επέστρεψε η strtok δηλαδή τιμές στις εκάστοτε θέσεις του str. Το str όμως είναι το command και συνεχίζει να υφίσταται έξω από την parse. Πρόσθεσα στον κώδικά σου μια for που να τυπώνει τι τιμή έχουν τα διάφορα tok μετά την εκτέλεση της parse και δες τι λέει:

 

% ./a.out
command has address 0xffeb1426
Hello World Treia Poylakia Kathontan
I = 0, s = Hello, addr = 0xffeb1426
I = 1, s = World, addr = 0xffeb142c
I = 2, s = Treia, addr = 0xffeb1432
I = 3, s = Poylakia, addr = 0xffeb1438
I = 4, s = Kathontan, addr = 0xffeb1441
	

 

Όπως βλέπεις, έχουν τιμές μέσα στις θέσεις του πίνακα command που υπάρχει στην stack της main και δεν χάνεται ποτέ. Δεν έπαιζε κατά τύχη δηλαδή, έτσι έπρεπε να παίξει. Ανάλογα με το πώς είναι ο υπόλοιπος κώδικάς σου, ίσως είχες πρόβλημα επειδή οι αλλαγές στα tok θα επηρρέαζαν και τον command και αντίστροφα η αλλαγή στο command θα επηρρέαζε τα tok, το οποίο δεν συμβαίνει όταν κάνεις αντιγραφή με την strcpy στον νέο κώδικα.

Όσον αφορά αλλαγές, γιατί χρησιμοποιείς την χαμηλού επιπέδου read και όχι κάποια fgets ή κάτι αντίστοιχο για πιο ευκολία ?

Επεξ/σία από imitheos
  • Thanks 1
Δημοσ.

Thanx imitheos. Ούτε καν είχα ελέγξει αν τελικά πείραζα το command. Η strtok με μπέρδεψε αρκετά (ακόμα δηλαδή δεν έχω καταλάβει τι ακριβώς κάνει, θα το ξανακοιτάξω). Νομίζω τώρα δουλεύει όπως θα ήθελα:

int parse(char **res, char *str, int *argc){

	char *temp=(char*)malloc((strlen(str)+1)*sizeof(char));  //break up string
	strcpy(temp,str);
	temp=strtok(temp," ");
	int i=0;
	while(temp!=NULL){
		strcpy(res[i],temp);
		i++;
		temp=strtok(NULL, " ");
	}
	free(temp);
.
.
.

Θα κοιτάξω και την fgets. Δε την έχω ξαναχρησιμοποιήσει, ενώ με την read υπάρχει μια εξοικείωση. Thanx και πάλι!

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...