Page 1 of 1
Απλή απoρία στη C
Posted: Sat Feb 28, 2009 8:44 pm
by PASCAL
Γιατί ο ακόλουθος κώδικας διαβάζει μόνο ένα char;
Code: Select all
#include <stdio.h>
#include <stdlib.h>
int main() {
char mychar;
printf("Type a char: ");
mychar = getchar();
printf("Type a char: ");
mychar = getchar();
system("PAUSE");
return EXIT_SUCCESS;
}
και αυτός δύο:
Code: Select all
#include <stdio.h>
#include <stdlib.h>
int main() {
char mychar;
printf("Type a char: ");
mychar = getchar();
printf("Type a char: ");
mychar = getchar();
mychar = getchar();
system("PAUSE");
return EXIT_SUCCESS;
}
Re: Απλή απoρία στη C
Posted: Sat Feb 28, 2009 9:28 pm
by cyberpython
Επειδή αφού διαβάσεις ένα χαρακτήρα με τη getchar() μένει(ουν) στο ρεύμα εισόδου ο χαρακτήρας(ες) αλλαγής γραμμής (σε win 2 - cr+lf).
Επίσης, τη system("PAUSE") καλό είναι να την αποφεύγεις αφού δεν είναι cross-platform (βάζε μια getchar() καλύτερα).
Re: Απλή απoρία στη C
Posted: Sat Feb 28, 2009 10:08 pm
by netharis
Δοκίμασε ανάμεσα απο τα input:
Re: Απλή απoρία στη C
Posted: Sun Mar 01, 2009 12:45 am
by PASCAL
Eυχαριστώ παιδιά και ειδικά netharis, δούλεψε με τo flush του standard input.
Re: Απλή απoρία στη C
Posted: Fri Jun 05, 2009 11:17 pm
by Theofaman
Θα χρειαστώ την βοήθειά σας

