Χορδές σε C. Εισαγωγή. Εργασία με χορδές. Κατηγορία χορδών. Κατασκευαστές τάξης. Οι συναρτήσεις εκχώρησης (), προσθήκη (), εισαγωγή (), αντικατάσταση (), διαγραφή (), εύρεση (), rfind (), σύγκριση (), c_str (). Παραδείγματα του

Χορδές. Γραμμές I/O. Μορφοποιημένο I/O. Επεξεργασία συμβολοσειρών με χρήση τυπικών συναρτήσεων C. Εργασία με μνήμη.

1.1. Δήλωση και αρχικοποίηση συμβολοσειρών.

Μια συμβολοσειρά είναι ένας πίνακας χαρακτήρων που τελειώνει με τον κενό χαρακτήρα '\ 0'. Η συμβολοσειρά δηλώνεται ως ένας κανονικός πίνακας χαρακτήρων, για παράδειγμα

char s1; // συμβολοσειρά μήκους εννέα χαρακτήρων

char * s2; // δείκτης σε συμβολοσειρά

Η διαφορά μεταξύ s1 και s2 είναι ότι η s1 είναι μια ονομαζόμενη σταθερά και η s2 είναι μια μεταβλητή.

Οι σταθερές συμβολοσειράς περικλείονται σε διπλά εισαγωγικά, σε αντίθεση με τους χαρακτήρες που περικλείονται σε μονά εισαγωγικά. Για παράδειγμα,

«Αυτό είναι μια χορδή».

Το μήκος μιας σταθεράς συμβολοσειράς δεν μπορεί να υπερβαίνει τους 509 χαρακτήρες από το πρότυπο. Ωστόσο, πολλές υλοποιήσεις επιτρέπουν μεγαλύτερες συμβολοσειρές.

Κατά την προετοιμασία των συμβολοσειρών, είναι καλύτερα να μην προσδιορίσετε τη διάσταση του πίνακα· ο μεταγλωττιστής θα το κάνει αυτό υπολογίζοντας το μήκος της συμβολοσειράς και προσθέτοντας μία σε αυτήν. Για παράδειγμα,

char s1 = "Αυτή είναι μια συμβολοσειρά.";

Στη γλώσσα προγραμματισμού C, για εργασία με συμβολοσειρές, υπάρχει ένας μεγάλος αριθμός απόσυναρτήσεις των οποίων τα πρωτότυπα περιγράφονται στα αρχεία κεφαλίδας stdlib.h και string.h. Η εργασία με αυτές τις λειτουργίες θα συζητηθεί στις επόμενες παραγράφους.

1.2. Γραμμές I/O.

Για να εισαγάγετε μια συμβολοσειρά από την κονσόλα, χρησιμοποιήστε τη συνάρτηση

char * παίρνει (char * str);

που γράφει μια συμβολοσειρά στο str και επιστρέφει τη διεύθυνση της συμβολοσειράς που εισάγατε. Η συνάρτηση σταματά την είσοδο όταν συναντήσει τον χαρακτήρα '\ n' ή EOF (τέλος αρχείου). Ο χαρακτήρας της νέας γραμμής δεν αντιγράφεται. Ένα μηδενικό byte τοποθετείται στο τέλος της γραμμής ανάγνωσης. Σε περίπτωση επιτυχίας, η συνάρτηση επιστρέφει έναν δείκτη στη συμβολοσειρά ανάγνωσης και σε περίπτωση αποτυχίας, NULL.

Για έξοδο μιας γραμμής στην κονσόλα, χρησιμοποιήστε την τυπική συνάρτηση

int puts (const char * s);

που επιστρέφει έναν μη αρνητικό αριθμό στην επιτυχία και τον ΕΟΦ σε περίπτωση αποτυχίας.

Τα πρωτότυπα συναρτήσεων gets και puts περιγράφονται στο αρχείο κεφαλίδας stdio.h.

#περιλαμβάνω

printf ("Συμβολοσειρά εισόδου:");

1.3. Μορφοποιημένο I/O.

Για μορφοποιημένη εισαγωγή δεδομένων από την κονσόλα, χρησιμοποιήστε τη συνάρτηση

int scanf (const char * μορφή, ...);

το οποίο, εάν είναι επιτυχές, επιστρέφει τον αριθμό των μονάδων δεδομένων που διαβάστηκαν και αν όχι, επιστρέφει τον ΕΟΦ. Η παράμετρος μορφή πρέπει να δείχνει σε μια μορφοποιημένη συμβολοσειρά που περιέχει προδιαγραφές των μορφών εισόδου. Ο αριθμός και οι τύποι ορισμάτων που ακολουθούν τη συμβολοσειρά μορφοποίησης πρέπει να ταιριάζουν με τον αριθμό και τους τύπους των μορφών εισόδου που καθορίζονται στη συμβολοσειρά μορφοποίησης. Εάν αυτή η προϋπόθεση δεν πληρούται, τότε το αποτέλεσμα της συνάρτησης είναι απρόβλεπτο.

Το διάστημα, οι χαρακτήρες "\ t" ή "\ n" στη συμβολοσειρά μορφοποίησης περιγράφουν έναν ή περισσότερους κενούς χαρακτήρες στη ροή εισόδου, οι οποίοι περιλαμβάνουν χαρακτήρες: space, '\ t', '\ n', '\ v', '\ στ'. Η λειτουργία σάρωσης παρακάμπτει τους κενούς χαρακτήρες στη ροή εισόδου.

Οι κυριολεκτικοί χαρακτήρες στη συμβολοσειρά μορφοποίησης, με εξαίρεση τον χαρακτήρα %, απαιτούν να εμφανίζονται ακριβώς οι ίδιοι χαρακτήρες στη ροή εισόδου. Εάν δεν υπάρχει τέτοιος χαρακτήρας, τότε το scanf διακόπτει την είσοδο. Η λειτουργία σάρωσης παρακάμπτει τους κυριολεκτικούς χαρακτήρες.

Γενικά, οι προδιαγραφές της μορφής εισόδου είναι:

% [*] [πλάτος] [τροποποιητές] τύπος

Ο χαρακτήρας '*' υποδηλώνει παράλειψη κατά την είσοδο σε ένα πεδίο που ορίζεται από αυτήν την προδιαγραφή.

- Το «πλάτος» καθορίζει τον μέγιστο αριθμό χαρακτήρων που εισάγονται σύμφωνα με αυτήν την προδιαγραφή·

Ο τύπος μπορεί να λάβει τις ακόλουθες τιμές:

γ - πίνακας χαρακτήρων,

s - συμβολοσειρά χαρακτήρων, οι συμβολοσειρές χωρίζονται με κενούς χαρακτήρες,

d - υπογεγραμμένος ακέραιος σε 10 s / s,

Το i είναι ένας ακέραιος αριθμός, το σύστημα αριθμών εξαρτάται από τα δύο πρώτα ψηφία,

u - ανυπόγραφος ακέραιος στα 10 s/s,

o - ανυπόγραφος ακέραιος σε 8 s/s,

x, X - ανυπόγραφος ακέραιος σε 16 s / s,

e, E, f, g, G - κυμαινόμενος αριθμός,

Το p είναι ένας δείκτης σε έναν δείκτη,

Το n είναι δείκτης σε έναν ακέραιο αριθμό,

[...] - συστοιχία σαρωμένων χαρακτήρων, για παράδειγμα,.

Στην τελευταία περίπτωση, μόνο χαρακτήρες που περικλείονται σε αγκύλες θα εισαχθούν από τη ροή εισόδου. Εάν ο πρώτος χαρακτήρας μέσα στις αγκύλες είναι «^», τότε εισάγονται μόνο εκείνοι οι χαρακτήρες που δεν βρίσκονται στον πίνακα. Το εύρος των χαρακτήρων στον πίνακα καθορίζεται χρησιμοποιώντας το σύμβολο '-'. Κατά την εισαγωγή χαρακτήρων, εισάγονται επίσης κενά στην αρχή και το τερματικό μηδενικό byte της συμβολοσειράς.

Οι τροποποιητές μπορούν να λάβουν τις ακόλουθες τιμές:

h - σύντομος ακέραιος,

l, L - μακρύς ακέραιος ή float,

και χρησιμοποιούνται μόνο για ακέραιους αριθμούς ή πλωτήρες.

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

#περιλαμβάνω

printf ("Εισαγωγή ακέραιου αριθμού:");

scanf ("% d", & n);

printf ("Εισαγωγή διπλού:");

scanf ("% lf", & d);

printf ("Εισαγωγή χαρακτήρων:");

scanf ("% c", & c);

printf ("Εισαγωγή συμβολοσειράς:");

scanf ("% s", & s);

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

Για μορφοποιημένη έξοδο στην κονσόλα, χρησιμοποιήστε τη συνάρτηση

int printf (const char * μορφή, ...);

το οποίο, εάν είναι επιτυχές, επιστρέφει τον αριθμό των μονάδων εξόδου δεδομένων, και εάν όχι, επιστρέφει ΕΟΦ. Η παράμετρος μορφή είναι μια μορφοποιημένη συμβολοσειρά που περιέχει προδιαγραφές για τις μορφές εξόδου. Ο αριθμός και οι τύποι ορισμάτων που ακολουθούν τη συμβολοσειρά μορφοποίησης πρέπει να ταιριάζουν με τον αριθμό και τους τύπους των προδιαγραφών μορφής εξόδου που δίνονται στη συμβολοσειρά μορφοποίησης. Γενικά, οι προδιαγραφές της μορφής εξόδου είναι:

% [σημαία] [πλάτος] [. ακρίβεια] [τροποποιητές] τύπος

- οι «σημαίες» είναι διάφορα σύμβολα που καθορίζουν τη μορφή εξόδου·

- Το «πλάτος» ορίζει τον ελάχιστο αριθμό χαρακτήρων που εμφανίζονται σύμφωνα με αυτήν την προδιαγραφή·

- ".precision" ορίζει τον μέγιστο αριθμό χαρακτήρων που θα εμφανίζονται.

- οι «τροποποιητές» καθορίζουν τον τύπο των ορισμάτων·

- «τύπος» ορίζει τον τύπο του ορίσματος.

Οι υπογεγραμμένοι ακέραιοι αριθμοί εξάγονται στην ακόλουθη μορφή:

% [-] [+ | διάστημα] [πλάτος] [l] δ

- - ευθυγράμμιση προς τα αριστερά, από προεπιλογή - προς τα δεξιά.

+ - εμφανίζεται το σύμβολο «+», σημειώστε ότι για αρνητικούς αριθμούς εμφανίζεται πάντα το σύμβολο «-».

«Διάστημα» - εμφανίζεται ένα κενό στη θέση χαρακτήρων.

d - τύπος δεδομένων int.

Η ακόλουθη μορφή εξόδου χρησιμοποιείται για την έξοδο ανυπόγραφων ακεραίων:

