1. Sissejuhatus
Programmeerimises on stringide töötlemine põhiline ja sageli kasutatav oskus. Eriti C-keeles on oluline käsitleda stringe tõhusalt ja turvaliselt, kuid see võib olla mõnevõrra keerulisem kui teistes kõrgema taseme keeltes. Põhjus on selles, et C-keeles puudub spetsiaalne andmetüüp stringide jaoks, mistõttu tuleb neid põhimõtteliselt käsitleda massiividena.
Selles artiklis selgitame üksikasjalikult C-keele “stringide liitmist”. Stringide liitmine tähendab mitme stringi ühendamist üheks, mida kasutatakse sageli andmete kombineerimisel või kuvamise sisu loomisel. Kuid C-keeles tuleb arvestada mitmete turvalisuse ja jõudlusega seotud aspektidega, mistõttu on vajalik põhjalik arusaamine.
Pärast selle artikli lugemist peaksid sa selgelt mõistma järgmisi punkte:
- C-keele stringide põhitõed ja liitmise meetodid
- Parimad tavad turvaliseks liitmiseks
- Praktilised koodinäited
Omades teadmisi stringide liitmise kohta, muutub C-keeles programmeerimine veelgi võimsamaks ja paindlikumaks. Järgmises peatükis tutvustame konkreetseid meetodeid ja nippe nende turvaliseks kasutamiseks.
2. Stringide põhitõed C-keeles
Stringide töötlemise mõistmiseks C-keeles tuleb kõigepealt omandada teadmised nende käsitlemise põhimõtetest. C-keel ei paku teistes kõrgema taseme keeltes leiduvaid stringitüüpe, seega käsitletakse stringe massiividena. Siin selgitame, kuidas C-keeles stringe defineerida ja millised on põhilised toimingud.
Stringide defineerimine ja käsitlemine
C-keeles käsitletakse stringe char
-tüüpi massiivina. String on järjestikuste märkide kogum, mis peab lõppema '\0'
(nullmärk) sümboliga. See lõputähis annab arvutile teada, kus string lõpeb.
Stringi deklareerimise näide
Põhiline viis stringi deklareerimiseks on järgmine:
char str[20] = "Hello, World!";
Selles näites salvestatakse char
-tüüpi massiivi str
pikkusega 20 string “Hello, World!”. Stringi lõppu lisatakse automaatselt '\0'
, seega koosneb kogu massiiv 19 tähemärgist ja ühest nullmärgist.
Nullmärgi olulisus
C-keeles määratakse stringi lõpp '\0'
abil. Kui see lõputähis puudub, võivad stringifunktsioonid lugeda mälust andmeid suvaliselt edasi, põhjustades ettearvamatuid vigu või isegi programmi krahhi. Seepärast tuleb alati veenduda, et string lõpeb '\0'
-ga.
Näide: probleem ilma nullmärgita
char str[5] = {'H', 'e', 'l', 'l', 'o'};
Selles näites puudub '\0'
, mistõttu stringi ei tunta õigesti ära. Kui proovida seda printf
-iga kuvada, võidakse ekraanile tuua ka mälus järgnevaid andmeid või programm võib kokku kukkuda.
Stringide töötlemine C-keeles
C-keeles on saadaval hulk standardteegi funktsioone stringide töötlemiseks. Lisades <string.h>
päisefaili, saab kasutada funktsioone nagu strcat
, strlen
ja strcmp
. Nendega saab uurida stringi pikkust, neid omavahel liita või võrrelda.
Nende põhifunktsioonide abil õpime, kuidas stringe turvaliselt ja tõhusalt töödelda.
3. Stringide liitmise meetodid
C-keeles on stringide liitmiseks mitu võimalust. Kõige sagedamini kasutatakse strcat
ja strncat
funktsioone, kuid võimalik on ka sprintf
-i kasutamine või käsitsi liitmine, sõltuvalt vajadusest. Selles peatükis käsitleme iga meetodi kasutamist ja tähelepanekuid.
Funktsiooni strcat kasutamine
Mis on strcat
strcat
on standardteegi funktsioon kahe stringi liitmiseks. See lisab teise stringi esimese lõppu, moodustades ühe stringi. Funktsiooni kasutamiseks tuleb lisada päisefail <string.h>
.
Põhinäide
Alljärgnev näide näitab, kuidas strcat
-iga stringe liita:
#include <stdio.h>
#include <string.h>
int main() {
char str1[20] = "Hello, ";
char str2[] = "World!";
strcat(str1, str2);
printf("%s\n", str1); // Väljund: Hello, World!
return 0;
}
Oluline: puhvrioverflow oht
strcat
võib põhjustada puhvrioverflow’d, kui sihtpuhver on liiga väike. Kui str1
ei ole piisavalt suur, kirjutatakse mälu lubatud alast välja. Seetõttu tuleb enne liitmist kontrollida puhvri suurust.
Funktsiooni strncat kasutamine
Mis on strncat
strncat
töötab sarnaselt strcat
-ile, kuid võimaldab määrata lisatavate märkide arvu. See aitab vältida puhvrioverflow’d.
Põhinäide
#include <stdio.h>
#include <string.h>
int main() {
char str1[20] = "Hello, ";
char str2[] = "World!";
strncat(str1, str2, 5); // Lisa kuni 5 märki
printf("%s\n", str1); // Väljund: Hello, Worl
return 0;
}
Selles näites lisatakse str2
esimesed 5 märki str1
-le, vähendades ohtu, et puhver täis saab.
Funktsiooni sprintf kasutamine
Mis on sprintf
sprintf
võimaldab liita stringe koos vormindamisega. See muudab andmed stringiks vastavalt etteantud vormingule ja salvestab tulemuse puhvris. Väga kasulik, kui vaja lisada arve või muutujaid stringi sisse.
Põhinäide
#include <stdio.h>
int main() {
char str[50];
int num = 123;
sprintf(str, "The number is %d", num);
printf("%s\n", str); // Väljund: The number is 123
return 0;
}
Käsitsi liitmine
Eelis ja meetod
Mõnikord võib olla kasulik liita stringe käsitsi tsüklitega, et saada täielik kontroll protsessi üle.
Põhinäide
#include <stdio.h>
int main() {
char str1[20] = "Hello, ";
char str2[] = "World!";
int i, j;
// Leia str1 lõpp
for (i = 0; str1[i] != '\0'; i++);
// Kopeeri str2 str1 lõppu
for (j = 0; str2[j] != '\0'; j++) {
str1[i + j] = str2[j];
}
// Lisa lõputähis
str1[i + j] = '\0';
printf("%s\n", str1); // Väljund: Hello, World!
return 0;
}
4. Parimad tavad turvaliseks stringide liitmiseks
Kui stringe C-keeles liita valesti, võib tekkida puhvrioverflow või ootamatu käitumine, mis ohustab programmi stabiilsust ja turvalisust. Järgnevalt mõned parimad tavad turvaliseks liitmiseks.
Puhvrisuuruse kontroll
Ära ületa puhvri piire
Enne liitmist tuleb alati veenduda, et tulemus mahub sihtpuhvrisse.
Näide kontrollist
#include <stdio.h>
#include <string.h>
int main() {
char str1[20] = "Hello, ";
char str2[] = "World!";
if (strlen(str1) + strlen(str2) < sizeof(str1)) {
strcat(str1, str2);
} else {
printf("Puhver on liiga väike\n");
}
printf("%s\n", str1);
return 0;
}
snprintf kasutamine
snprintf
on turvalisem alternatiiv, sest määratakse maksimaalne kirjutatav suurus.
Näide snprintf kasutamisest
#include <stdio.h>
int main() {
char buffer[20];
snprintf(buffer, sizeof(buffer), "%s %s", "Hello,", "World!");
printf("%s\n", buffer); // Väljund: Hello, World!
return 0;
}
Dünaamilise mälu eraldamise kasutamine paindlikuks liitmiseks
Kui liidetava stringi suurus võib muutuda, tasub kaaluda malloc
ja realloc
kasutamist, et mälu eraldamine oleks paindlik. See võimaldab hallata suuremaid stringe ilma kindla puhvrisuuruseta.
Näide dünaamilisest mälu eraldamisest
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *str1 = malloc(20);
strcpy(str1, "Hello, ");
char *str2 = "World!";
// Arvuta vajalik suurus ja eralda uuesti
str1 = realloc(str1, strlen(str1) + strlen(str2) + 1);
strcat(str1, str2);
printf("%s\n", str1); // Väljund: Hello, World!
free(str1); // Vabasta mälu
return 0;
}
Selles näites eraldatakse mälu malloc
-iga ja vajaduse korral suurendatakse seda realloc
-iga. Seejärel liidetakse stringid strcat
-iga. Lõpuks tuleb mälu vabastada free
-ga.
Kokkuvõte turvalise liitmise põhipunktidest
- Kontrolli alati puhvri suurust enne liitmist.
- Kasutage
strncat
võisnprintf
turvaliseks töötlemiseks. - Kasuta dünaamilist mälu, kui liidetavate stringide suurus pole eelnevalt teada.

