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

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

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

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

Δημοσίευσηαπό medigeek » 18 Ιουν 2011, 15:13

Χρόνο όσο θέλεις, θα τα κοιτάξω ξανά αργότερα το απόγευμα. Ελπίζω πως αυτό που έκανα χωρίς τους δείκτες να είναι σωστό.
Ας περιμένουμε και τον clepto, δεν έχουμε λόγο να βιαζόμαστε. :)
Κύπριος; Κόπιασε στο ubuntu-cy! ┃ Launchpad Debian Github
Οδηγός για νεοεισερχόμενους -- Αρχικές οδηγίες για αρχάριους χρήστες του Ubuntu

1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 12.10 quantal 3.5.0-21-generic 64bit (en_US.UTF-8, GNOME cinnamon2d), Ubuntu 3.5.0-19-generic, Windows 7
3 Intel Core2 Duo CPU E6550 2.33GHz ‖ RAM 5970 MiB ‖ MSI MS-7235
4 nVidia G73 [GeForce 7300 GT] [10de:0393] {nvidia}
5 eth0: Realtek RTL-8110SC/8169SC Gigabit Ethernet [10ec:8167] (rev 10)
Άβαταρ μέλους
medigeek
Freedom
Freedom
 
Δημοσιεύσεις: 5023
Εγγραφή: 24 Μάιος 2008, 14:49
Τοποθεσία: Σερβία/Κύπρος
Launchpad: medigeek
IRC: savvas
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 18 Ιουν 2011, 15:14

Με την ευκαιρία βρήκα κι ένα bug στον δικό μου κώδικα! Το dummy πρέπει να το ορίζω ως σκέτο char και όχι ως δείκτη σε char (πάω να το διορθώσω και στο προηγούμενο ποστ, αλλά και στη Ξερή :( )

Σημείωση: λειτουργεί μονάχα με αρχικοποιημένα strings!

Δηλαδή το:
Κώδικας: Επιλογή όλων
puts( s_reverse( "Hello cruel world") );
ΚΡΑΣΑΡΕΙ, κι είναι λογικό γιατί σε αυτή την περίπτωση δεν του περνάμε δικιά μας μεταβλητή string, αλλά string literal (δηλαδή σταθερά τύπου string" που δεν είναι αποθηκευμένη σε δικιά μας μεταβλητή). Για τα string literals ο compiler δημιουργεί δικές του εσωτερικές μεταβλητές τύπου string, οι οποίες είναι όμως READ ONLY, κι εδώ η s_reverse() αλλάζει τα περιεχόμενα του ορίσματος s.

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

char s[] = "Hello cruel world";
puts( s_reverse(s) );

Παραθέτω και τις 2 εκδόσεις του κώδικα, με και χωρίς δείκτες ;)
Spoiler: show
Κώδικας: Επιλογή όλων

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

// ***********************************************************
char *s_reverse1(char s[])
{
if ( !s ) // early exit
return NULL;

char dummy;
register int i,j;

j = strlen(s) - 1;
for (i=0; i < j; i++, j--) {
dummy = s[i];
s[i] = s[j];
s[j] = dummy;
}

return s;
}
// ***********************************************************
char *s_reverse2(char *s)
{
if ( !s ) // early exit
return NULL;

char *cp1, *cp2, dummy;

cp2 = s + strlen(s) - 1; // set cp2 at end of s
for (cp1=s; cp1 < cp2; cp1++, cp2--) {
dummy = *cp1;
*cp1 = *cp2;
*cp2 = dummy;
}

return s;
}

// ***********************************************************
int main( void )
{
char s[] = "Hello cruel world";
puts( s_reverse1(s) );
puts( s_reverse2(s) );

fflush(stdin); getchar();
exit(0);
}

Τελευταία επεξεργασία από migf1 και 18 Ιουν 2011, 19:14, έχει επεξεργασθεί 2 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό clepto » 18 Ιουν 2011, 15:32

συνεχίστε εσείς...εγώ δεν έχω πρόβλημα...
έτσι και αλλιώς δεν νομίζω να την καταφέρω την άσκηση...θέλω διάβασμα ακόμα!
1 Γνώσεις Linux: Ικανοποιητικό ┃ Προγραμματισμού: Ικανοποιητικό ┃ Αγγλικών: Ικανοποιητικό
2 Ubuntu 13.04 raring 3.8.0-30-generic 64bit (en_US.UTF-8, Unity ubuntu), Ubuntu 3.8.0-19-generic, Windows 7
3 Intel Core i7-3537U CPU @ 2.00GHz ‖ RAM 3840 MiB ‖ ASUS K56CB
4 Intel 3rd Gen Core processor Graphics Controller [8086:0166] {i915}
5 wlan0: Atheros Inc. AR9485 Wireless Network Adapter [168c:0032] (rev 01) ⋮ eth0: Realtek RTL8111/8168 PCI Express Gigabit Ethernet controller [10ec:8168] (rev 0a)
clepto
antiwinTUX
antiwinTUX
 
Δημοσιεύσεις: 4102
Εγγραφή: 07 Ιαν 2010, 16:27
Τοποθεσία: Πάτρα
Launchpad: christriant
IRC: Clepto
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 18 Ιουν 2011, 17:48

medigeek έγραψε:[snip]
Ελπίζω πως αυτό που έκανα χωρίς τους δείκτες να είναι σωστό.
[snip]

Μια χαρά σωστό είναι, και δουλεύει και με string literals, λόγω του static που έβαλες στον ορισμό του newss και την επιστροφή του από τη συνάρτηση. Το μειονέκτημά της είναι οι μειωμένες επιδόσεις και το γεγονός πως αν της περάσεις string literal χωρίς '\n' κόβει τον τελευταίο χαρακτήρα.

Στη δικιά μου έκδοση το μειονέκτημα είναι η μη λειτουργία με string literals (διορθώνεται με ορισμό static string, κόπια του s σε αυτό κι επιστροφή του, αλλά χάνει σε επιδόσεις μετά).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό clepto » 18 Ιουν 2011, 20:57

διόρθωσα το θέμα με τους αρνητικούς αριθμούς :)
Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <math.h>
#include <string.h>

