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

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

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

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

Δημοσίευσηαπό stamatiou » 29 Αύγ 2011, 22:03

Star_Light έγραψε:
stamatiou έγραψε:
Spoiler: show
Κώδικας: Επιλογή όλων
#include <stdio.h>

char *mystrcpy(char *destination,int n,char *source) {
int i;
for(i=0;i<n;i++) {
if(source[i]) {
destination[i] = source[i];
}else {
for(;i < n;i++) {
destination[i] = 0;
}
destination[i+1] = '\0';
return destination;
}
}
destination[i] = '\0';
return destination;
}

int main(void) {
char source[] = "Hello World";
char destination[] = "Hello Everybody";
mystrcpy(destination,5,source);
puts(destination);
return 0;
}


Το χεις τρέξει αυτο καθόλου να δεις τι βγάζει? :P
Γιατι σε μενα βγαζει ενα σκετο hello αρα δεν κανει την δουλεια που θελουμε....

Γιατι; Εγω εβαλα εναν πινακα Hello καθ εναν Hello World και ο δευτερος εγινε Hello. Αυτο δεν πρεπει να κανει;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 29 Αύγ 2011, 22:10

δεν ξερω οτι θελετε.... απλα εχω αρχιζει να ζαλιζομαι λιγο με τους δεικτες και τις συναρτησεις.... εχουμε βρει το διαολομπελα μας με αυτους τους δεικτες δηλαδη :crazy:
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 29 Αύγ 2011, 22:19

Star_Light έγραψε:δεν ξερω οτι θελετε.... απλα εχω αρχιζει να ζαλιζομαι λιγο με τους δεικτες και τις συναρτησεις.... εχουμε βρει το διαολομπελα μας με αυτους τους δεικτες δηλαδη :crazy:

:lol: Εγώ πάντως αυτή που έκανα είναι η http://www.cplusplus.com/reference/clibrary/cstring/strncpy/ δλδ copy
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 29 Αύγ 2011, 22:35

Spoiler: show
Κώδικας: Επιλογή όλων
#include<stdio.h>
#define N 255
#define M 255
char *f_cp(char *ptr1 , char *ptr2);

int main()

{

char s1[N];
char s2[M]="";
char *ptr1;
char *ptr2;

printf("Dwse mia sumvoloseira: ");
fgets(s2,255,stdin);
sscanf(s2,"%c",s2);

ptr1=s1;
ptr2=s2;

f_cp(&ptr1,&ptr2);
printf("%c",*ptr1);

return 0;
}
char *f_cp(char *ptr1 , char *ptr2)
{

for(ptr2; *ptr2!='\0'; ptr2++)
*ptr1=*ptr2;


return ptr1;
}


αλλα δεν δουλευει.....
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 29 Αύγ 2011, 22:42

Άυτή η συνάρτηση δεν πρέπει να έχει και ένα όρισμα αριθμό; Επίσης αυτή τι κάνει; Copy ή Overwrite;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 29 Αύγ 2011, 22:46

stamatiou έγραψε:Άυτή η συνάρτηση δεν πρέπει να έχει και ένα όρισμα αριθμό; Επίσης αυτή τι κάνει; Copy ή Overwrite;


ναι πρεπει αλλα αρχικα ειπα να μην το βαλω.... Copy παω να την βαλω να κανει... εφοσον ο ενας πινακας ειναι ηδη αδειος.
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 29 Αύγ 2011, 23:02