% [-] [#] [πλάτος] [l]

# - το αρχικό 0 εμφανίζεται για αριθμούς σε 8 c / s ή το αρχικό 0x ή 0X για αριθμούς σε 16 c / s,

l - τροποποιητής του τύπου μακράς δεδομένων.

u - ακέραιος σε 10c / s,

o - ακέραιος σε 8 s / s,

x, X είναι ακέραιος αριθμός 16 s / s.

Για αριθμούς κινητής υποδιαστολής, χρησιμοποιείται η ακόλουθη μορφή εξόδου:

% [-] [+ | διάστημα] [πλάτος] [.ακρίβεια]

Η "ακρίβεια" υποδηλώνει τον αριθμό των ψηφίων μετά την υποδιαστολή για τις μορφές f, e και E ή τον αριθμό των σημαντικών ψηφίων για τις μορφές g και G. Οι αριθμοί στρογγυλοποιούνται. Η προεπιλογή είναι έξι δεκαδικά ψηφία.

στ - αριθμός σταθερού σημείου,

e - ένας αριθμός σε εκθετική μορφή, ο εκθέτης συμβολίζεται με το γράμμα "e",

E - ένας αριθμός σε εκθετική μορφή, ο εκθέτης συμβολίζεται με το γράμμα "E",

g - η συντομότερη από τις μορφές f ή g,

Το G είναι η συντομότερη από τις μορφές f ή G.

printf ("n =% d \ n f =% f \ n e =% e \ n E =% E \ n f =% .2f", -123, 12.34, 12.34, 12.34, 12.34);

// εκτυπώσεις: n = 123 f = 12,340000 e = 1,234000e + 001 E = 1,234000E + 001 f = 12,34

1.4. Μορφοποίηση συμβολοσειρών.

Υπάρχουν παραλλαγές των συναρτήσεων scanf και printf για τη μορφοποίηση συμβολοσειρών και ονομάζονται sscanf και sprintf, αντίστοιχα.

int sscanf (const char * str, const char * μορφή, ...);

διαβάζει δεδομένα από τη συμβολοσειρά που καθορίζεται από την παράμετρο str σύμφωνα με τη συμβολοσειρά μορφής που καθορίζεται από την παράμετρο μορφής. Επιστρέφει τον όγκο των δεδομένων που διαβάζονται για την επιτυχία και τον ΕΟΦ σε περίπτωση αποτυχίας. Για παράδειγμα,

#περιλαμβάνω

char str = "a 10 1.2 String Χωρίς είσοδο";

sscanf (str, "% c% d% lf% s", & c, & n, & d, s);

printf ("% c \ n", c); // εκτυπώνει: α

printf ("% d \ n", n); // εκτυπώσεις: 10

printf ("% f \ n", d); // εκτυπώσεις: 1,200000

printf ("% s \ n", s); // prints: String

int sprintf (char * buffer, const char * format, ...);

μορφοποιεί τη συμβολοσειρά σύμφωνα με τη μορφή που καθορίζεται από την παράμετρο μορφής και εγγράφει το αποτέλεσμα στο buffer του πίνακα χαρακτήρων. Η συνάρτηση επιστρέφει τον αριθμό των χαρακτήρων που είναι γραμμένοι στην προσωρινή μνήμη του πίνακα χαρακτήρων, εξαιρουμένου του μηδενικού byte τερματισμού. Για παράδειγμα,

#περιλαμβάνω

char str = "c =% c, n =% d, d =% f, s =% s";

char s = "Αυτή είναι μια συμβολοσειρά.";

sprintf (buffer, str, c, n, d, s);

printf ("% s \ n", buffer); // εκτυπώνει: c = c, n = 10, d = 1,200000, s = Αυτή είναι μια συμβολοσειρά

1.5. Μετατροπή συμβολοσειρών σε αριθμητικά δεδομένα.

Πρωτότυπα συναρτήσεων για τη μετατροπή συμβολοσειρών σε αριθμητικά δεδομένα δίνονται στο αρχείο κεφαλίδας stdlib.h, το οποίο πρέπει να συμπεριληφθεί στο πρόγραμμα.

Για να μετατρέψετε μια συμβολοσειρά σε ακέραιο, χρησιμοποιήστε τη συνάρτηση

int atoi (const char * str);

char * str = “-123”;

n = atoi (str); // n = -123

Για να μετατρέψετε μια συμβολοσειρά σε μακρύ ακέραιο, χρησιμοποιήστε τη συνάρτηση

long int atol (const char * str);

το οποίο, εάν είναι επιτυχές, επιστρέφει έναν ακέραιο αριθμό στον οποίο έχει μετατραπεί η συμβολοσειρά str και εάν το 0 αποτύχει, για παράδειγμα,

char * str = “-123”;

n = ατόλη (str); // n = -123

Για να μετατρέψετε μια συμβολοσειρά σε διπλή, χρησιμοποιήστε τη συνάρτηση

διπλό atof (const char * str);

το οποίο, εάν είναι επιτυχές, επιστρέφει έναν κυμαινόμενο αριθμό τύπου double, στον οποίο έχει μετατραπεί η συμβολοσειρά και εάν το 0 αποτύχει, για παράδειγμα,

char * str = “-123.321”;

n = atof (str); // n = -123.321

Οι παρακάτω συναρτήσεις εκτελούν ενέργειες παρόμοιες με τις λειτουργίες atoi, atol, atof, αλλά παρέχουν πιο προηγμένες λειτουργίες.

long int strtol (const char * str, char ** endptr, int base);

μετατρέπει τη συμβολοσειρά str σε μεγάλη int, την οποία επιστρέφει. Οι παράμετροι αυτής της συνάρτησης έχουν την εξής σημασία.

Εάν η βάση είναι 0, τότε η μετατροπή εξαρτάται από τους δύο πρώτους χαρακτήρες του str:

Εάν ο πρώτος χαρακτήρας είναι ένα ψηφίο από το 1 έως το 9, τότε υποτίθεται ότι ο αριθμός αντιπροσωπεύεται σε 10 s / s.

Εάν ο πρώτος χαρακτήρας είναι ένα ψηφίο 0 και ο δεύτερος είναι ένα ψηφίο από το 1 έως το 7, τότε υποτίθεται ότι ο αριθμός αντιπροσωπεύεται σε 8 c / s.

Εάν ο πρώτος χαρακτήρας είναι 0 και ο δεύτερος είναι «X» ή «x», υποτίθεται ότι ο αριθμός αντιπροσωπεύεται σε 16 c / s.

Εάν η βάση είναι ένας αριθμός μεταξύ 2 και 36, τότε αυτή η τιμή λαμβάνεται ως βάση της βάσης και οποιοσδήποτε χαρακτήρας εκτός αυτής της βάσης διακόπτει τη μετατροπή. Η βάση 11 έως 36 χρησιμοποιεί τους χαρακτήρες 'A' έως 'Z' ή 'a' έως 'z' για να αναπαραστήσει αριθμούς.

Το όρισμα endptr ορίζεται από τη συνάρτηση strtol. Αυτή η τιμή περιέχει έναν δείκτη στον χαρακτήρα που σταμάτησε τη μετατροπή του str. Εάν είναι επιτυχής, η συνάρτηση strtol επιστρέφει τον αριθμό που έχει μετατραπεί και εάν αποτύχει, επιστρέφει 0. Για παράδειγμα,

n = strtol ("12a", & p, 0);

printf ("n =% ld,% stop =% c, n, * p); // n = 12, στάση = α

n = strtol ("012b", & p, 0);

printf ("n =% ld,% stop =% c, n, * p); // n = 10, διακοπή = β

n = strtol ("0x12z", & p, 0);

printf ("n =% ld,% stop =% c, n, * p); // n = 18, stop = z

n = strtol ("01117", & p, 0);

printf ("n =% ld,% stop =% c, n, * p); // n = 7, stop = 7

ανυπόγραφο long int strtol (const char * str, char ** endptr, int base);

λειτουργεί παρόμοια με το strtol, αλλά μετατρέπει την αναπαράσταση χαρακτήρων ενός αριθμού σε ανυπόγραφο μακρύ int.

διπλό strtod (const char * str, char ** endptr);

μετατρέπει την παράσταση χαρακτήρων ενός αριθμού σε διπλό.

Όλες οι συναρτήσεις που αναφέρονται σε αυτήν την παράγραφο σταματούν την εργασία τους όταν συναντήσουν τον πρώτο χαρακτήρα που δεν ταιριάζει στη μορφή του εν λόγω αριθμού.

Επιπλέον, εάν η τιμή χαρακτήρων ενός αριθμού υπερβαίνει το εύρος των έγκυρων τιμών για τον αντίστοιχο τύπο δεδομένων, τότε οι συναρτήσεις atof, strtol, strtoul, strtod ορίζουν την τιμή της μεταβλητής errno σε ERANGE. Η μεταβλητή errno και η σταθερά ERANGE ορίζονται στο αρχείο κεφαλίδας math.h. Οι συναρτήσεις atof και strtod επιστρέφουν την τιμή HUGE_VAL, η συνάρτηση strtol επιστρέφει την τιμή LONG_MAX ή LONG_MIN και η συνάρτηση strtoul την τιμή ULONG_MAX.

Οι μη τυπικές συναρτήσεις itoa, ltoa, utoa, ecvt, fcvt και gcvt μπορούν να χρησιμοποιηθούν για τη μετατροπή αριθμητικών δεδομένων σε συμβολοσειρές χαρακτήρων. Αλλά είναι καλύτερο να χρησιμοποιήσετε την τυπική συνάρτηση sprintf για αυτούς τους σκοπούς.

1.6. Τυπικές λειτουργίες για εργασία με χορδές.

Αυτή η ενότητα περιγράφει λειτουργίες για εργασία με συμβολοσειρές, τα πρωτότυπα των οποίων περιγράφονται στο αρχείο κεφαλίδας string.h.

1. Σύγκριση χορδών.Οι συναρτήσεις strcmp και strncmp χρησιμοποιούνται για τη σύγκριση συμβολοσειρών.

int strcmp (const char * str1, const char * str2);

συγκρίνει λεξικογραφικά τα str1, str2 και επιστρέφει –1, 0 ή 1 εάν το str1 είναι, αντίστοιχα, μικρότερο, ίσο ή μεγαλύτερο από το str2.

int strncmp (const char * str1, const char * str2, size_t n);

λεξικογραφικά συγκρίνει το πολύ n πρώτους χαρακτήρες από το str1 και το str2. Η συνάρτηση επιστρέφει -1, 0 ή 1 εάν οι πρώτοι n χαρακτήρες από τη συμβολοσειρά str1 είναι αντίστοιχα μικρότεροι από, ίσοι ή μεγαλύτεροι από τους πρώτους n χαρακτήρες από τη συμβολοσειρά str2.

// παράδειγμα σύγκρισης συμβολοσειρών

#περιλαμβάνω

#περιλαμβάνω

char str1 = "aa bb";

char str2 = "aa aa";

char str3 = "aa bb cc";

printf ("% d \ n", strcmp (str1, str3)); // εκτυπώσεις: -1

printf ("% d \ n", strcmp (str1, str1)); // εκτυπώσεις: -0

printf ("% d \ n", strcmp (str1, str2)); // εκτυπώσεις: 1

printf ("% d \ n", strncmp (str1, str3, 5)); // εκτυπώσεις: 0

2. Αντιγραφή γραμμών.Οι συναρτήσεις strcpy και strncpy χρησιμοποιούνται για την αντιγραφή συμβολοσειρών.

char * strcpy (char * str1, const char * str2);

αντιγράφει τη συμβολοσειρά str2 στη συμβολοσειρά str1. Αντιγράφεται ολόκληρη η συμβολοσειρά str2, συμπεριλαμβανομένου του τερματικού null byte. Η συνάρτηση επιστρέφει έναν δείκτη στο str1. Εάν οι γραμμές επικαλύπτονται, το αποτέλεσμα είναι απρόβλεπτο.

char * strncpy (char * str1, const char * str2, size_t n);

αντιγράφει n χαρακτήρες από τη συμβολοσειρά str2 στη συμβολοσειρά str1. Εάν η συμβολοσειρά str2 περιέχει λιγότερους από n χαρακτήρες, τότε το τελευταίο null byte αντιγράφεται όσες φορές χρειάζεται για να επεκταθεί η συμβολοσειρά str2 σε n χαρακτήρες. Η συνάρτηση επιστρέφει έναν δείκτη στη συμβολοσειρά str1.

char str2 = "Αντιγραφή συμβολοσειράς.";

strcpy (str1, str2);

printf (str1); // prints: Αντιγραφή συμβολοσειράς.

4. Συνένωση χορδών.Οι συναρτήσεις strcat και strncat χρησιμοποιούνται για τη συνένωση συμβολοσειρών σε μία συμβολοσειρά.

char * strcat (char * str1, const char * str2);

προσαρτά τη συμβολοσειρά str2 στη συμβολοσειρά str1, με το τερματικό null byte της συμβολοσειράς str1 να έχει διαγραφεί. Η συνάρτηση επιστρέφει έναν δείκτη στη συμβολοσειρά str1.

char * strncat (char * str1, const char * str2, size_t n);

προσθέτει n χαρακτήρες από τη συμβολοσειρά str2 στη συμβολοσειρά str1 και το τερματικό null byte της συμβολοσειράς str1 διαγράφεται. Η συνάρτηση επιστρέφει έναν δείκτη στη συμβολοσειρά str1. εάν το μήκος της συμβολοσειράς str2 είναι μικρότερο από n, τότε προστίθενται μόνο χαρακτήρες που περιλαμβάνονται στη συμβολοσειρά str2. Μετά τη συνένωση συμβολοσειρών, ένα μηδενικό byte προστίθεται πάντα στο str1. Η συνάρτηση επιστρέφει έναν δείκτη στη συμβολοσειρά str1.

#περιλαμβάνω

#περιλαμβάνω

char str1 = "Συμβολοσειρά";

char str2 = "catenation";

char str3 = "Ναι Όχι";

strcat (str1, str2);

printf ("% s \ n", str1); // εκτυπώσεις: Κατενοποίηση συμβολοσειρών

strncat (str1, str3, 3);

printf ("% s \ n", str1); // prints: Κατηγορία συμβολοσειράς Ναι

5. Αναζητήστε έναν χαρακτήρα σε μια συμβολοσειρά.Οι συναρτήσεις strchr, strrchr, strspn, strcspn και strpbrk χρησιμοποιούνται για την αναζήτηση ενός χαρακτήρα σε μια συμβολοσειρά.

char * strchr (const char * str, int c);

αναζητά την πρώτη εμφάνιση του χαρακτήρα που καθορίζεται από την παράμετρο c στη συμβολοσειρά str. Σε περίπτωση επιτυχίας, η συνάρτηση επιστρέφει έναν δείκτη στον πρώτο χαρακτήρα που βρέθηκε και σε περίπτωση αποτυχίας, NULL.

char * strrchr (const char * str, int c);

αναζητά την τελευταία εμφάνιση του χαρακτήρα που καθορίζεται από την παράμετρο c στη συμβολοσειρά str. Εάν είναι επιτυχής, η συνάρτηση επιστρέφει έναν δείκτη στον τελευταίο χαρακτήρα που βρέθηκε και εάν δεν είναι επιτυχής, επιστρέφει NULL.

#περιλαμβάνω

#περιλαμβάνω

char str = "Αναζήτηση χαρακτήρων";

printf ("% s \ n", strchr (str, "r")); // prints: r αναζήτηση

printf ("% s \ n", strrchr (str, "r")); // εκτυπώσεις: rch

size_t strspn (const char * str1, const char * str2);

επιστρέφει το ευρετήριο του πρώτου χαρακτήρα από τη συμβολοσειρά str1 που δεν βρίσκεται στη συμβολοσειρά str2.

size_t strcspn (const char * str1, const char * str2);

επιστρέφει το ευρετήριο του πρώτου χαρακτήρα από τη συμβολοσειρά str1 που πηγαίνει στη συμβολοσειρά str2.

char str = "123 abc";

printf ("n =% d \ n", strspn (str, "321"); // εκτυπώνει: n = 3

printf ("n =% d \ n", strcspn (str, "cba"); // εκτυπώνει: n = 4

char * strpbrk (const char * str1, const char * str2);

βρίσκει τον πρώτο χαρακτήρα στη συμβολοσειρά str1 που είναι ίσος με έναν από τους χαρακτήρες στη συμβολοσειρά str2. Σε περίπτωση επιτυχίας, η συνάρτηση επιστρέφει έναν δείκτη σε αυτόν τον χαρακτήρα και σε περίπτωση αποτυχίας, NULL.

char str = "123 abc";

printf ("% s \ n", strpbrk (str, "bca")); // εκτυπώσεις: abc

6. Σύγκριση χορδών.Η συνάρτηση strstr χρησιμοποιείται για τη σύγκριση συμβολοσειρών.

char * strstr (const char * str1, const char * str2);

βρίσκει την πρώτη εμφάνιση της συμβολοσειράς str2 (χωρίς μηδενικό byte μετάδοσης) στη συμβολοσειρά str1. Σε περίπτωση επιτυχίας, η συνάρτηση επιστρέφει έναν δείκτη στην υποσυμβολοσειρά που βρέθηκε και σε περίπτωση αποτυχίας, NULL. Εάν ο δείκτης str1 δείχνει σε μια συμβολοσειρά μηδενικού μήκους, η συνάρτηση επιστρέφει τον δείκτη str1.

char str = "123 abc 456;

printf ("% s \ n", strstr (str, "abc"); // εκτύπωση: abc 456

7. Ανάλυση της συμβολοσειράς σε μάρκες.Η συνάρτηση strtok χρησιμοποιείται για την ανάλυση μιας συμβολοσειράς σε διακριτικά.

char * strtok (char * str1, const char * str2);

επιστρέφει έναν δείκτη στο επόμενο διακριτικό (λέξη) στη συμβολοσειρά str1, στην οποία τα διακριτικά οριοθετούνται από χαρακτήρες από τη συμβολοσειρά str2. Εάν τα lexemes έχουν τελειώσει, η συνάρτηση επιστρέφει NULL. Στην πρώτη κλήση στη συνάρτηση strtok, η παράμετρος str1 πρέπει να δείχνει σε μια συμβολοσειρά που αναλύεται σε διακριτικά και σε επόμενες κλήσεις, αυτή η παράμετρος πρέπει να οριστεί σε NULL. Μετά την εύρεση του διακριτικού, η συνάρτηση strtok γράφει ένα μηδενικό byte μετά από αυτό το διακριτικό στη θέση του διαχωριστή.

#περιλαμβάνω

#περιλαμβάνω

char str = "12 34 ab cd";

p = strtok (str, "");

printf ("% s \ n", p); // εκτυπώνει σε στήλη τις τιμές: 12 34 ab cd

p = strtok (NULL, "");

8. Προσδιορισμός του μήκους της χορδής.Η συνάρτηση strlen χρησιμοποιείται για τον προσδιορισμό του μήκους μιας συμβολοσειράς.

size_t strlen (const char * str);

επιστρέφει το μήκος της συμβολοσειράς, εξαιρουμένου του τελευταίου μηδενικού byte. Για παράδειγμα,

char str = "123";

printf ("len =% d \ n", strlen (str)); // εκτυπώσεις: len = 3

1.7. Λειτουργίες για εργασία με μνήμη.

Το αρχείο κεφαλίδας string.h περιγράφει επίσης συναρτήσεις για εργασία με μπλοκ μνήμης, οι οποίες είναι παρόμοιες με τις αντίστοιχες συναρτήσεις για εργασία με συμβολοσειρές.

void * memchr (const void * str, int c, size_t n);

αναζητά την πρώτη εμφάνιση του χαρακτήρα που καθορίζεται από την παράμετρο c σε n byte του str.

int memcmp (const void * str1, const void * str2, size_t n);

συγκρίνει τα πρώτα n byte του str1 και του str2.

void * memcpy (const void * str1, const void * str2, size_t n);

αντιγράφει τα πρώτα n byte από τη συμβολοσειρά str1 στη συμβολοσειρά str2.

void * memmove (const void * str1, const void * str2, size_t n);

αντιγράφει τα πρώτα n byte από τη συμβολοσειρά str1 στη συμβολοσειρά str2, διασφαλίζοντας ότι οι επικαλυπτόμενες συμβολοσειρές αντιμετωπίζονται σωστά.

void * memset (const void * str, int c, size_t n);

αντιγράφει τον χαρακτήρα που καθορίζεται από την παράμετρο c στα πρώτα n byte του str.

Αναστείλετε το AdBlock σε αυτόν τον ιστότοπο.

Έτσι, χορδές σε C. Δεν υπάρχει ξεχωριστός τύπος δεδομένων για αυτά, όπως γίνεται σε πολλές άλλες γλώσσες προγραμματισμού. Στο C, μια συμβολοσειρά είναι ένας πίνακας χαρακτήρων. Για να επισημάνετε το τέλος μιας γραμμής, χρησιμοποιείται ο χαρακτήρας "\ 0", για τον οποίο μιλήσαμε στο τελευταίο μέρος αυτού του μαθήματος. Δεν εμφανίζεται στην οθόνη με κανέναν τρόπο, επομένως δεν θα μπορείτε να το δείτε.

Δημιουργία και αρχικοποίηση συμβολοσειράς

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

Ο παρακάτω κώδικας απεικονίζει διάφορους τρόπους προετοιμασίας συμβολοσειρών.

Λίστα 1.

Char str; char str1 = ("Y", "o", "n", "g", "C", "o", "d", "e", "r", "\ 0"); char str2 = "Γεια σου!"; char str3 = "Γεια σου!";

Εικ. 1 Δήλωση και αρχικοποίηση συμβολοσειρών

Στην πρώτη γραμμή, απλώς δηλώνουμε έναν πίνακα δέκα χαρακτήρων. Δεν είναι καν αρκετή χορδή, αφού δεν έχει τον μηδενικό χαρακτήρα \ 0 εφόσον είναι απλώς ένα σύνολο χαρακτήρων.

Δεύτερη γραμμή. Ο πιο απλός τρόποςαρχικοποίηση στο μέτωπο. Δηλώνουμε κάθε χαρακτήρα ξεχωριστά. Το κύριο πράγμα εδώ είναι να μην ξεχάσετε να προσθέσετε τον μηδενικό χαρακτήρα \ 0.

Η τρίτη γραμμή είναι ανάλογη με τη δεύτερη γραμμή. Δώστε προσοχή στην εικόνα. Επειδή υπάρχουν λιγότεροι χαρακτήρες στη συμβολοσειρά στα δεξιά από τα στοιχεία του πίνακα, τα υπόλοιπα στοιχεία θα γεμίσουν με \ 0.

Τέταρτη γραμμή. Όπως μπορείτε να δείτε, δεν προσδιορίζεται μέγεθος εδώ. Το πρόγραμμα θα το υπολογίσει αυτόματα και θα δημιουργήσει μια σειρά χαρακτήρων του απαιτούμενου μήκους. Αυτό θα εισαγάγει τον μηδενικό χαρακτήρα \ 0 τελευταίο.

Πώς να βγάζετε μια συμβολοσειρά

Ας προσθέσουμε τον παραπάνω κώδικα σε ένα πλήρες πρόγραμμα που θα εμφανίζει τις δημιουργημένες γραμμές στην οθόνη.

Λίστα 2.

#περιλαμβάνω int main (void) (char str; char str1 = ("Y", "o", "n", "g", "C", "o", "d", "e", "r", " \ 0 "); char str2 =" Γεια σου! "; Char str3 =" Γεια σου! "; Για (int i = 0; i< 10; i = i + 1) printf("%c\t",str[i]); printf("\n"); puts(str1); printf("%s\n",str2); puts(str3); return 0; }


Εικ. 2 Διαφορετικοί τρόποι εμφάνισης μιας συμβολοσειράς στην οθόνη

Όπως μπορείτε να δείτε, υπάρχουν αρκετοί βασικοί τρόποι εμφάνισης μιας συμβολοσειράς στην οθόνη.

  • χρησιμοποιήστε τη συνάρτηση printf με προσδιοριστή% s
  • χρήση βάζει συνάρτηση
  • χρησιμοποιήστε τη συνάρτηση fputs, προσδιορίζοντας το stdout ως δεύτερη παράμετρο.

Η μόνη προειδοποίηση με τις συναρτήσεις puts και fputs. Σημειώστε ότι η συνάρτηση puts τυλίγει την έξοδο στην επόμενη γραμμή, αλλά η συνάρτηση fputs όχι.

Όπως μπορείτε να δείτε, το συμπέρασμα είναι αρκετά απλό.

Συμβολοσειρές εισαγωγής

Η εισαγωγή συμβολοσειρών είναι λίγο πιο περίπλοκη από την έξοδο. Ο απλούστερος τρόπος θα ήταν ο εξής:

Λίστα 3.

#περιλαμβάνω int main (void) (char str; gets (str); puts (str); return 0;)

Η συνάρτηση gets διακόπτει το πρόγραμμα, διαβάζει μια συμβολοσειρά χαρακτήρων που εισάγονται από το πληκτρολόγιο και την τοποθετεί σε έναν πίνακα χαρακτήρων, το όνομα του οποίου μεταβιβάζεται στη συνάρτηση ως παράμετρος.
Η ολοκλήρωση της συνάρτησης gets θα είναι ο χαρακτήρας που αντιστοιχεί στο πλήκτρο enter και θα γράφεται στη συμβολοσειρά ως μηδενικός χαρακτήρας.
Έχετε παρατηρήσει τον κίνδυνο; Εάν όχι, ο μεταγλωττιστής θα σας προειδοποιήσει ευγενικά για αυτό. Το θέμα είναι ότι η λειτουργία gets εξέρχεται μόνο όταν ο χρήστης πατήσει το πλήκτρο enter. Αυτό είναι γεμάτο με το γεγονός ότι μπορούμε να προχωρήσουμε πέρα ​​από τον πίνακα, στην περίπτωσή μας - εάν έχουν εισαχθεί περισσότεροι από 20 χαρακτήρες.
Παρεμπιπτόντως, τα σφάλματα υπερχείλισης buffer θεωρούνταν προηγουμένως ο πιο συνηθισμένος τύπος ευπάθειας. Βρίσκονται ακόμα σήμερα, αλλά έχει γίνει πολύ πιο δύσκολο να χρησιμοποιηθούν για να χακάρουν προγράμματα.

Τι έχουμε λοιπόν. Έχουμε ένα καθήκον: να γράψουμε μια συμβολοσειρά σε έναν πίνακα περιορισμένου μεγέθους. Δηλαδή, πρέπει με κάποιο τρόπο να ελέγχουμε τον αριθμό των χαρακτήρων που εισάγει ο χρήστης. Εδώ έρχεται να μας σώσει η συνάρτηση fgets:

Λίστα 4.

#περιλαμβάνω int main (void) (char str; fgets (str, 10, stdin); puts (str); return 0;)

Η συνάρτηση fgets παίρνει τρία ορίσματα ως είσοδο: μια μεταβλητή για να γράψει τη συμβολοσειρά, το μέγεθος της συμβολοσειράς που θα γράψει και το όνομα της ροής από όπου θα ληφθούν τα δεδομένα για εγγραφή στη συμβολοσειρά, σε αυτήν την περίπτωση, το stdin. Όπως γνωρίζετε ήδη από το Μάθημα 3, το stdin είναι τυπική είσοδος, που συνήθως σχετίζεται με ένα πληκτρολόγιο. Δεν είναι καθόλου απαραίτητο τα δεδομένα να προέρχονται από τη ροή stdin· στο μέλλον, θα χρησιμοποιούμε επίσης αυτή τη λειτουργία για την ανάγνωση δεδομένων από αρχεία.

Εάν κατά την εκτέλεση αυτού του προγράμματος εισάγουμε μια συμβολοσειρά μεγαλύτερη από 10 χαρακτήρες, μόνο 9 χαρακτήρες από την αρχή και μια αλλαγή γραμμής θα εξακολουθεί να γράφεται στον πίνακα, τα fgets θα «κόψουν» τη συμβολοσειρά στο απαιτούμενο μήκος.

Σημειώστε ότι το fgets δεν διαβάζει 10 χαρακτήρες, αλλά 9! Όπως θυμόμαστε, στις συμβολοσειρές, ο τελευταίος χαρακτήρας δεσμεύεται για έναν μηδενικό χαρακτήρα.

Ας το ελέγξουμε. Ας ξεκινήσουμε το πρόγραμμα από την τελευταία λίστα. Και εισάγετε τη γραμμή 1234567890. Στην οθόνη εμφανίζεται η συμβολοσειρά 123456789.


Εικ. 3 Ένα παράδειγμα του τρόπου λειτουργίας της συνάρτησης fgets

Γεννιέται το ερώτημα. Πού πήγε ο δέκατος χαρακτήρας; Και θα απαντήσω. Δεν έχει πάει πουθενά, έχει παραμείνει στη ροή εισόδου. Εκτελέστε το παρακάτω πρόγραμμα.

Λίστα 5.

#περιλαμβάνω int main (void) (char str; fgets (str, 10, stdin); puts (str); int h = 99; printf ("do% d \ n", h); scanf ("% d", & h ) ; printf ("posle% d \ n", h); return 0;)

Ιδού το αποτέλεσμα της δουλειάς της.


Εικόνα 4 Μη κενή buffer stdin

Επιτρέψτε μου να εξηγήσω τι συνέβη. Καλέσαμε τη συνάρτηση fgets. Άνοιξε μια ροή εισόδου και περίμενε να εισάγουμε δεδομένα. Εισαγάγαμε 1234567890 από το πληκτρολόγιο \ n (\ n εννοώ πατώντας το πλήκτρο Enter). Αυτό πήγε στη ροή εισόδου stdin. Η συνάρτηση fgets, όπως αναμενόταν, πήρε τους πρώτους 9 χαρακτήρες 123456789 από τη ροή εισόδου, πρόσθεσε έναν μηδενικό χαρακτήρα \ 0 σε αυτούς και τον έγραψε στη συμβολοσειρά. Απομένουν ακόμη 0 \ n στη ροή εισόδου.

Στη συνέχεια, δηλώνουμε τη μεταβλητή h. Εμφανίζουμε την αξία του στην οθόνη. Στη συνέχεια καλούμε τη συνάρτηση scanf. Εδώ είναι που αναμένεται ότι μπορούμε να μπούμε κάτι, αλλά αφού Το 0 \ n κολλάει στη ροή εισόδου, τότε η συνάρτηση scanf το αντιλαμβάνεται ως είσοδο μας και το 0 γράφεται στη μεταβλητή h. Στη συνέχεια, το εμφανίζουμε στην οθόνη.

Αυτή, φυσικά, δεν είναι ακριβώς η συμπεριφορά που περιμένουμε. Για να αντιμετωπίσετε αυτό το πρόβλημα, είναι απαραίτητο να διαγράψετε το buffer εισόδου αφού διαβάσουμε μια γραμμή που έχει εισαχθεί από τον χρήστη από αυτό. Για αυτό χρησιμοποιείται η ειδική λειτουργία flush. Έχει μόνο μία παράμετρο - το ρεύμα που πρέπει να καθαριστεί.

Ας διορθώσουμε το τελευταίο παράδειγμα έτσι ώστε να λειτουργεί προβλέψιμα.

Λίστα 6.

#περιλαμβάνω int main (void) (char str; fgets (str, 10, stdin); flush (stdin); // διαγραφή της ροής εισόδου puts (str); int h = 99; printf ("do% d \ n", h ) ; scanf ("% d", & h); printf ("posle% d \ n", h); επιστροφή 0;)

Το πρόγραμμα θα λειτουργεί πλέον όπως αναμένεται.


Εικ. 4 Ξεπλύνετε το buffer stdin με flush

Συνοψίζοντας, μπορούν να σημειωθούν δύο γεγονότα. Πρώτα. Δεν είναι ασφαλές να χρησιμοποιήσετε τη συνάρτηση gets αυτή τη στιγμή, επομένως συνιστάται να χρησιμοποιείτε τη συνάρτηση fgets παντού.

Δεύτερος. Θυμηθείτε να ξεπλύνετε το buffer εισόδου εάν χρησιμοποιείτε τη συνάρτηση fgets.

Αυτό ολοκληρώνει τη συζήτηση σχετικά με την εισαγωγή χορδών. Προχώρα.

n »Η αξιόπιστη εταιρεία SEO Η Ινδία μπορεί να αυξήσει τα έσοδα των μικρών επιχειρήσεων

Το 80% των χρηστών αναζητούν στο Google και σε άλλες μηχανές αναζήτησης πριν κάνουν μια αγορά και πάνω από το 50% των ερωτημάτων που δημιουργούνται μέσω των μηχανών αναζήτησης μετατρέπονται. Αυτά τα δύο στατιστικά στοιχεία αποδεικνύουν τη σημασία του Search Engine Optimization. Υπάρχουν πολλά τέτοια στατιστικά και γεγονότα που κάνουν ένα ξεκάθαρο σημείο: κάθε επιχείρηση μικρής, μεσαίας ή μεγάλης κλίμακας χρειάζεται επαγγελματικές υπηρεσίες SEO. Οι μικρές επιχειρήσεις και οι νεοσύστατες επιχειρήσεις αντιμετωπίζουν συχνά προβλήματα προϋπολογισμού. Μπορούν να λάβουν βοήθεια από οποιοδήποτε αξιόπιστο πρακτορείο SEO από την Ινδία για να λάβουν την καλύτερη υπηρεσία SEO στον προϋπολογισμό τους για να αυξήσουν τα έσοδά τους.
Η αναζήτηση έχει μεγάλη επίδραση στο μυαλό των καταναλωτών. Σύμφωνα με τα διάφορα στατιστικά στοιχεία που μοιράζονται σημαντικοί ειδικοί στη βελτιστοποίηση μηχανών αναζήτησης σε διάφορους εξουσιοδοτημένους ιστότοπους όπως Search Engine Land, Moz, SEO Journal, Digital Marketers India, Hubspot κ.λπ. Το SEO συλλαμβάνει την πλειοψηφία των πελατών. Επίσης, οι δυνητικοί πελάτες που προέρχονται από τα οργανικά αποτελέσματα αναζήτησης έχουν υψηλότερο ποσοστό μετατροπών. Αυτά τα στατιστικά στοιχεία και η συμπεριφορά των καταναλωτών καθιστούν σαφέστερο το γεγονός ότι η καλύτερη υπηρεσία SEO δεν είναι πολυτέλεια, αλλά αναγκαιότητα για κάθε επιχείρηση.
Για να παρακάμψει τον ανταγωνισμό και να αυξήσει την επιχειρηματική ανάπτυξη, κάθε οργανισμός πρέπει να χρησιμοποιεί τις υπηρεσίες βελτιστοποίησης μηχανών αναζήτησης. Οι μεγάλες μάρκες μπορούν να επενδύσουν αρκετά χρήματα για την εξειδικευμένη υπηρεσία SEO που προσφέρει μια κορυφαία εταιρεία SEO ή ένας ειδικός SEO, αλλά οι ιδιοκτήτες μικρών επιχειρήσεων συχνά συμβιβάζονται με την ποιότητα αυτής της υπηρεσίας λόγω μικρότερου προϋπολογισμού. Είναι δύσκολο γεγονός ότι οι μικρές επιχειρήσεις και οι νεοσύστατες επιχειρήσεις καταλήγουν να αφήνουν τις ευκαιρίες που μπορούν να δημιουργηθούν με την επαγγελματική υπηρεσία SEO ή να χρησιμοποιούν μια φθηνή υπηρεσία SEO που δεν αποφέρει θετικά αποτελέσματα.
Οι ιδιοκτήτες μικρών επιχειρήσεων και οι νεοσύστατες επιχειρήσεις μπορούν να επωφεληθούν από επαγγελματικές υπηρεσίες SEO ακόμη και στον περιορισμένο προϋπολογισμό. Η καλύτερη λύση είναι η εύρεση μιας αξιόπιστης εταιρείας SEO με έδρα την Ινδία. Στην Ινδία, υπάρχουν πολλοί ειδικοί SEO που συνεργάζονται με την εταιρεία ψηφιακού μάρκετινγκ και προσφέρουν τις καλύτερες υπηρεσίες στον κλάδο. Μπορούν να σας παρέχουν τις απαιτούμενες υπηρεσίες SEO στον προϋπολογισμό σας. Οι μισθοί μπορούν να αποτελέσουν αντικείμενο διαπραγμάτευσης με ένα πρακτορείο SEO στην Ινδία για να λάβετε καλύτερες υπηρεσίες σε χαμηλότερες τιμές. Ωστόσο, μην πέφτετε σε φθηνή υπηρεσία SEO που χρεώνει λιγότερο και υπόσχεστε να προσφέρετε περισσότερα καθώς η τεχνογνωσία έχει το δικό της κόστος. Πρέπει να δείτε το χαρτοφυλάκιο ή να κάνετε τις κατάλληλες ερωτήσεις προτού συνάψετε σύμβαση με μια εταιρεία για την επιχείρησή σας.
Οι ειδικοί SEO στην Ινδία είναι ειδικευμένοι στις βέλτιστες πρακτικές βελτιστοποίησης μηχανών αναζήτησης. Επίσης, υπάρχουν ορισμένοι ειδικοί SEO στην Ινδία, όπως ο Ash Vyas, οι οποίοι ειδικεύονται στη δημιουργία της καλύτερης στρατηγικής βελτιστοποίησης μηχανών αναζήτησης για μια επιχείρηση με δηλωμένο προϋπολογισμό. Οι επαγγελματίες SEO θα δημιουργήσουν ένα σαφές σχέδιο και θα μοιραστούν επίσης ποια μπορεί να είναι τα αναμενόμενα αποτελέσματα. Με αυτόν τον τρόπο μπορείτε να γνωρίζετε καλά την επένδυση και τις αποδόσεις σας. Αυτό βοηθά στη λήψη μιας καλύτερης επιχειρηματικής απόφασης.
Μια καλή ιδέα είναι να βρείτε και να συνάψετε σύμβαση με μια αξιόπιστη εταιρεία SEO από την Ινδία που προσφέρει τις καλύτερες υπηρεσίες SEO το συντομότερο δυνατό. Μπορείτε επίσης να ξεκινήσετε με μικρό προϋπολογισμό και περιορισμένες δραστηριότητες για να αρχίσετε να ευρετηριάζετε τις ιστοσελίδες σας και να ενισχύετε τις λέξεις-κλειδιά σας στις μηχανές αναζήτησης. Μην περιμένετε την τέλεια στιγμή ή μια μέρα που θα έχετε χιλιάδες δολάρια για να επενδύσετε στις καλύτερες υπηρεσίες SEO. Το να ξεκινήσετε νωρίς θα σας βοηθήσει να έχετε ταχύτερα αποτελέσματα όταν μπορείτε να προχωρήσετε επιθετικά με την προσέγγιση μάρκετινγκ. Μια αξιόπιστη εταιρεία SEO με έδρα την Ινδία θα σας βοηθήσει να καθορίσετε τα τρέχοντα και μελλοντικά σας σχέδια για να αποφέρετε καλά αποτελέσματα. Οι περισσότερες ευρετηριασμένες σελίδες ενίσχυσαν τις κατατάξεις και η αξιόπιστη επωνυμία της επιχείρησής σας που δημιουργήθηκαν με συνεχείς επαγγελματικές πρακτικές SEO θα διπλασιάσουν τα ερωτήματα, τις επιχειρήσεις και τα έσοδα. Κάθε μικρή επιχείρηση μπορεί να ξεκινήσει με διψήφια επένδυση στις επαγγελματικές υπηρεσίες SEO. Υπάρχουν πολλές εταιρείες SEO στην Ινδία που προσφέρουν χαμηλό προϋπολογισμό, αλλά προκύπτουν από προσανατολισμένες υπηρεσίες βελτιστοποίησης μηχανών αναζήτησης.

έρευνες από την εξορία

  • CraigWew

    12.04.2018

    п »їΗ σημασία της δημιουργίας σχέσης με τον πελάτη σε ακίνητα και γενικές πωλήσεις

    Η σημασία της δημιουργίας σχέσης με τον πελάτη.
    Η δημιουργία σχέσης με έναν πελάτη πρέπει να κερδίζεται και πρέπει να προσεγγίζεται ως πολύ αναπόσπαστο μέρος της διαδικασίας πωλήσεων.
    Για να κάνετε έναν πελάτη και τον εαυτό σας να σχετιστούν σε μια πραγματική βάση ένα προς ένα, περιλαμβάνει δύο πράγματα!
    Πρώτα, θα πρέπει να είστε ενήμεροι και να είστε εκεί! Δεύτερον, πρέπει να καταλάβετε ότι υπάρχουν δύο διαφορετικά στάδια που θα προκύψουν κατά τη διάρκεια αυτής της διαδικασίας.
    Α-Να είσαι εκεί-τι σημαίνει αυτό;
    o Οι περισσότεροι άνθρωποι δεν ακούν πραγματικά ένα άλλο άτομο καθώς μιλάει. Γενικά είναι τόσο απασχολημένοι με τη διατύπωση της επόμενης απάντησης ή δήλωσής τους που δεν μπορούσαν να ακούσουν πραγματικά.
    o Αν σας ακούγεται, το να είστε εκεί σημαίνει να σκάσετε και να ακούσετε!
    Β-Ποιο είναι το πρώτο ή το αρχικό στάδιο;
    o Γενικά έχετε μόνο λίγα λεπτά για να καθιερωθείτε στο μυαλό των πελατών ως κάποιος με τον οποίο θέλουν να συνεννοηθούν.
    o Όταν έχετε αμφιβολίες, είναι καλύτερο να κάνετε πρώτα ερωτήσεις που θα τους τραβήξουν έξω και θα μιλήσουν για τον εαυτό τους.
    o Είναι επίσης πάντα ασφαλές να εμφανίζεσαι ως επαγγελματίας - δεν εννοώ στωικός ή στεγνός, αλλά κάποιος που ξέρει τι κάνουν και μιλάει και κοιτάζει το μέρος.
    Γ-Άλλα στάδια
    o Όσο περνά ο καιρός, μέσα από τη συζήτηση και τις ερωτήσεις που θα έχουν, είτε θα εδραιώσετε την ικανότητά σας είτε όχι.
    o Να γνωρίζετε ότι πιθανότατα θα σας μετρούν για λίγο. Τα καλά νέα είναι ότι κάποια στιγμή, εάν έχετε πετύχει να δημιουργήσετε σχέσεις, θα χαλαρώσουν και μπορείτε και οι δύο να συγκεντρωθείτε στην εύρεση ή την πώληση του σπιτιού.
    Τι άλλο μπορεί να με βοηθήσει να αναπτύξω σχέσεις;
    o Προσπαθώντας να κατανοήσετε διαφορετικούς τύπους προσωπικότητας και στη συνέχεια λέγοντας και κάνοντας τις σωστές ερωτήσεις.
    o Εάν έχετε καλή σχέση (να έχετε το ίδιο μήκος κύματος με τον πελάτη), τότε η πώληση έχει ουσιαστικά τελειώσει, τώρα είναι απλώς θέμα εύρεσης του κατάλληλου σπιτιού ή συμπλήρωσης των εγγράφων καταχώρισης.
    Τι γίνεται με τις διαφορετικές προσωπικότητες
    o Δεδομένου ότι αυτό δεν είναι ένα βιβλίο για την ψυχιατρική, προς το παρόν κατανοήστε δύο βασικούς τύπους.
    o Υπάρχουν εσωστρεφείς και εξωστρεφείς άνθρωποι.
    o Γνωρίζετε τον τύπο. Σκεφτείτε τρία άτομα που γνωρίζετε ότι ταιριάζουν σε κάθε κατηγορία.
    Τι γίνεται με τη γλώσσα του σώματος και τα πρότυπα ομιλίας;
    o Εάν μιλούν γρήγορα ή αργά, προσπαθήστε να μιμηθείτε τα μοτίβα ομιλίας τους.
    o Εάν μιλάνε δυνατά ή απαλά, κάντε το ίδιο. Γέρνουν προς τα εμπρός ή προς τα πίσω;
    o Περιττό να πούμε ότι υπάρχουν πολλά βιβλία γραμμένα για αυτό το θέμα. Απλώς να γνωρίζετε ότι είναι ένας σημαντικός παράγοντας - ειδικά όταν κάθεστε σε μια αίθουσα συνεδριάσεων ή στο σπίτι κάποιου και συζητάτε μια συμφωνία 400.000 $.
    Η ανάπτυξη σχέσεων είναι μια δεξιότητα που μπορεί να μάθει και να βελτιωθεί.
    o Όλοι έχουμε βιώσει έναν πωλητή που μας πούλησε κάτι και όμως δεν νιώθαμε ότι μας πουλούσαν. Ο λόγος είναι αυτός ή αυτή, σε έκανε να νιώσεις άνετα εκεί που τους εμπιστεύτηκες.
    Πώς αναπτύσσουμε τη σχέση;
    o Χρησιμοποιήστε τα μάτια και τα αυτιά σας και κάντε ερωτήσεις. Για να εξηγήσει
    o Χρησιμοποιήστε τα μάτια:
    o Κοιτάξτε το φόρεμά τους-το αυτοκίνητό τους-τα προσωπικά τους υπάρχοντα και εννοώ να τα κοιτάξετε και να αποκρυπτογραφήσετε τι σας λέει αυτό για αυτούς.
    o Χρησιμοποιήστε τα αυτιά:
    o Ακούστε τι λένε και κάντε ερωτήσεις για να καταλήξετε στο πραγματικό τους ΚΙΝΗΤΡΟ!
    Τώρα κατά τη διάρκεια όλης αυτής της συνομιλίας, πιθανότατα θα υπάρχουν ένα ή δύο πράγματα που θα ανακαλύψετε ότι έχετε κοινά μαζί τους. (Οικογένεια, γεωγραφικές περιοχές, ψάρεμα κ.λπ.) Όταν συναντήσετε κοινά σημεία, ενημερώστε τους ότι είστε εξοικειωμένοι και μετά αφιερώστε ένα λεπτό για να το συζητήσετε μαζί τους.
    Ποιος είναι ο Στόχος;
    o Μόλις σας δεχτούν ως έναν από αυτούς, είστε σε θέση να έχετε πραγματικά μια εξαιρετική εμπειρία στις εκπτώσεις καθώς τώρα εργάζεστε μαζί και μετά ως ομάδα — δεν είστε πλέον ο πωλητής που βρίσκεστε τώρα σε συμβουλευτική θέση ...
    o Να θυμάστε, ο πελάτης είτε θα σας επιτρέψει είτε όχι να εισέλθετε στον κόσμο του. Εάν το καταλαβαίνετε αυτό και εργάζεστε πραγματικά σκληρά για να γίνετε συμπονετικοί μαζί του/της, μπορείτε να κερδίσετε μια θέση εμπιστοσύνης. Στις περισσότερες περιπτώσεις, θα τους δείτε πραγματικά να χαλαρώνουν (γλώσσα του σώματος) όταν αυτό συμβεί όταν είστε καθ' οδόν.
    o Για να το καταδείξετε αυτό, έχετε κάνει ποτέ μια ομιλία και έχετε παρατηρήσει ότι καθώς τελικά συνδέεστε με ένα μέλος του ακροατηρίου, θα κουνήσει καταφατικά το κεφάλι. Αυτά τα πράγματα μπορεί να φαίνονται τετριμμένα, αλλά δεν είναι.
    Κλείνοντας, εάν μπορείτε να κερδίσετε την εμπιστοσύνη των πελατών, η πώληση ενός προϊόντος ή μιας υπηρεσίας είναι πολύ πιο εύκολη και η εμπειρία μπορεί να είναι απολαυστική για όλους τους εμπλεκόμενους.
    Να θυμάστε πάντα ότι ένα Win / Win είναι η καλύτερη κατάσταση.

Habra, γεια!

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

Η συζήτηση για τον προγραμματισμό Linux έφτασε σιγά-σιγά στο σημείο όπου αυτός ο άνθρωπος υποστήριξε ότι η πολυπλοκότητα του προγραμματισμού συστημάτων ήταν στην πραγματικότητα υπερβολικά υπερβολική. Ότι η γλώσσα C είναι τόσο απλή όσο ένα ταίριασμα, στην πραγματικότητα, όπως ο πυρήνας του Linux (κατά τα λόγια του).

Είχα μαζί μου έναν φορητό υπολογιστή Linux με ένα σύνολο εργαλείων ανάπτυξης C για κυρίους (gcc, vim, make, valgrind, gdb). Δεν θυμάμαι πλέον ποιος στόχος θέσαμε τότε, αλλά μετά από λίγα λεπτά ο αντίπαλός μου βρέθηκε πίσω από αυτό το laptop, εντελώς έτοιμος να λύσει το πρόβλημα.

Και κυριολεκτικά στις πρώτες κιόλας γραμμές, έκανε ένα σοβαρό λάθος όταν διέθεσε μνήμη για ... μια γραμμή.

Char * str = (char *) malloc (sizeof (char) * strlen (buffer));
Το buffer είναι μια μεταβλητή στοίβας στην οποία εγγράφηκαν δεδομένα από το πληκτρολόγιο.

Νομίζω ότι σίγουρα θα υπάρχουν άνθρωποι που θα ρωτήσουν: "Μπορεί κάτι να μην πάει καλά εδώ;"
Πιστέψτε με, μπορεί.

Και τι ακριβώς - διαβάστε στην περικοπή.

Μια μικρή θεωρία - ένα είδος FaceBez.

Εάν γνωρίζετε, κάντε κύλιση στην επόμενη κεφαλίδα.

Μια συμβολοσειρά στο C είναι ένας πίνακας χαρακτήρων, ο οποίος με φιλικό τρόπο πρέπει πάντα να τελειώνει με "\ 0" - τον χαρακτήρα τέλους γραμμής. Οι συμβολοσειρές στη στοίβα (στατικές) δηλώνονται ως εξής:

Char str [n] = (0);
n είναι το μέγεθος του πίνακα χαρακτήρων, το ίδιο με το μήκος της συμβολοσειράς.

Εκχώρηση (0) - "μηδενισμός" της συμβολοσειράς (προαιρετικό, μπορείτε να το δηλώσετε χωρίς αυτό). Το αποτέλεσμα είναι το ίδιο με τις συναρτήσεις memset (str, 0, sizeof (str)) και bzero (str, sizeof (str)). Χρησιμοποιείται για την πρόληψη των σκουπιδιών σε μη αρχικοποιημένες μεταβλητές.

Επίσης στη στοίβα, μπορείτε να αρχικοποιήσετε αμέσως τη γραμμή:

Char buf = "προεπιλεγμένο κείμενο buffer \ n";
Επιπλέον, μια συμβολοσειρά μπορεί να δηλωθεί ως δείκτης και να εκχωρηθεί μνήμη στο σωρό για αυτήν:

Char * str = malloc (μέγεθος);
μέγεθος - ο αριθμός των byte που διαθέτουμε για τη συμβολοσειρά. Τέτοιες συμβολοσειρές ονομάζονται δυναμικές (λόγω του γεγονότος ότι το απαιτούμενο μέγεθος υπολογίζεται δυναμικά + το εκχωρημένο μέγεθος μνήμης μπορεί να αυξηθεί ανά πάσα στιγμή χρησιμοποιώντας τη συνάρτηση realloc ()).

Στην περίπτωση μιας μεταβλητής στοίβας, χρησιμοποίησα τον συμβολισμό n για να προσδιορίσω το μέγεθος του πίνακα· στην περίπτωση μιας μεταβλητής στο σωρό, χρησιμοποίησα το μέγεθος συμβολισμού. Και αυτό αντικατοπτρίζει τέλεια την πραγματική ουσία της διαφοράς μεταξύ μιας δήλωσης στη στοίβα και μιας δήλωσης με εκχώρηση μνήμης στο σωρό, επειδή το n χρησιμοποιείται συνήθως όταν μιλάμε για τον αριθμό των στοιχείων. Και το μέγεθος είναι μια εντελώς διαφορετική ιστορία...

Ο Valgrind θα μας βοηθήσει

Στο προηγούμενο άρθρο μου το ανέφερα και εγώ. Valgrind (, δύο - μικρό πώς-να) - πολύ χρήσιμο πρόγραμμαπου βοηθά τον προγραμματιστή να εντοπίσει τις διαρροές μνήμης και τα σφάλματα περιβάλλοντος - αυτά είναι τα πράγματα που εμφανίζονται πιο συχνά όταν εργάζεστε με συμβολοσειρές.

Ας δούμε μια μικρή λίστα, η οποία υλοποιεί κάτι παρόμοιο με το πρόγραμμα που ανέφερα, και ας το εκτελέσουμε μέσω του valgrind:

#περιλαμβάνω #περιλαμβάνω #περιλαμβάνω #define HELLO_STRING "Γεια σου, Habr! \ n" void main () (char * str = malloc (sizeof (char) * strlen (HELLO_STRING)); strcpy (str, HELLO_STRING); printf ("-> \ t% s" , str); δωρεάν (str);)
Και μάλιστα το αποτέλεσμα του προγράμματος:

$ gcc main.c $ ./a.out -> Γεια σου, Χαμπρ!
Τίποτα ασυνήθιστο μέχρι στιγμής. Τώρα ας τρέξουμε αυτό το πρόγραμμα με το valgrind!

$ valgrind --tool = memcheck ./a.out == 3892 == Memcheck, ένας ανιχνευτής σφαλμάτων μνήμης == 3892 == Πνευματικά δικαιώματα (C) 2002-2015 και GNU GPL "d, από Julian Seward et al. == 3892 == Χρήση Valgrind-3.12.0 και LibVEX, επανάληψη με -h για πληροφορίες πνευματικών δικαιωμάτων == 3892 == Εντολή: ./a.out == 3892 == == 3892 == Μη έγκυρη εγγραφή μεγέθους 2 == 3892 = = στο 0x4005B4: main (στο /home/indever/prg/C/public/a.out) == 3892 == Η διεύθυνση 0x520004c είναι 12 byte μέσα σε ένα μπλοκ μεγέθους 13 alloc "d == 3892 == στο 0x4C2DB9D: malloc (vg_replace_malloc.c: 299) == 3892 == κατά 0x400597: κύρια (στο /home/indever/prg/C/public/a.out) == 3892 == == 3892 == Μη έγκυρη ανάγνωση μεγέθους 1 == 3892 == σε 0x4C30BC4: strlen (vg_replace_strmem.c: 454) == 3892 == κατά 0x4E89AD0: vfprintf (σε /usr/lib64/libc-2.24.so) == 3892 == εκτύπωση κατά 0x4E89AD0 lib64 / libc-2.24.so) == 3892 == κατά 0x4005CF: κύρια (στο /home/indever/prg/C/public/a.out) == 3892 == Η διεύθυνση 0x520004d είναι 0 byte μετά από ένα μπλοκ μεγέθους 13 alloc "d == 3892 == στο 0x4C2DB9D: malloc (vg_replace_malloc.c: 299) == 3892 == κατά 0x400597: κύρια (in / home / indever / prg / C / public / a.out) == 3892 == -> Γεια σου, Habr! == 3892 == == 3892 == ΠΕΡΙΛΗΨΗ ΣΩΡΟΥ: == 3892 == σε χρήση κατά την έξοδο: 0 byte σε 0 μπλοκ == 3892 == συνολική χρήση σωρού: 2 εκχωρήσεις, 2 ελεύθερες, 1.037 byte εκχωρημένες == 3892 = = == 3892 == Όλα τα μπλοκ σωρού απελευθερώθηκαν - δεν είναι δυνατές διαρροές == 3892 == == 3892 == Για μετρήσεις σφαλμάτων που εντοπίστηκαν και καταστάλθηκαν, εκτελέστε ξανά με: -v == 3892 == ΣΥΝΟΨΗ ΣΦΑΛΜΑΤΟΣ: 3 σφάλματα από 2 περιβάλλοντα (αποκλείονται: 0 από 0)
== 3892 == Όλα τα μπλοκ σωρού απελευθερώθηκαν - δεν είναι πιθανές διαρροές- Δεν υπάρχουν διαρροές, και αυτό είναι καλά νέα. Αλλά αξίζει να χαμηλώσετε τα μάτια σας λίγο χαμηλότερα (αν και, θέλω να σημειώσω, αυτή είναι μόνο μια περίληψη, οι βασικές πληροφορίες είναι λίγο αλλού):

== 3892 == ΣΥΝΟΨΗ ΣΦΑΛΜΑΤΟΣ: 3 σφάλματα από 2 περιβάλλοντα (καταργήθηκαν: 0 από 0)
3 λάθη. Σε 2 πλαίσια. Σε ένα τόσο απλό πρόγραμμα. Πως!?

Είναι πολύ απλό. Το όλο "κόλπο" είναι ότι η συνάρτηση strlen δεν λαμβάνει υπόψη τον χαρακτήρα τέλους γραμμής - "\ 0". Ακόμα κι αν το καθορίσετε ρητά στη γραμμή εισαγωγής (#define HELLO_STRING "Hello, Habr! \ N \ 0"), θα αγνοηθεί.

Λίγο πάνω από το αποτέλεσμα της εκτέλεσης του προγράμματος, γραμμές -> Γεια σου, Χαμπρ!υπάρχει μια λεπτομερής αναφορά για το τι και πού δεν άρεσε στον πολύτιμο βαλγκρίντ μας. Προτείνω να εξετάσετε αυτές τις γραμμές μόνοι σας και να βγάλετε συμπεράσματα.

Στην πραγματικότητα, η σωστή έκδοση του προγράμματος θα μοιάζει με αυτό:

#περιλαμβάνω #περιλαμβάνω #περιλαμβάνω #define HELLO_STRING "Hello, Habr! \ n" void main () (char * str = malloc (sizeof (char) * (strlen (HELLO_STRING) + 1)); strcpy (str, HELLO_STRING); printf ("-> \ t% s ", str); δωρεάν (str);)
Ας περάσουμε από το valgrind:

$ valgrind --tool = memcheck ./a.out -> Γεια σου, Habr! == 3435 == == 3435 == ΠΕΡΙΛΗΨΗ ΣΩΡΟΥ: == 3435 == σε χρήση κατά την έξοδο: 0 byte σε 0 μπλοκ == 3435 == συνολική χρήση σωρού: 2 εκχωρήσεις, 2 ελεύθερες, 1.038 byte που εκχωρήθηκαν == 3435 = = == 3435 == Όλα τα μπλοκ σωρού απελευθερώθηκαν - δεν είναι δυνατές διαρροές == 3435 == == 3435 == Για μετρήσεις σφαλμάτων που εντοπίστηκαν και αποκρύψθηκαν, εκτελέστε ξανά με: -v == 3435 == ΣΥΝΟΨΗ ΣΦΑΛΜΑΤΟΣ: 0 σφάλματα από 0 περιβάλλοντα (αποκλείονται: 0 από 0)
Πρόστιμο. Χωρίς σφάλματα, +1 byte εκχωρημένης μνήμης βοήθησε στην επίλυση του προβλήματος.

Είναι ενδιαφέρον ότι στις περισσότερες περιπτώσεις τόσο το πρώτο όσο και το δεύτερο πρόγραμμα θα λειτουργούν το ίδιο, αλλά εάν η μνήμη που εκχωρήθηκε για τη γραμμή, στην οποία δεν χωρούσε ο τελικός χαρακτήρας, δεν ήταν κενή, τότε η λειτουργία printf () κατά την έξοδο ενός τέτοιου γραμμή, θα εξάγει επίσης όλα τα σκουπίδια μετά από αυτήν τη γραμμή - όλα θα εμφανίζονται μέχρι να εμφανιστεί ο χαρακτήρας τέλους γραμμής στη διαδρομή printf ().

Ωστόσο, ξέρετε, (strlen (str) + 1) είναι μια τέτοια λύση. Αντιμετωπίζουμε 2 προβλήματα:

  1. Και αν χρειάζεται να εκχωρήσουμε μνήμη για μια συμβολοσειρά που σχηματίζεται χρησιμοποιώντας, για παράδειγμα, s (n) printf (..); Δεν υποστηρίζουμε επιχειρήματα.
  2. Εμφάνιση. Η γραμμή δήλωσης μεταβλητής φαίνεται απλά απαίσια. Μερικοί τύποι καταφέρνουν να βιδώσουν (char *) στο malloc, σαν να γράφουν κάτω από τα συν. Σε ένα πρόγραμμα όπου χρειάζεται τακτικά να επεξεργάζεστε χορδές, είναι λογικό να βρείτε μια πιο κομψή λύση.
Ας βρούμε μια λύση που θα ικανοποιήσει και εμάς και το valgrind.

snprintf ()

int snprintf (char * str, size_t μέγεθος, const char * μορφή, ...);- συνάρτηση - επέκταση του sprintf, που μορφοποιεί μια συμβολοσειρά και την γράφει στον δείκτη που περνά ως πρώτο όρισμα. Διαφέρει από το sprintf () στο ότι η str δεν θα γραφεί περισσότερα byte από το μέγεθος.

Η συνάρτηση έχει ένα ενδιαφέρον χαρακτηριστικό - ούτως ή άλλως επιστρέφει το μέγεθος της συμβολοσειράς που δημιουργείται (εξαιρουμένου του χαρακτήρα τέλους γραμμής). Εάν η συμβολοσειρά είναι κενή, τότε επιστρέφεται το 0.

Ένα από τα προβλήματα που περιέγραψα με τη χρήση του strlen σχετίζεται με τις συναρτήσεις sprintf () και snprintf (). Ας υποθέσουμε ότι πρέπει να γράψουμε κάτι στο str. Η τελική συμβολοσειρά περιέχει τις τιμές άλλων μεταβλητών. Η καταχώρισή μας θα πρέπει να είναι κάπως έτσι:

Char * str = / * εκχωρήστε μνήμη εδώ * /; sprintf (str, "Hello,% s \ n", "Habr!");
Τίθεται το ερώτημα: πώς να προσδιορίσετε πόση μνήμη πρέπει να εκχωρηθεί για τη συμβολοσειρά;

Char * str = malloc (sizeof (char) * (strlen (str, "Hello,% s \ n", "Habr!") + 1)); - δεν θα δουλέψει. Το πρωτότυπο της συνάρτησης strlen () μοιάζει με αυτό:

#περιλαμβάνω size_t strlen (const char * s);
const char * s δεν υπονοεί ότι η συμβολοσειρά που μεταβιβάζεται στο s μπορεί να είναι μια συμβολοσειρά μορφής με μεταβλητό αριθμό ορισμάτων.

Εδώ θα μας βοηθήσει η χρήσιμη ιδιότητα της συνάρτησης snprintf () που προανέφερα. Ας ρίξουμε μια ματιά στον κώδικα για το παρακάτω πρόγραμμα:

#περιλαμβάνω #περιλαμβάνω #περιλαμβάνω void main () (/ * Επειδή το snprintf () δεν λαμβάνει υπόψη τον χαρακτήρα τέλους γραμμής, προσθέστε το μέγεθός του στο αποτέλεσμα * / size_t need_mem = snprintf (NULL, 0, "Hello,% s! \ n" , "Habr") + sizeof ("\ 0"); char * str = malloc (needed_mem); snprintf (str, need_mem, "Hello,% s! \ n", "Habr"); printf ("-> \ t% s", str); δωρεάν (str);)
Εκτελέστε το πρόγραμμα στο valgrind:

$ valgrind --tool = memcheck ./a.out -> Γεια σου, Habr! == 4132 == == 4132 == ΠΕΡΙΛΗΨΗ ΣΩΡΟΥ: == 4132 == σε χρήση κατά την έξοδο: 0 byte σε 0 μπλοκ == 4132 == συνολική χρήση σωρού: 2 εκχωρήσεις, 2 ελεύθερες, 1.041 byte εκχωρημένες == 4132 = = == 4132 == Όλα τα μπλοκ σωρού απελευθερώθηκαν - δεν είναι δυνατές διαρροές == 4132 == == 4132 == Για μετρήσεις σφαλμάτων που εντοπίστηκαν και αποκήρυξαν, εκτελέστε ξανά με: -v == 4132 == ΣΥΝΟΨΗ ΣΦΑΛΜΑΤΟΣ: 0 σφάλματα από 0 περιβάλλοντα (καταργήθηκαν: 0 από 0) $
Πρόστιμο. Έχουμε υποστήριξη για επιχειρήματα. Λόγω του γεγονότος ότι περνάμε το μηδέν ως δεύτερο όρισμα στη συνάρτηση snprintf (), η εγγραφή με μηδενικό δείκτη δεν θα οδηγήσει ποτέ σε Seagfault. Ωστόσο, παρόλα αυτά, η συνάρτηση θα επιστρέψει το απαιτούμενο μέγεθος για τη συμβολοσειρά.

Αλλά από την άλλη, έπρεπε να προσθέσουμε μια επιπλέον μεταβλητή, και την κατασκευή

Size_t need_mem = snprintf (NULL, 0, "Hello,% s! \ N", "Habr") + sizeof ("\ 0");
φαίνεται ακόμα χειρότερο από το strlen ().

Γενικά, το + sizeof ("\ 0") μπορεί να αφαιρεθεί ορίζοντας ρητά το "\ 0" στο τέλος της συμβολοσειράς μορφής (size_t need_mem = snprintf (NULL, 0, "Hello,% s! \ N \0 "," Habr ");), αλλά αυτό δεν είναι σε καμία περίπτωση πάντα δυνατό (ανάλογα με τον μηχανισμό επεξεργασίας γραμμής, μπορούμε να διαθέσουμε ένα επιπλέον byte).

Κάτι πρέπει να γίνει. Σκέφτηκα λίγο και αποφάσισα ότι τώρα ήρθε η ώρα να απευθυνθώ στη σοφία των αρχαίων. Ας περιγράψουμε μια συνάρτηση μακροεντολής που θα καλέσει τη snprintf () με έναν δείκτη null ως πρώτο όρισμα και null ως δεύτερο. Και ας μην ξεχνάμε το τέλος της γραμμής!

#define strsize (args ...) snprintf (NULL, 0, args) + sizeof ("\ 0")
Ναι, μπορεί να είναι είδηση ​​για κάποιον, αλλά οι μακροεντολές στο C υποστηρίζουν έναν μεταβλητό αριθμό ορισμάτων και η έλλειψη λέει στον προεπεξεργαστή ότι το καθορισμένο όρισμα της συνάρτησης μακροεντολής (στην περίπτωσή μας, είναι args) αντιστοιχεί σε πολλά πραγματικά ορίσματα.

Ας ελέγξουμε τη λύση μας στην πράξη:

#περιλαμβάνω #περιλαμβάνω #περιλαμβάνω #define strsize (args ...) snprintf (NULL, 0, args) + sizeof ("\ 0") void main () (char * str = malloc (strsize ("Hello,% s \ n", "Habr! ")); sprintf (str," Hello,% s \ n "," Habr! "); printf (" -> \ t% s ", str); δωρεάν (str);)
Τρέξτε με το valgrund:

$ valgrind --tool = memcheck ./a.out -> Γεια σου, Habr! == 6432 == == 6432 == ΠΕΡΙΛΗΨΗ ΣΩΡΟΥ: == 6432 == σε χρήση κατά την έξοδο: 0 byte σε 0 μπλοκ == 6432 == συνολική χρήση σωρού: 2 εκχωρήσεις, 2 ελεύθερες, 1.041 μπιτ εκχωρημένες == 6432 = = == 6432 == Όλα τα μπλοκ σωρού απελευθερώθηκαν - δεν είναι δυνατές διαρροές == 6432 == == 6432 == Για μετρήσεις σφαλμάτων που εντοπίστηκαν και αποκρυπτογραφήθηκαν, εκτελέστε ξανά με: -v == 6432 == ΣΥΝΟΨΗ ΣΦΑΛΜΑΤΟΣ: 0 σφάλματα από 0 περιβάλλοντα (αποκλείονται: 0 από 0)
Ναι, δεν υπάρχουν λάθη. Ολα είναι σωστά. Και ο Valgrind είναι χαρούμενος και ο προγραμματιστής μπορεί επιτέλους να κοιμηθεί.

Αλλά, τέλος, θα πω κάτι άλλο. Σε περίπτωση που χρειαστεί να εκχωρήσουμε μνήμη για οποιαδήποτε συμβολοσειρά (ακόμα και με ορίσματα) υπάρχει ήδη πλήρως λειτουργική λύση με το κλειδί στο χέρι.

Πρόκειται για τη συνάρτηση asprintf:

#define _GNU_SOURCE / * Δείτε feature_test_macros (7) * / #include int asprintf (char ** strp, const char * fmt, ...);
Ως πρώτο όρισμα, παίρνει έναν δείκτη σε μια συμβολοσειρά (** strp) και εκχωρεί μνήμη στον μη αναφερόμενο δείκτη.

Το πρόγραμμά μας asprintf () θα μοιάζει με αυτό:

#περιλαμβάνω #περιλαμβάνω #περιλαμβάνω void main () (char * str; asprintf (& str, "Hello,% s! \ n", "Habr"); printf ("-> \ t% s", str); δωρεάν (str);)
Και, μάλιστα, στο valgrind:

$ valgrind --tool = memcheck ./a.out -> Γεια σου, Habr! == 6674 == == 6674 == ΠΕΡΙΛΗΨΗ ΣΩΡΟΥ: == 6674 == σε χρήση κατά την έξοδο: 0 byte σε 0 μπλοκ == 6674 == συνολική χρήση σωρού: 3 εκχωρήσεις, 3 ελεύθερες, 1.138 byte εκχωρημένες == 6674 = = == 6674 == Όλα τα μπλοκ σωρού απελευθερώθηκαν - δεν είναι πιθανές διαρροές == 6674 == == 6674 == Για μετρήσεις σφαλμάτων που εντοπίστηκαν και αποκρυπτογραφήθηκαν, εκτελέστε ξανά με: -v == 6674 == ΣΥΝΟΨΗ ΣΦΑΛΜΑΤΟΣ: 0 σφάλματα από 0 περιβάλλοντα (αποκλείονται: 0 από 0)
Όλα είναι καλά, αλλά, όπως μπορείτε να δείτε, κατανεμήθηκε περισσότερη μνήμη και τώρα υπάρχουν τρεις εκχωρήσεις, όχι δύο. Σε αδύναμα ενσωματωμένα συστήματα, αυτή η λειτουργία είναι ανεπιθύμητη.
Επιπλέον, αν γράψουμε man asprintf στην κονσόλα, θα δούμε:

ΣΥΜΜΟΡΦΩΣΗ ΜΕ Αυτές οι συναρτήσεις είναι επεκτάσεις GNU, όχι σε C ή POSIX. Διατίθενται επίσης υπό * BSD. Η υλοποίηση του FreeBSD θέτει το strp σε NULL σε περίπτωση σφάλματος.

Είναι σαφές από αυτό ότι αυτή η δυνατότητα είναι διαθέσιμη μόνο στην πηγή GNU.

συμπέρασμα

Εν κατακλείδι, θέλω να πω ότι η εργασία με χορδές στο C είναι ένα πολύ περίπλοκο θέμα που έχει πολλές αποχρώσεις. Για παράδειγμα, για να γράψετε "ασφαλή" κωδικό όταν δυναμική κατανομήμνήμη, εξακολουθεί να συνιστάται η χρήση της συνάρτησης calloc () αντί για malloc () - το calloc φράζει την εκχωρημένη μνήμη με μηδενικά. Λοιπόν, ή μετά την εκχώρηση μνήμης, χρησιμοποιήστε τη συνάρτηση memset (). Διαφορετικά, τα σκουπίδια που βρίσκονταν αρχικά στην εκχωρημένη περιοχή μνήμης μπορεί να προκαλέσουν ερωτήσεις κατά τη διόρθωση σφαλμάτων και μερικές φορές κατά την εργασία με μια συμβολοσειρά.

Περισσότεροι από τους μισούς συναδέλφους μου προγραμματιστές C (οι περισσότεροι από αυτούς είναι αρχάριοι) που, κατόπιν αιτήματός μου, έλυσαν το πρόβλημα της εκχώρησης μνήμης για συμβολοσειρές, το έκαναν με τέτοιο τρόπο που τελικά οδήγησε σε σφάλματα περιβάλλοντος. Σε μια περίπτωση - ακόμη και σε διαρροή μνήμης (καλά, ένα άτομο ξέχασε να κάνει δωρεάν (str), που δεν συμβαίνει). Στην πραγματικότητα, αυτό με ώθησε να δημιουργήσω αυτή τη δημιουργία που μόλις διαβάσατε.

Ελπίζω ότι κάποιος θα βρει αυτό το άρθρο χρήσιμο. Γιατί τα παζάρισα όλα αυτά - καμία γλώσσα δεν είναι απλή. Παντού έχει τις δικές του λεπτότητες. Και όσο περισσότερες λεπτομέρειες της γλώσσας γνωρίζετε, τόσο καλύτερος είναι ο κώδικάς σας.

Πιστεύω ότι αφού διαβάσετε αυτό το άρθρο, ο κωδικός σας θα είναι λίγο καλύτερος :)
Καλή τύχη, Χαμπρ!

Δήλωση συμβολοσειρών

Μια συμβολοσειρά C είναι ένας μονοδιάστατος πίνακας χαρακτήρων, το τελευταίο στοιχείο του οποίου είναι μια μηδενική τερματική συμβολοσειρά (null terminated string).

Η δήλωση μιας μεταβλητής τύπου string στη γλώσσα C είναι δυνατή με τρεις τρόπους, δύο από τους οποίους αρχικοποιούν τη συμβολοσειρά κατά τη δήλωση.

Πρώτος τρόπος:

Δηλώσεις πίνακα χαρακτήρων (θυμηθείτε να προσθέσετε χώρο για το μηδενικό τέλος):

Χαρ s;

Δεύτερος τρόπος:

Εκχωρήστε μια αρχική τιμή σε μια μεταβλητή συμβολοσειράς (σε αυτή την περίπτωση, ο μεταγλωττιστής μπορεί να υπολογίσει το μήκος της ίδιας της συμβολοσειράς):

Char s = "Παράδειγμα αρχικοποίησης συμβολοσειράς";

Μια σταθερά συμβολοσειράς γράφεται στα δεξιά του σημείου εκχώρησης. Ένα μηδέν ('\ 0') προστίθεται αυτόματα στο τέλος της γραμμής. Οι σταθερές συμβολοσειράς χαρακτήρων τοποθετούνται σε μια κλάση στατικής μνήμης.

Τρίτος τρόπος:

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

Char * s = "Δεύτερη επιλογή αρχικοποίησης";

Η μεταβλητή s θα είναι ένας δείκτης στη θέση στη μνήμη RAM όπου βρίσκεται η σταθερά συμβολοσειράς. Υπάρχει ένα πιθανό λάθος σε αυτή τη μορφή σημειογραφίας, που είναι ότι ένας δείκτης σε έναν χαρακτήρα ονομάζεται συχνά συμβολοσειρά. Η παρακάτω καταχώρηση είναι μόνο ένας δείκτης σε έναν χαρακτήρα, καθώς δεν υπάρχει χώρος για να τοποθετηθεί η συμβολοσειρά:

Χαρ * s;

Εισαγωγή συμβολοσειράς από τυπική συσκευή εισόδου (πληκτρολόγιο)

Υπάρχει ένα σύνολο συναρτήσεων για εργασία με χορδές. Για είσοδο από μια τυπική συσκευή εισόδου (πληκτρολόγιο), οι λειτουργίες βιβλιοθήκης από την τυπική μονάδα εισόδου-εξόδου χρησιμοποιούνται συχνότερα: scanfκαι παίρνει.

Για να εισαγάγετε μια συμβολοσειρά χρησιμοποιώντας μια συνάρτηση scanf, χρησιμοποιεί τη μορφή « % s» , και σημειώστε ότι δεν χρησιμοποιείται κανένα σύμβολο διεύθυνσης μπροστά από το αναγνωριστικό συμβολοσειράς « & » αφού ο μονοδιάστατος πίνακας αντιπροσωπεύεται ήδη από έναν δείκτη στην αρχή του:

Scanf ("% s", s);

Λειτουργία παίρνει ()διαβάζει χαρακτήρες μέχρι να φτάσει σε χαρακτήρα νέας γραμμής. Η συνάρτηση δέχεται όλους τους χαρακτήρες μέχρι τον χαρακτήρα τροφοδοσίας γραμμής, αλλά δεν τον περιλαμβάνει. Ένα μηδέν στο τέλος της γραμμής ('\ 0') προστίθεται στο τέλος της γραμμής. Λειτουργία παίρνει ()βάζει μια ακολουθία χαρακτήρων που διαβάζονται από το πληκτρολόγιο σε μια παράμετρο συμβολοσειράς τύπου και επιστρέφει έναν δείκτη σε αυτήν τη συμβολοσειρά (εάν η λειτουργία ήταν επιτυχής) ή NULL (σε περίπτωση σφάλματος). Στο παρακάτω παράδειγμα, με την επιτυχή ολοκλήρωση της λειτουργίας, στην οθόνη θα εμφανιστούν δύο ίδιες γραμμές:

#περιλαμβάνω int main () (char s; char * p; p = παίρνει (s); printf ("\ n Εισήχθη συμβολοσειρά% s.", s); εάν (p) printf ("\ n Εισήχθη συμβολοσειρά% s.", p); επιστροφή 0;)

Παρεμπιπτόντως, σημειώνουμε ότι η συνάρτηση gets χρησιμοποιείται συχνά για την εισαγωγή οποιωνδήποτε δεδομένων από το πληκτρολόγιο ως συμβολοσειρά με σκοπό την περαιτέρω μετατροπή της συνάρτησης sscanf στην επιθυμητή μορφή ή για προκαταρκτική ανάλυση των δεδομένων εισόδου, για παράδειγμα:

#περιλαμβάνω #περιλαμβάνω #περιλαμβάνω int main () (char s; int x, err; do (printf ("\ n Εισαγάγετε έναν ακέραιο ->"); παίρνει (s); err = sscanf (s, "% d", & x); εάν ( err ! = 1) printf ("\ n Σφάλμα εισαγωγής.");) while (err! = 1); printf ("\ n Εισάχθηκε ακέραιος αριθμός ->% d", x); επιστροφή 0;)

Γραμμές εξόδου σε τυπική έξοδο (οθόνη οθόνης)

Μπορούν να χρησιμοποιηθούν δύο λειτουργίες για την έξοδο συμβολοσειρών σε τυπική έξοδο (οθόνη οθόνης) printfκαι βάζει... Στη συνάρτηση printf, το "% s" μεταβιβάζεται ως μορφή. Η ευκολία χρήσης αυτής της συνάρτησης έγκειται στο γεγονός ότι εκτός από μια συμβολοσειρά, μπορείτε να εξάγετε αμέσως δεδομένα άλλων τύπων. Χαρακτηριστικό γνώρισμα βάζειέγκειται στο γεγονός ότι μετά την έξοδο της γραμμής, η μετάβαση στην επόμενη γραμμή πραγματοποιείται αυτόματα.

Λειτουργίες για εργασία με χορδές

Η βιβλιοθήκη συμβολοσειρών παρέχεται για τη μετατροπή συμβολοσειρών στη γλώσσα C. Κάθε μία από τις λειτουργίες έχει τη δική της μορφή εγγραφής (πρωτότυπο).

Οι πιο χρησιμοποιούμενες λειτουργίες καλύπτονται σε αυτό το άρθρο. - ανάγνωση

Ένα παράδειγμα προγραμμάτων (καταχώρισης) που λειτουργούν με συμβολοσειρές

Συνεχίζοντας το θέμα:
διάφορα

Ίσως, σχεδόν κανείς δεν θα διαφωνήσει με το γεγονός ότι ένα από τα μεγαλύτερα επιτεύγματα της επιστήμης είναι η κατάκτηση του διαστήματος. Χάρη στο σπαρακτικό έργο των επιστημόνων, η επιφάνεια του Άρη σήμερα...

Νέα άρθρα
/
Δημοφιλής