Ανοίγω ένα αρχείο της μορφής
και έπειτα το διαβάζω ανά γραμμή και την καταχωρώ σε ένα κόμβο της λίστας. Γιατί όταν τυπώνω την λίστα εμφανίζει μόνο την τελευταία εγγραφή του αρχείου? (δηλ. το ef). Αν εισάγω στην λίστα αριθμούς με μορφή μεταβλητών δουλεύει κανονικά. Κάτι συμβαίνει και το line δείχνει πάντα στο τέλος του αρχείου.
Code: Select all
char line[80];
fs = fopen ( "onomata.txt", "r") ;
while(fgets(line, sizeof(line), fs) != NULL)
{
lnode = (item*)malloc(sizeof(item));
printf("%s",line);
lnode = (struct dllist *)malloc(sizeof(struct dllist));
node->val = line;
append_node(lnode);
}
for(lnode = head; lnode != NULL; lnode = lnode->next) {
printf("%s\n", lnode->val);
fprintf(ft, "%s\n", lnode->val);
Ευχαριστώ

Re: Απλή απoρία στη C
Posted: Sat Jun 06, 2009 12:33 pm
by HdkiLLeR
Τα έχεις μπλέξει λίγο
το
line είναι ένας buffer, τον οποίο κάθε φορά γεμίζεις με τα περιεχόμενα μιας γραμμής που διαβάζεις απο το file σου. Όταν κάνεις
node->val = line; τότε ο pointer του node struct δείχνει στον buffer αυτόν. Συνεπώς αφού δεν έχεις ξεχωριστούς buffers / node και απλά παίζεις με τους pointers όλα τα node structs δείχνουν στην ίδια περιοχή (στον buffer των 80 bytes). Εάν στο τέλος του βάλεις εκεί το "ef" τότε όλα τα node->val θα είναι το "ef\0".
Γενικότερα τώρα:
- το lnode το κάνεις init δύο φορές, την μία φορά σαν item και την άλλη σαν dllist -- memory leak (το πρώτο χάνεται και δεν γίνεται free)
- το buffer σου δεν το κάνεις clear (zero) σε κάθε loop. Tο ότι βάζει \0 η fgets στο τέλος δεν λέει κάτι εάν διαβάζεις πχ σε ένα loop το "12345", στο buffer σου θα έχεις το 12345\0, εάν μετά διαβάσεις το 1 τότε το buffer σου θα έχει "1\0345\0" κοκ. Νομίζεις ότι είναι σωστό επειδή στο printf δεν κάνει print τπτ μετά το πρώτο \0 (string termination char)
- η append_node() που είναι?

Re: Απλή απoρία στη C
Posted: Sat Jun 06, 2009 1:59 pm
by Theofaman
HdkiLLeR wrote:Τα έχεις μπλέξει λίγο
το
line είναι ένας buffer, τον οποίο κάθε φορά γεμίζεις με τα περιεχόμενα μιας γραμμής που διαβάζεις απο το file σου. Όταν κάνεις
node->val = line; τότε ο pointer του node struct δείχνει στον buffer αυτόν. Συνεπώς αφού δεν έχεις ξεχωριστούς buffers / node και απλά παίζεις με τους pointers όλα τα node structs δείχνουν στην ίδια περιοχή (στον buffer των 80 bytes). Εάν στο τέλος του βάλεις εκεί το "ef" τότε όλα τα node->val θα είναι το "ef\0".
Καταλαβαίνω ότι αυτό είναι το προβλημα αλλά δεν μπορώ να το λύσω

Δηλαδή προσπαθώ αντί να κάνω lnode->val = line να κάνω πχ lnode->val = *line για να παρω το περιεχόμενο και να μην δειχνει στο line το val.
Το line πως γινεται clear? Δεν βρηκα κατι στο google.
Ετσι τυπωνω την λίστα
Code: Select all
int printlist(struct dllist *lnode)
{
for(lnode = head; lnode != NULL; lnode = lnode->next) {
printf("%s\n", lnode->val);
fprintf(ft, "%s\n", lnode->val);
}
fclose (fs) ;
fclose (ft);
}
και αυτη είναι η append node
Code: Select all
void append_node(struct dllist *lnode) {
if(head == NULL) {
head = lnode;
lnode->prev = NULL;
} else {
tail->next = lnode;
lnode->prev = tail;
}
tail = lnode;
lnode->next = NULL;
}
Re: Απλή απoρία στη C
Posted: Sat Jun 06, 2009 5:30 pm
by HdkiLLeR
Theofaman wrote:
Καταλαβαίνω ότι αυτό είναι το προβλημα αλλά δεν μπορώ να το λύσω

Δηλαδή προσπαθώ αντί να κάνω lnode->val = line να κάνω πχ lnode->val = *line για να παρω το περιεχόμενο και να μην δειχνει στο line το val.
Τα char arrays (και όλα τα arrays) δεν έχουν value (δηλαδή
*p). Τι σημαίνει value ενός array (δεν έχει νόημα δηλαδή). Η απλούστατη λύση είναι
copy. Αντί να κάνεις lnode->val = line θα πρέπει κάθε φορά να δεσμεύεις δηναμικά ένα άλλο κομμάτι heap space στο οποίο θα αποθηκεύεις τα περιεχόμενα του buffer. Εάν ήταν Java τι θα έκανες; Φαντάζομαι κάτι σε
lnode.setVal(new String("...")), έ αυτό το
new (που κάνει dynamic allocation για ένα new string object) θα πρέπει να το κάνεις είτε με
malloc() (δηλαδή lnode->val = (char *)malloc(strlen(line)+1); strncpy(lnode->val, line, strlen(line));, είτε με
strdup() (δηλαδή lnode->val = strdup(line);) To δεύτερο κάνει ότι το πρώτο απο μόνο του.
Theofaman wrote:
Το line πως γινεται clear? Δεν βρηκα κατι στο google.
bzero(line, sizeof(line));
memset(line, 0, sizeof(line));
Στο τέλος ότι έχεις κάνει
malloc()/calloc() φρόντισε να το κάνεις
free(), ομοίως και ότι έχει προκύψει απο
strdup() -- αλλιώς έχεις σοβαρά memory leaks/λάθη.
Re: Απλή απoρία στη C
Posted: Sat Jun 06, 2009 7:51 pm
by Theofaman
Προσπάθησα να ορίσω μια νέα δομή που θα περιέχει μέσα εναν πίνακα char αλλά ο τρόπος που πρότεινες είναι καλύτερος και τρέχει.
Ευχαριστώ

Re: Απλή απoρία στη C
Posted: Thu Oct 08, 2009 8:32 pm
by PASCAL
Να ρωτήσω κάτι άλλο;
Όταν έχεις μια δομή:
Code: Select all
union example {
char ch;
int xyz;
} str[10];
πώς μπορείς να γεμίσεις τον πίνακα str και το μέλος ch από κονσόλα; Γίνεται με scanf(), gets() κτλ ή κάπως αλλιώς;
Ευχαριστώ
Re: Απλή απoρία στη C
Posted: Thu Oct 08, 2009 9:25 pm
by netharis
Κανονικά μπορείς να διαβάσεις σε ένα union array. Eίναι και αυτό ένα κομμάτι μνήμης που έχει προσπελάσιμη διεύθυνση απο τις κανονικές μεθόδους εισόδου.
Δεδομένης της παραπάνω δήλωσης σου:
Code: Select all
#include <stdio.h>
union example
{
char ch;
int xyz;
}str[10];
int main()
{
/*Απλή ανάθεση */ /*str[0].ch = 'a';*/
scanf("%c", &str[0].ch);
printf("%c\n", str[0].ch);
return 0;
}
Re: Απλή απoρία στη C
Posted: Thu Oct 08, 2009 11:07 pm
by PASCAL
Α, ωραία. Βέβαια τώρα έχει σφάλμα εκτέλεσης

Just-In-Time Debugger 3860
Re: Απλή απoρία στη C
Posted: Fri Oct 09, 2009 12:02 am
by netharis
PASCAL wrote:Α, ωραία. Βέβαια τώρα έχει σφάλμα εκτέλεσης

Just-In-Time Debugger 3860
Μα C σε Visual Studio ?
Άν ο κώδικας που γράφεις είναι πάνω σε μία κλητική ακολουθία, πόσταρε λίγο κώδικα αν μπορείς να του ρίξουμε μία ματιά.
Re: Απλή απoρία στη C
Posted: Fri Oct 09, 2009 1:31 am
by PASCAL
Δεν πειράζει εντάξει το διόρθωσα! Thanks!
Και όντως, μακρία η C από Visual Studio