int x, y, z, x2, y2, z2, day, month, year, day1, month1, year1;


int main(void) {


printf("Πόσο έχει ο μήνας: ");
scanf("%d", &x);

printf("Ποιος μήνας είναι: ");
scanf("%d", &y);

printf("Ποια χρονιά είναι: ");
scanf("%d", &z);



printf("Ποσο ειχε την μερα που γεννηθηκες; ");
scanf("%d", &x2);

printf("Ποιον μηνα γεννηθηκες: ");
scanf("%d", &y2);

printf("Ποια χρονιά γεννηθηκες: ");
scanf("%d", &z2);



day = (x-x2);
month = (y-y2);
year = (z-z2);

if (month<0 && day<0) {
year1 = (year-1);
month1 = (12+month);
day1 = (30+day);
printf("Είσαι %d χρονών, %d μηνών και %d ημερών \n", year1, month1, day1);
}
else if (month>0 && day>0) {
printf("Είσαι %d χρονών, %d μηνών και %d ημερών \n", year, month, day);
}

}
1 Γνώσεις Linux: Ικανοποιητικό ┃ Προγραμματισμού: Ικανοποιητικό ┃ Αγγλικών: Ικανοποιητικό
2 Ubuntu 13.04 raring 3.8.0-30-generic 64bit (en_US.UTF-8, Unity ubuntu), Ubuntu 3.8.0-19-generic, Windows 7
3 Intel Core i7-3537U CPU @ 2.00GHz ‖ RAM 3840 MiB ‖ ASUS K56CB
4 Intel 3rd Gen Core processor Graphics Controller [8086:0166] {i915}
5 wlan0: Atheros Inc. AR9485 Wireless Network Adapter [168c:0032] (rev 01) ⋮ eth0: Realtek RTL8111/8168 PCI Express Gigabit Ethernet controller [10ec:8168] (rev 0a)
clepto
antiwinTUX
antiwinTUX
 
Δημοσιεύσεις: 4102
Εγγραφή: 07 Ιαν 2010, 16:27
Τοποθεσία: Πάτρα
Launchpad: christriant
IRC: Clepto
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 18 Ιουν 2011, 22:57