Οπότε θα κάνουμε την copy πρώτα, μισό να φάω και θα επιστρέψω να δω τις λύσεις σας
(σορυ που αργώ, αλλά γράφω και στο άλλο τοπικ: viewtopic.php?p=204811#p204811 :) )
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 29 Αύγ 2011, 23:03

migf1 έγραψε:Οπότε θα κάνουμε την copy πρώτα, μισό να φάω και θα επιστρέψω να δω τις λύσεις σας
(σορυ που αργώ, αλλά γράφω και στο άλλο τοπικ: viewtopic.php?p=204811#p204811 :) )


KANoνικα θα επρεπε να μας αφησεις ολη νυχτα να το ψαξουμε μονοι μας
τοσα μας εχεις πει... βεβαια ο σταματιου το ελυσε.
Μαγκας!!! Καλα ξηγηθηκε. :D
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

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

Δημοσίευσηαπό Star_Light » 29 Αύγ 2011, 23:16

Spoiler: show
Κώδικας: Επιλογή όλων
#include<stdio.h>
#define N 255
#define M 255
char *f_cp(char *ptr1 , char *ptr2);

int main()

{

char s1[N];
char s2[M]="";
char *ptr1;
char *ptr2;

printf("Dwse mia sumvoloseira: ");
fgets(s2,255,stdin);
sscanf(s2,"%c",s2);

ptr1=s1;
ptr2=s2;
f_cp(ptr1,ptr2);
printf("%c",*ptr1);


return 0;
}
char *f_cp(char *ptr1 , char *ptr2)
{

for(; *ptr2!='\0'; ptr2++)
*ptr1=*ptr2;


return ptr1;
}



αυτο να κοιταξεις migf1 οχι τα αλλα... βασικα εβγαλα μεσα απο την κληση της συναρτησης τo & γιατι μου ελεγε πως χρησιμοποιειται διπλος δεικτης
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 30 Αύγ 2011, 01:12

Λοιπόν, υπάρχει ένα θέμα παιδιά με την strncpy, για αυτό δεν ήθελα να ξεκινήσουμε από αυτήν. Συγκεκριμένα, αν οι χαρακτήρες του source string είναι περισσότεροι από το n, τότε το destination string ΔΕΝ τερματίζεται με τον μηδενικό χαρακτήρα (και άρα παύει να είναι έγκυρο c-string).

Για να το διαπιστώσετε και μόνοι σας δοκιμάστε τον παρακάτω κώδικα:

Κώδικας: Επιλογή όλων

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

int main( void )
{
char src[] = "56789";
char dst[] = "123";
size_t n = 2;

strncpy(dst, src, n);
puts( dst );

return 0;
}

Θα δείτε πως το puts( dst ) δεν θα τυπώσει "56" όπως θα περιμέναμε, αλλά θα τυπώσει "563". Δηλαδή, παίρνει τους 2 πρώτους χαρακτήρες από το src ("56") και τους αντιγράφει στις 2 πρώτες θέσεις του dst, αλλά δεν βάζει '\0', οπότε ο 3ος χαρακτήρας του dst παραμένει αυτός που ήταν από πριν, δηλαδή ο '3'.

Δοκιμάστε επίσης με n = 4 που είναι το μέγιστο μήκος του dst {'1', '2', '3', '\0'} και τα πράγματα γίνονται ακόμα χειρότερα, διότι θα αντιγραφεί το "5678" από το src στο dst, αλλά το '8' θα αντικαταστήσει το '\0' που βρισκόταν στο τέλος του dst πριν την αντιγραφή. Το αποτέλεσμα θα είναι να δημιουργηθεί ένα string dst το οποίο δεν θα έχει πουθενά μηδενικό χαρακτήρα, άρα δεν θα τελειώνει (στην πραγματικότητα θα συνεχίζει κι έξω από τα όριά του μέχρι να βρεθεί τυχαία κάπου στη μνήμη ένας μηδενικός χαρακτήρας).

Μια λύση που έρχεται στο μυαλό πρώτη είναι να προσθέτουμε ένα '\0' μετά την αντιγραφή, αλλά και πάλι αν το n ισούται με το μέγιστο μήκος του dst, τότε αυτό το '\0' που θα προσθέσουμε θα βγει έξω από τα όρια του dst (και άρα θα μηδενίσει ένα byte στη μνήμη, το οποίο δεν ανήκει στο dst! Δηλαδή, στο παράδειγμά μας, αν το n=4 κι εμείς προσθέτουμε ένα '\0' μετά την αντιγραφή των 4 πρώτων χαρακτήρων από το src στο dst, αυτό το 'έξτρα \0' θα μπει στην 5η θέση του dst η οποία πολύ απλά ΔΕΝ υπάρχει (η τελευταία θέση του dst όπως το έχουμε ορίσει είναι η 4η, η οποία οφείλει να φιλοξενεί έναν μηδενικό χαρακτήρα).

Στη δική μου υλοποίηση της strncpy (την οποία δεν θα σας τη δώσω ακόμα) αυτό που κάνω είναι να αντιγράφω όχι τους n πρώτους χαρακτήρες του src στο dst, αλλά τους n-1 χαρακτήρες! Στη θέση n βάζω πάντα τον μηδενικό χαρακτήρα. Άρα λοιπόν στη δική μου υλοποίηση το n περιλαμβάνει και τον μηδενικό χαρακτήρα, που με άλλα λόγια σημαίνει πως αντιγράφει n-1 ωφέλιμους χαρακτήρες και όχι n.

Προφανώς αν το n είναι μεγαλύτερο από το μέγιστο μήκος του dst (δλδ από 5 και πάνω στο παράδειγμά μας) το πρόβλημα επανέρχεται, αλλά αυτό το πρόβλημα υπάρχει και στην στάνταρ strncpy.

Η λύση είναι μέσα στη συνάρτηση μας να υπολογίζουμε πρώτα το μέγιστο μέγεθος του dst: sizeof( dst ) ή να το περνάμε σαν όρισμα στη συνάρτηση, και κατόπιν να το χρησιμοποιούμε στους ελέγχους που κάνουμε στο κύριο loop της συνάρτησης, φροντίζοντας η αντιγραφή από το src στο dst να περιορίζεται όχι από n αλλά από το μικρότερο νούμερο μεταξύ των n και sizeof( dst ).

Όταν δώσω τη δική μου λύση, θα έχω δυο εκδοχές της συνάρτησης: μια που δεν θα κάνει έλεγχο για το μέγιστο μήκος του dst και μια που θα κάνει.

Φίλε Σταματίου, η δική σου λύση "υποφέρει" από το έξτρα '\0' που προσθέτεις μετά την αντιγραφή των n χαρακτήρων, γιατί στην περίπτωση που το n ισούται με το μέγιστο μήκος του dst, ο έξτρα αυτός χαρακτήρας βγαίνει εκτός ορίων του dst.

Φίλε Star_Light, η δική σου λύση δεν υλοποιεί την strncpy, αλλά την strcpy (που δεν έχει n) οπότε θα την κοιτάξω λεπτομερώς όταν θα τη φτιάξει με το n. Επίσης, για να μη παιδεύεσαι, μη ζητάς τα strings από την κύρια είσοδο... όρισέ τα εσύ απευθείας μέσα στη main όπως κάνει ο φίλος Σταματίου ή όπως κάνω εγώ στο κώδικα που έδωσα πιο πάνω σε αυτό το post.

Επίσης, αυτό εδώ...
Κώδικας: Επιλογή όλων

printf("Dwse mia sumvoloseira: ");
fgets(s2,255,stdin);
sscanf(s2,"%c",s2);

σου έχω εξηγήσει τουλάχιστον 2 φορές από ότι θυμάμαι πως είναι λάθος και γιατί είναι λάθος ! :P Αφενός το %c αναφέρεται σε χαρακτήρα και εσύ το χρησιμοποιείς για string, αφετέρου στην scanf δεν μπορείς να έχεις το 1ο της όρισμα σε άλλα ορίσματα κι αφετρίτου :lol: για να διαβάζεις σκέτα strings δεν χρειάζεσαι τη scanf... χρειάζεσαι ή την fgets (και να πας να μηδενίσεις το '\n' μετά στο τέλος του string) ή την s_get ή την s_getflushed (αυτές οι 2 τελευταίες δεν βάζουν '\n' στο τέλος του string που διαβάζουν).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

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