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

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

Δημοσ.

Προσπαθώ να φτιάξω μια συνάρτηση που θα καλείται από τη main με σκοπό να εκτυπώνεται η συμβολοσειρά Little,by little,one travel far. χωρίς τα σημεία στίξης, δηλ:

 

Little

by

little

one

travel

far

 

Παραθέτω τον κώδικα που έκανα, αλλά κάτι δεν κάνω σωστά και τυπώνεται null και κάποιοι χαρακτήρες σκουπίδια.

Καμιά ιδέα κανείς?

 

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

char *my_Strtok(char *str, const char *p);

int main()
{
   const char  *delim=",.";
   const char str[]="Little,by little,one travel far.";


    printf("%s,%s",(my_Strtok(str,delim)));

}
char *my_Strtok(char *string, const char *p)
{

    if (!string)
     return NULL;
     char s[]="Little,by little,one travel far.";

    if(p!=NULL)

        printf("%s\n",p);
        while (p=my_Strtok(NULL,",.")!=NULL){
        printf("%s",p);
        }

    return 0;
}

Δημοσ.

Αν η strtok() δεν είναι προαπαιτούμενο της άσκησης, τότε...

#include <stdio.h>
#include <ctype.h>
 
void print_nopunct( const char *str )
{
    if ( !str || !*str )
       return;

    for (char *p=str; *p; p++) {
        if ( ispunct(*p) )
            putchar('\n');
        else
            putchar(*p);
    }
    fflush( stdout );
}
...

ή πιο εξειδικευμένα...

#include <stdio.h>
#include <string.h>
 
void print_nopunct( const char *str )
{
    if ( !str || !*str )
        return;

    for (char *p=str; *p; p++) {
        if ( strchr(".,", *p) )
            putchar('\n');
        else
            putchar(*p);
    }
    fflush( stdout );
}
...

ΥΓ. Αντί για p μπορείς να δουλέψεις κι απευθείας με το str μέσα στην συνάρτηση.

Δημοσ.

Αν η strtok() δεν είναι προαπαιτούμενο της άσκησης, τότε...

#include <stdio.h>
#include <ctype.h>
 
void print_nopunct( const char *str )
{
    if ( !str || !*str )
       return;

    for (char *p=str; *p; p++) {
        if ( ispunct(*p) )
            putchar('\n');
        else
            putchar(*p);
    }
    fflush( stdout );
}
...

ή πιο εξειδικευμένα...

#include <stdio.h>
#include <string.h>
 
void print_nopunct( const char *str )
{
    if ( !str || !*str )
        return;

    for (char *p=str; *p; p++) {
        if ( strchr(".,", *p) )
            putchar('\n');
        else
            putchar(*p);
    }
    fflush( stdout );
}
...

ΥΓ. Αντί για p μπορείς να δουλέψεις κι απευθείας με το str μέσα στην συνάρτηση.

Ευχαριστώ πολύ για την απάντηση σου.

Τι εννοείς με το αντί για p, ότι γίνεται και απευθείας με το str?

Δημοσ.