Υπάρχει πρόβλημα :(

Π.χ. δοκίμασε 18/6/2011 με 5/10/2000, δεν μπαίνει ούτε στο if ούτε στο else, οπότε τερματίζει χωρίς να τυπώσει τίποτα.

Υποθέτω αυτό που θέλεις να κάνεις, σαν λογική, είναι κάτι σαν το παρακάτω ε;
Κώδικας: Επιλογή όλων

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

int main( void )
{
int d1, m1, y1, d2, m2, y2, days, months, years;

// διάβασε την 1η ημερομηνία

printf("Πόσο έχει ο μήνας: ");
scanf("%d", &d1);

printf("Ποιος μήνας είναι: ");
scanf("%d", &m1);

printf("Ποια χρονιά είναι: ");
scanf("%d", &y1);

// διάβασε τη 2η ημερομηνία

printf("\nΠοσο ειχε την μερα που γεννηθηκες; ");
scanf("%d", &d2);

printf("Ποιον μηνα γεννηθηκες: ");
scanf("%d", &m2);

printf("Ποια χρονιά γεννηθηκες: ");
scanf("%d", &y2);

// υπολόγισε τη διαφορά μεταξύ των ημερομηνιών

days = d1 - d2;
months = m1 - m2;
years = y1 - y2;

if (months < 0) {
months += 12;
years--;
}
if (days < 0) {
days += 30;
months--;
}

printf("\nΕίσαι %d χρονών, %d μηνών και %d ημερών \n", years, months, days);

/*
if (month < 0 && day < 0)
{
year1 = year - 1;
month1 = 12 + month;
day1 = 30 + day;
printf("Είσαι %d χρονών, %d μηνών και %d ημερών \n", year1, month1, day1);
}
else if (month > 0 && day > 0 ) {
printf("Είσαι %d χρονών, %d μηνών και %d ημερών \n", year, month, day);
}
*/

printf("\npress ENTER to exit...");
fflush(stdin); getchar();

return 0;
}
(άλλαξα και τα ονόματα των μεταβλητών ώστε να είναι πιο ευανάγνωστα, έβαλα τον παλιό κώδικα σε σχόλια και σου έβαλα τις αυξήσεις και τις μειώσεις με τους τελεστές += και --)

Δεν το τεστάρισα με πολλές περιπτώσεις εισόδου, αλλά δείχνει να δουλεύει σωστά όση η 2η ημερομηνία είναι μικρότερη της 1ης (άρα τώρα λείπει ο έλεγχος ώστε η 2η ημερομηνία να είναι πάντα μικρότερη ;))
Τελευταία επεξεργασία από migf1 και 18 Ιουν 2011, 23:48, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 18 Ιουν 2011, 23:43

Μπα, δεν δουλεύει ούτε έτσι, κολλάει αλλού :(

Αν έχεις κατεβάσει το dates.c που έχω ποστάρει στο άλλο νήμα, δες τη συνάρτηση:
Κώδικας: Επιλογή όλων
long date_diff( Date *datediff, Date date1, Date date2, int mdays[] )
της έχω και σύνδεσμο προς σελίδα που αναλύει τον αλγόριθμο αφαίρεσης μεταξύ 2 ημερομηνιών ;)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό clepto » 19 Ιουν 2011, 00:11

σε ποιο θέμα έχεις ποστάρει αυτήν την συνάρτηση;
1 Γνώσεις Linux: Ικανοποιητικό ┃ Προγραμματισμού: Ικανοποιητικό ┃ Αγγλικών: Ικανοποιητικό
2 Ubuntu 13.04 raring 3.8.0-30-generic 64bit (en_US.UTF-8, Unity ubuntu), Ubuntu 3.8.0-19-generic, Windows 7
3 Intel Core i7-3537U CPU @ 2.00GHz ‖ RAM 3840 MiB ‖ ASUS K56CB
4 Intel 3rd Gen Core processor Graphics Controller [8086:0166] {i915}
5 wlan0: Atheros Inc. AR9485 Wireless Network Adapter [168c:0032] (rev 01) ⋮ eth0: Realtek RTL8111/8168 PCI Express Gigabit Ethernet controller [10ec:8168] (rev 0a)
clepto
antiwinTUX
antiwinTUX
 
Δημοσιεύσεις: 4102
Εγγραφή: 07 Ιαν 2010, 16:27
Τοποθεσία: Πάτρα
Launchpad: christriant
IRC: Clepto
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 19 Ιουν 2011, 01:28

Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 19 Ιουν 2011, 12:37

Επειδή πρέπει να φύγω και δεν έχω προλάβει να τεστάρω σωστά, για δες αν δουλεύει σωστά ο παρακάτω κώδικας. Αν δουλεύει, τότε τα επόμενα βήματα είναι να γίνεται έλεγχος α) για τον αν οι 2 ημερομηνίες είναι σωστές (π.χ. 29/2/2011 δεν υπάρχει) και β) για τον αν η 2η είναι μικρότερη από την 1η (ώστε να έχει νόημα μετά η αφαίρεση).

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

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

#define isleap(y) ( !((y) % 4) && ( (y) % 100 || !((y) % 400) ) )

// ----------------------------------------------------------------------
int main( void )
{
int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int d1, m1, y1, d2, m2, y2, days, months, years;

// διάβασε την 1η ημερομηνία
printf("Πόσο έχει σήμερα (η μ χ): ");
scanf("%d %d %d", &d1, &m1, &y1);

// διάβασε τη 2η ημερομηνία
printf("Πότε γεννηθήκατε (η μ χ); ");
scanf("%d %d %d", &d2, &m2, &y2);

// υπολόγισε τη διαφορά μεταξύ των ημερομηνιών

days = d1 - d2;
months = m1 - m2;
years = y1 - y2;

if (months < 0) {
months += 12;
years--;
}
if (days < 0) {
days += mdays[m2-1];
if ( m2 == 2 && isleap(y2) )
days++;
months--;
}

printf("\nΕίστε %d χρονών, %d μηνών και %d ημερών \n", years, months, days);

printf("\npress ENTER to exit...");
fflush(stdin); getchar();

return 0;
}
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

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

cron