5. Praktilised koodinäited
Järgnevalt vaatleme praktilisi koodinäiteid, mis illustreerivad C-keeles stringide liitmise erinevaid meetodeid.
1. Lihtne liitmine strcat-iga
#include <stdio.h>
#include <string.h>
int main() {
char greeting[30] = "Hello, ";
char name[] = "Alice";
strcat(greeting, name);
printf("%s\n", greeting); // Väljund: Hello, Alice
return 0;
}
2. Turvaline liitmine strncat-iga
#include <stdio.h>
#include <string.h>
int main() {
char buffer[15] = "Hello, ";
char additionalText[] = "Wonderland!";
strncat(buffer, additionalText, 7); // Liida kuni 7 märki
printf("%s\n", buffer); // Väljund: Hello, Wonder
return 0;
}
3. Vormindatud liitmine sprintf-iga
#include <stdio.h>
int main() {
char message[50];
int age = 25;
char name[] = "Alice";
sprintf(message, "Name: %s, Age: %d", name, age);
printf("%s\n", message); // Väljund: Name: Alice, Age: 25
return 0;
}
4. Käsitsi liitmine
#include <stdio.h>
int main() {
char str1[20] = "Hello, ";
char str2[] = "C Programming";
int i, j;
for (i = 0; str1[i] != '\0'; i++);
for (j = 0; str2[j] != '\0'; j++) {
str1[i + j] = str2[j];
}
str1[i + j] = '\0';
printf("%s\n", str1); // Väljund: Hello, C Programming
return 0;
}
5. snprintf ja dünaamilise mälu kombinatsioon
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *dynamicStr = malloc(20);
if (dynamicStr == NULL) {
printf("Mälu eraldamine ebaõnnestus\n");
return 1;
}
strcpy(dynamicStr, "Hello, ");
char *additionalStr = "Dynamic World!";
dynamicStr = realloc(dynamicStr, strlen(dynamicStr) + strlen(additionalStr) + 1);
if (dynamicStr == NULL) {
printf("Mälu uuesti eraldamine ebaõnnestus\n");
return 1;
}
strcat(dynamicStr, additionalStr);
printf("%s\n", dynamicStr); // Väljund: Hello, Dynamic World!
free(dynamicStr);
return 0;
}
6. Kokkuvõte
Selles artiklis selgitasime üksikasjalikult C-keele stringide liitmist. Võrreldes kõrgema taseme keeltega on see keerukam ja vajab hoolikat mälu ning puhvrite haldamist.
Peamised punktid
- Stringide põhitõed C-keeles
- C-keeles on string
char
-massiv, mis peab lõppema'\0'
-ga.
- Liitmise meetodid
strcat
jastrncat
võimaldavad stringe liita, kuid tuleb jälgida puhvrisuurust.sprintf
võimaldab lisada stringidesse arve ja muid muutujaid.- Käsitsi liitmine annab täieliku kontrolli, kuid on töömahukam.
- Turvalise liitmise tavad
- Kontrolli pikkust enne liitmist.
- Kasuta
snprintf
-i või dünaamilist mälu suuremate stringide puhul.
Stringide turvaline käsitlemine
Stringidega töötades tuleb alati tagada mälu ohutus, vältida puhvrioverflow’d ja vabastada dünaamiline mälu. Omandades need oskused, saad kirjutada turvalisemaid ja töökindlamaid C-keele programme.