Εννοει οτι αντι να βάλεις εναν δεικτη να δειχνει στον πινακα χαρακτήρων str μπορεις να δουλεψεις απευθειας με αυτον.

 

 

 
for (int i = 0;  i < LEN ; i++) {
        if ( strchr(".,", str[i]) )
            putchar('\n');
        else
            putchar(str[i]);
 
Δημοσ.

Βασικά εννοούσα αυτό εδώ...

void print_nopunct( const char *str )
{
    if ( !str || !*str )
        return;

    for (; *str; str++) {
        if ( strchr("., \n\t", *str) )
            putchar('\n');
        else
            putchar(*str);
    }
    fflush( stdout );
}
...

ή αυτό που έδωσε ο StarLight αλλά χωρίς το LEN (το LEN καθυστερεί αχρείαστα τη συνάρτηση, γιατί πρέπει να υπολογιστεί πρώτα)...

void print_nopunct( const char *str )
{
    if ( !str || !*str )
        return;

    for (int i=0; str[i]; i++) {
        if ( strchr("., \n\t", str[i]) )
            putchar('\n');
        else
            putchar(str[i]);
    }
    fflush( stdout );
}
Δημοσ.

Ευχαριστώ πολύ και τους δυο σας. Κάτι τελευταίο, όταν ξεκινάει μια for με το ερωτηματικό ως πρώτο όρισμα μέσα στην παρένθεση, δηλ for(; ... ...) τι ακριβώς κάνει αυτό το ; ?

 

Ευχαριστώ εκ των προτέρων.

Δημοσ.

Ευχαριστώ πολύ και τους δυο σας. Κάτι τελευταίο, όταν ξεκινάει μια for με το ερωτηματικό ως πρώτο όρισμα μέσα στην παρένθεση, δηλ for(; ... ...) τι ακριβώς κάνει αυτό το ; ?

 

Ευχαριστώ εκ των προτέρων.

 

Ξεκιναει απο εκει που ο str ειναι ηδη αρχικοποιημενος δηλαδη απο την αρχη του πινακα. 

 

 

 
int i = 0;
 
for( ; i<4; i++) 
// do sth 
 

 

Το i πιο πανω ειναι ηδη αρχικοποιημενο αρα η for θα χρησιμοποιησει την τιμη που έχει ηδη.

Δημοσ.

#include <stdio.h>
#include <ctype.h>

char print_nopunct( const char *str )
{
    char *p;
    int i;
    if ( !str || !*str )
       return 0;

        for (*p=str; *p; p++) {
        if ( ispunct(*p) )
            putchar('\n');
        else
            putchar(*p);
    }
    fflush( stdout );
}

int main()
{
char k;
const char *pin ="Winter.Autumn,Spring,Summer.";
print_nopunct(pin);
 //pin=k;
 printf("[%s]\n",pin);
 return 0;
}

 

Ακολούθησα τον τρόπο με τη συνάρτηση ispunct, αλλά δεν τρέχει σωστά. Τυπώνει "σκουπίδια" στην αρχή και έπειτα τα[Winter.Autumn,Spring,Summer] μαζί με τα σημεία στίξης. Κάνω κάτι λάθος στην κλήση της συνάρτησης, στη main?
 

Δημοσ.

for (char *p=str; *p; p++) {

 

 

for (*p=str; *p; p++) {

Η δήλωση του migf1 με τη δική σου είναι τελείως διαφορετική. Ο migf χρησιμοποιεί μια μαγκιά της έκδοσης C99 του προτύπου που επιτρέπει να δηλώνεις μια μεταβλητή μέσα στο for αντί για την αρχή. Από εκεί και πέρα όταν έχεις μια δήλωση της μορφής

τύπος *μεταβλητή = κάτι;
αυτό σημαίνει

τύπος *μεταβλητή;
μεταβλητή = κάτι;
Βλέπεις την διαφορά με το δικό σου κώδικα ?
Δημοσ.

Ναι, το έπιασα! Ευχαριστώ. Αντικατέστησα στον έλεγχο της for (*p=str; *p; p++) , το *p με p και "έτρεξε" μια χαρά.

Ωραία. Κατάλαβες όμως ποιο ήταν το λάθος στο *p και γιατί έπρεπε αφενός να αλλάξει και αφετέρου να αλλάξει σε p και όχι σε κάτι άλλο ?

Δημοσ.

Ωραία. Κατάλαβες όμως ποιο ήταν το λάθος στο *p και γιατί έπρεπε αφενός να αλλάξει και αφετέρου να αλλάξει σε p και όχι σε κάτι άλλο ?

Θα ήθελα να αναλύσουμε αν γίνεται όλο τον έλεχγο for.

Γιατί περνάμε την str στην p και όχι στο δείκτη *p. To δεύτερο όρισμα της for,  *p ; μόνο του τι κάνει?

Δημοσ.

Θα ήθελα να αναλύσουμε αν γίνεται όλο τον έλεχγο for.

Γιατί περνάμε την str στην p και όχι στο δείκτη *p.

Ανάλυσε μας τι είναι το str, τι το p και τι το *p

 

To δεύτερο όρισμα της for,  *p ; μόνο του τι κάνει?

for(ανάθεση εκκίνησης; συνθήκη ελέγχου; δήλωση αύξησης)

 

Όταν έχεις for(i = 0; i < 5; i++) είναι σαν να έχεις

i = 0;
Τρέξε τις παρακάτω εντολές
    ..... { σώμα του for }
    i++
μέχρι το i να γίνει 5.
Το πρώτο τμήμα του for θέτει μια αρχική τιμή εκκίνησης στην μεταβλητή index που χρησιμοποιείς και υπάρχει για ευκολία. Όπως ρώτησες σε προηγούμενο μήνυμα, μπορεί να είναι κενό αν η μεταβλητή έχει αρχικοποιηθεί πιο μπροστά. Το τρίτο τμήμα είναι εκτελείται στο τέλος κάθε φοράς και (στην πλειοψηφία των περιπτώσεων) δηλώνει πώς αυξάνεται το index. Το δεύτερο τμήμα είναι η συνθήκη ελέγχου. Όσο αυτή δεν είναι ψευδής (0) τόσο θα τρέχει η ανακύκλωση.

 

Για πες μας λοιπόν τι σημαίνει το *p που υπάρχει στο 2ο όρισμα της for ?

Δημοσ.

Η str είναι μια σταθερά δείκτης τυπου char η οποία "δείχνει" τη συμβολοσειρα(το 1ο στοιχειο της). Η p είναι δείκτης τύπου char(τοπικη μεταβλητης της print_nopunct) και όσο δεν δείχνει σε στοιχειο εκτος συμβολοσειρας(να το πούμε έτσι?), αυξάνεται και στην ουσία σαρώνει τη συμβολοσειρα και αν βρει σημειο στιξης, αλλάζει γραμμή και τυπώνονται μόνο τα στοιχεία χωρίς όμως τα . και ,

Θα μπορούσαμε να πούμε ότι το δεύτερο όρισμα της for , είναι το p>0; ?

Tώρα, βέβαια γιατί p=str και όχι *p=str, δεν το 'χω "πιάσει" πλήρως...

 

 

Ανάλυσε μας τι είναι το str, τι το p και τι το *p
 

for(ανάθεση εκκίνησης; συνθήκη ελέγχου; δήλωση αύξησης)

Όταν έχεις for(i = 0; i < 5; i++) είναι σαν να έχεις

i = 0;
Τρέξε τις παρακάτω εντολές
    ..... { σώμα του for }
    i++
μέχρι το i να γίνει 5.
Το πρώτο τμήμα του for θέτει μια αρχική τιμή εκκίνησης στην μεταβλητή index που χρησιμοποιείς και υπάρχει για ευκολία. Όπως ρώτησες σε προηγούμενο μήνυμα, μπορεί να είναι κενό αν η μεταβλητή έχει αρχικοποιηθεί πιο μπροστά. Το τρίτο τμήμα είναι εκτελείται στο τέλος κάθε φοράς και (στην πλειοψηφία των περιπτώσεων) δηλώνει πώς αυξάνεται το index. Το δεύτερο τμήμα είναι η συνθήκη ελέγχου. Όσο αυτή δεν είναι ψευδής (0) τόσο θα τρέχει η ανακύκλωση.

Για πες μας λοιπόν τι σημαίνει το *p που υπάρχει στο 2ο όρισμα της for ?

 

Δημοσ.

@lektikos το σύμβολο / μπορει να χρησιμοποιηθει και σαν διαιρεση και στα σχολια (με ενα αστερακι μετα). 

 

Ετσι και το συμβολο * . Μπορει να χρησιμοποιηθει και στον πολλαπλασιασμο και στην δηλωση ενος δεικτη και στην αποαναφοροποιηση του δεικτη (που παιρνεις το περιεχομενο της διευθυνσης που δειχνει ο δεικτης). Οταν δηλωνεις εναν δεικτη ο μεταγλωτιστης ξέρει οτι αυτο το συμβολο ειναι για αυτη την δουλεια επομενως κατα την στιγμη της δηλωσης του μπορει να αρχικοποιησεις τον δεικτη με μια διευθυνση στην προκειμενη με την διευθυνση του string. To str ειναι μια σταθερη διευθυνση και αντιμετωπιζεται σαν δεικτης ΜΟΝΟ οταν περνάει σαν ορισμα σε μια συνάρτηση σε ολες τις υπολοιπες περιπτωσεις ειναι πίνακας και οχι δεικτης. Για παράδειγμα αμα δηλωθει ενας πινακας στην main και δεν τον περνάς σε καποια συνάρτηση τοτε ειναι πινακας.

 

Επισης το συμβολο * διπλα στον p ΣΕ ΟΛΕΣ τις αλλες περιπτωσεις (εκτος της δηλωσης του που εγραψα πριν) αντιμετωπιζεται ως συμβολο αποαναφοροποιησης του δεικτη. Οποτε το χρησιμοποιεις δηλαδη θα παιρνεις το περιεχομενο του. Φυσικα η κατασταση αλλαζει οταν μιλαμε για διπλους δεικτες αλλα αυτο δεν σε απασχολει προς το παρον. 

 

Το for ή ανακυκλωση θα σταματησει οταν το *p γινει 0. Δωσει δηλαδη μη αληθη τιμη. Εκτιμηθει σε 0 που ειναι ο ASCII του null character '\0' για αυτο το λογο θα πρεπει ένα εγκυρο C-string να τερματιζει με αυτο τον χαρακτηρα σαν τελευταιο του. Ο βροχος θα σταματησει οταν το string φτασει στο τέλος του.

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

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

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

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

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

Σύνδεση

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

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