Algajatele: C char massiivi selgitus – Stringi alusest

1. Sissejuhatus

C keel on endiselt laialdaselt kasutatav keel süsteemi- ja sisseehitatud arenduse valdkonnas. Nende seas on “char massiiv” üks kõige põhilisi ja olulisi süntaksielemente stringide käsitlemiseks.

C keeles ei ole standardset stringitüüpi. Selle asemel kasutatakse tähemärkide massiivi (char massiiv) stringide esitamiseks. See ei ole algajatele väga intuitiivne, mistõttu võib char massiivi mõistmine olla C keele õppimisel suur takistus.

Lisaks, kui ei mõista täpselt char massiivi ja char pointeri (char*) kasutamise erinevusi ning nullmärgi (\0) olemasolu, võib see põhjustada ootamatuid vigu.

Selles artiklis keskendutakse teemale “C keel char massiiv“, selgitades selgelt aluseid, rakenduslikke tehnikaid ja levinud vigade vältimise meetodeid.

Kui plaanite C keelt põhjalikult õppida või soovite char massiivi üle vaadata, lugege julgelt lõpuni. Järgmises peatükis selgitatakse kõigepealt char massiivi määratlust ja selle põhimõistet.

2. Mis on char massiiv?

C keeles tähendab “char massiiv” märki (char tüüp) massiivi, mis hoiab mitut üksust. See on põhiline struktuur stringide käsitlemisel.

char tüüp?

C keeles on char tüüp andmetüüp, mis esindab ühte märki. Näiteks saab defineerida ühe märgi muutujat järgmiselt.

char c = 'A';

Nagu näidatud, 'A' sarnane üksik märk, mis on ühejuttega ümbritsetud, defineeritakse char tüübina.

char massiivi põhiline süntaks

Mitme tähe salvestamiseks kasutatakse char tüüpi massiivi. See defineeritakse järgmiselt:

char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

See massiiv eraldab 5-tähelist stringi "Hello" koos nullmärgiga ( \0) ning reserveerib 6 tähe pikkuse mälu.

Nullmärgi ( '

Massiivi suurus ja tähelepanekud

'
) tähtsus

C keeles kasutatakse stringi lõpu näitamiseks nullmärki '\0'. Kui seda sümbolit ei ole, ei tööta stringi manipuleerimise funktsioonid õigesti ja võib esineda ootamatuid käitumisi.

char str[] = "Hello"; // automaatselt lõppu '\0' lisatakse

Nagu eespool näidatud, kui kasutatakse kahekordsete jutumärkidega ümbritsetud stringilitteraali, lisab kompilaator automaatselt '\0' lõppu.

3. char massiivi deklareerimine ja initsialiseerimine

char massiivi kasutamisel on põhiline tagada vajalik tähemärkide arv + 1 (nullmärgi jaoks) suurus. Kui massiivi suurus on liiga väike ja sinna määratakse string, võib see põhjustada puhvri ületäitumist ja programm võib ootamatult lõpetada.

Staatiline deklareerimine ja initsialiseerimine

char massiivi kasutamiseks on kõigepealt vaja sobivat deklareerimist ja initsialiseerimist . Siin selgitame C-keeles char massiivi põhilist deklareerimisviisi, initsialiseerimist ning ka dünaamilise mälu kasutamist.

Stringi literaliga initsialiseerimine

Kõige põhilisema meetodina on massiivi suurus selgelt määrata, deklareerida see ja initsialiseerida üksikuid tähemärke.

char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

Nii tehes saab str käsitleda stringina "Hello". Oluline on, et lõpus peab alati olema '\0'.

Määratud suurusega literalide omistamine

C-keeles on võimalik kasutada lihtsat initsialiseerimist stringi literaliga, nagu allpool näidatud.

char str[] = "Hello";

Selles olukorras määratakse massiivi suuruseks automaatselt "Hello" + '\0', mis on 6 tähemärki. Kui soovite stringi sisu muuta, tuleb deklareerida see char massiivina, mis võimaldab turvalist muutmist.

Dünaamilise mälu eraldamine (malloc) kasutamine

Massiivi suurust määrates on võimalik initsialiseerida stringi literaliga, kuid suuruse puudumisele tuleb tähelepanu pöörata.

char str[5] = "Hello"; // ❌ Vea põhjus (suurus ebapiisav)

Nagu eespool näidatud, vajab "Hello" 5 tähemärki + 1 tähemärk (‘\0’), kokku 6 tähemärki. Seega peab olema vähemalt char str[6].

4. Teksti operatsioonid

Kui soovite stringidega paindlikumalt töötada, on olemas meetod, kus malloc abil eraldatakse dünaamiliselt char massiiv.

#include 
#include 

char* str = malloc(6 * sizeof(char));
strcpy(str, "Hello");

Selles meetodis eraldatakse mälu dünaamiliselt ja stringi käsitletakse selle pointeri kaudu. Pärast kasutamist tuleb free(str); abil mälu vabastada, seda ei tohi unustada.

Teksti kopeerimine: strcpy

C keeles on tavapärane kasutada standardraamatukogu funktsioone char massiivi kasutades tekstide käsitlemisel. Siin selgitame põhilisi tekstide käsitlemise funktsioone ja nende kasutamist konkreetsete näidetega.

Teksti liitmine: strcat

strcpy on funktsioon, mis kopeerib ühe teksti teise char massiivi.

#include 

char src[] = "Hello";
char dest[10];
strcpy(dest, src);

Märkus: dest ei ole piisava suurusega, võib see põhjustada puhvri ületäitumist. Tagake, et suurus oleks kopeeritava teksti pikkus + 1 (nullmärk).

Teksti pikkuse hankimine: strlen

strcat liidab kaks teksti. Teise argumendi sisu lisatakse esimese argumendi lõppu.

#include 

char str1[20] = "Hello";
char str2[] = " World";
strcat(str1, str2);

Selle tulemusena muutub str1 väärtuseks "Hello World". Samuti eeldatakse, et esimese argumendi massiivis on piisavalt ruumi kogu liidetud teksti jaoks.

Teksti võrdlemine: strcmp

strlen funktsioon tagastab teksti pikkuse (nullmärki arvestamata).

#include 

char str[] = "Hello";
int len = strlen(str); // len = 5

Nullmärk ei loe, seega peavad C keelega mittekogenud kasutajad olema ettevaatlikud.

Teksti otsimine: strchr ja strstr

Kahe teksti võrdlemiseks kasutage strcmp.

#include 

char str1[] = "Hello";
char str2[] = "World";

if (strcmp(str1, str2) == 0) {
    // võrdsed
} else {
    // erinevad
}

See funktsioon tagastab 0, kui tekstid on võrdsed, ja erinevuse korral tagastab tähemärkide koodide vahe.

5. char massiivi ja pointeri erinevus

Määratud tähe või alamsõne otsimiseks saab kasutada järgmisi funktsioone.

#include 

char str[] = "Hello World";

// tähemärgi otsimine
char *ptr1 = strchr(str, 'o'); // viit esimesele 'o'-le

// alamsõne otsimine
char *ptr2 = strstr(str, "World"); // viit "World" alguspunkti

Kui ei leita, tagastab mõlemad funktsioonid NULL.

Deklaratsiooni erinevus

C-keeles stringide käsitsemisel, char massiiv ja char pointer (char*) on sarnased, kuid neil on tegelikult erinevad omadused. Selle erinevuse õige mõistmine aitab vältida mälu valesti kasutamist ja ootamatuid vigu.

Muudetavuse erinevus

Alustuseks vaatame deklaratsiooniviisi erinevusi.

char str1[] = "Hello";  // char massiiv
char *str2 = "Hello";   // char pointer

str1 on tõelise sisuga massiiv, mis võtab mälu 6 baiti (“Hello” + ‘\\0’). Teisest küljest, str2 on pointer mälupiirkonnale, kus on salvestatud string literal.

Mälu struktuuri erinevus

char massiiv str1 võimaldab muuta massiivi sisalduvaid tähti vabalt.

str1[0] = 'h'; // OK

Kuid kui nagu char* str2 = "Hello"; viitab string literalile, siis selle sisu muutmine on määratlemata käitumine.

str2[0] = 'h'; // ❌ Määratlemata käitumine (võib põhjustada jooksva aja vea)

Suuruse hankimise erinevus

  • char massiivpinnal
  • char'i osoitajakonstantsed piirkonnad (kirjutuskaitstud)heap’i piirkond (malloc jne)mälukasutuse puhul tuleb olla ettevaatlik

Kokkuvõte: kasutamise punktid

Massiivi puhul, sizeof(str1) tagastab massiivi kogu baitide arvu.

char str1[] = "Hello";
printf("%lu", sizeof(str1)); // → 6 ('\\0' sisaldab)

Teisest küljest, pointeri puhul sizeof(str2) tagastab pointeri enda suuruse (tavaliselt 4–8 baiti), seega ei sobi see massiivi suuruse hankimiseks.

char *str2 = "Hello";
printf("%lu", sizeof(str2)); // → 8 (64-bit keskkond)

 

6. Kuidas edastada char massiivi funktsioonile

Üksuschar-massiivichar’i osoitaja
Sisu muutminevõimalikPrincipiililiselt keelatud (literaliseerimisel)
Suuruse saaminesizeof()strlen()
Kirjutamise kasutussobivEi sobi (kirjutuskaitstud)
Paindlikkuskindel suurusPaindlik, kuid tuleb olla ettevaatlik

Põhijuhis: char massiivi edastamine argumendina

C gengo puhul, massiivid funktsioonile edastamisel toimub mitte väärtuse edastamine, vaid pointeri edastamine. See kehtib char massiivi puhul samuti, ning funktsioonile edastamisel antakse massiivi algus aadress (pointer).

Selle mehhanismi mõistmine on funktsioonide vahel stringide manipuleerimisel või sisu muutmisel väga oluline.

Funktsioon, mis muudab sisu

#include 

void printString(char str[]) {
    printf("String: %s\n", str);
}

int main() {
    char greeting[] = "Hello";
    printString(greeting);
    return 0;
}

Selles näites antakse funktsioonile printString argument, mis on tüüpi char[], kuid tegelikult võetakse see vastu kui char*. See tähendab, et char str[] on char *str sama tähendus.

Massiivi suuruse haldamine

Ka funktsiooni sees massiivi sisu muutamisel saab antud aadressi kaudu otse andmeid manipuleerida.

void toUpperCase(char str[]) {
    for (int i = 0; str[i] != ' '; i++) {
        if ('a' <= str[i] && str[i] <= 'z') {
            str[i] = str[i] - ('a' - 'A');
        }
    }
}

int main() {
    char text[] = "hello world";
    toUpperCase(text);
    printf("%s\n", text); // Väljund: HELLO WORLD
    return 0;
}

Nii et isegi kui soovite massiivi sisu muuta, käsitletakse seda pointerina, funktsiooni sees tehtud muudatused kajastuvad kutsujas.

Lugemiseks ainult argument const kasutades

C gengo puhul ei edastata massiivi suuruse infot funktsioonile. Seetõttu on parim praktika edastada suurus samuti argumendina, et tagada turvaline kasutamine.

void printChars(char str[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%c ", str[i]);
    }
    printf("\n");
}

Samuti on tavaline kasutada strlen funktsiooni stringi pikkuse dünaamiliseks saamiseks. Kuid tuleb olla ettevaatlik, et seda ei kasutata massiivide puhul, mis ei lõpe nullterminatsiooniga.

7. Praktiline näide: stringi pööratud kuvamine

Kui stringi funktsiooni sees ei muuda, on soovitatav kasutada const char* et selgelt näidata, et see on ainult lugemiseks.

void printConstString(const char *str) {
    printf("%s\n", str);
}

See aitab vältida soovimatuid muudatusi ja selgitab funktsiooni spetsifikatsiooni.

Eesmärk

Siin kasutame seni õpitud char massiivi teadmisi, et luua tegelikult stringi pööratud kuvamise programm.

Näidis kood

Kasutaja sisestatud stringi väljastatakse üks täht korraga lõpusõna suunas algusse. See on väga kasulik massiivi operatsioonide, stringi pikkuse hankimise ja tsükli töötlemise harjutamiseks.

Selgitus

#include 
#include 

void printReversed(char str[]) {
    int len = strlen(str);
    for (int i = len - 1; i >= 0; i--) {
        putchar(str[i]);
    }
    putchar('\n');
}

int main() {
    char text[100];

    printf("Palun sisestage string: ");
    fgets(text, sizeof(text), stdin);

    // Eemalda reavahetustäht (vastumeede fgets kasutamisel)
    size_t len = strlen(text);
    if (len > 0 && text[len - 1] == '\n') {
        text[len - 1] = '\0';
    }

    printf("Pööratud kuvamisel: ");
    printReversed(text);

    return 0;
}

Käivitamise näide

  • fgets
  • Lisage kindlasti ka protsess, mis eemaldab sisendi lõpus lisatud (reavahetus).
  • strlen()

Rakendamise näpunäited

Palun sisestage string: OpenAI
Pööratud kuvamisel: IAnepO

8. Levinud vead ja nende lahendused

See protsess viib rakendusteni, nagu stringi palindroomi tuvastamine ja virna struktuuri mõistmine jne, mis on kasulik algoritmide õppimisel. Samuti on võimalik kasutada pointeriarvutusi ümberkirjutamiseks, muutes selle sobivaks keerukamate harjutuste jaoks.

1. Nullterminaatori(

2. Puhvri suuruse puudumine

)unustamine

C keeles char massiiv käsitsemisel, algajatest kuni edasijõudnuteni on mitmeid lõkse, millesse võivad sattuda. Siin selgitame sagedasti esinevaid vigu ja nende ennetamise ning lahendamise meetodeid konkreetsemalt.

3. Stringilitteraali muutmine

Üks kõige tavalisemaid vigu on unustada lisada nullmärk (\0) stringi lõppu.

char str[5] = {'H', 'e', 'l', 'l', 'o'}; // ❌ lõpus '\0' puudub
printf("%s\n", str); // määratlemata käitumine

Lahendus:

char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // ✅ õige

Või kasutades stringilitteraali, lisatakse nullmärk automaatselt.

4. fgets’i reavahetuse tähe töötlemise unustamine

strcpy ja strcat funktsioonide kasutamisel, kui sihtmassivi suurus ei ole piisav, põhjustab see mälu rikkumise (puhvri ülevoolu).

char str1[5];
strcpy(str1, "Hello"); // ❌ kopeerib 6 tähemärki massiivi suurusega 5

Lahendus:

  • Kopeerimispaikale tuleb tagada (näiteks: “tähtede arv + 1”)
  • Kaalu turvalisemat kasutamist
char str1[6];
strncpy(str1, "Hello", sizeof(str1) - 1);
str1[5] = '\0'; // lisab lõppu nullmärgi kindluse huvides

5. Näitaja ja massiivi segadus

char *str = "Hello"; nagu deklareeritud näitaja on, võib viidata kirjutamiskindlale alale. Kui sellesse kirjutada, tekib jooksuaegne viga.

char *str = "Hello";
str[0] = 'h'; // ❌ jooksuaegne Segmentation fault

Lahendus:

char str[] = "Hello"; // ✅ deklareeritud muudetavana massiivina
str[0] = 'h';

9. Kokkuvõte

fgets kasutamisel, tuleb tähele panna, et lõpus võib jääda reavahetuse märk (\n).

fgets(str, sizeof(str), stdin);
// str sisaldab näiteks "Hello\n\0"

Lahendus:

size_t len = strlen(str);
if (len > 0 && str[len - 1] == '\n') {
    str[len - 1] = '\0';
}

Mida selles artiklis õppisime

Kuna need näevad sarnased, char* ja char[] segi ajamine võib viia määratlemata käitumiseni. suuruse ( sizeof) erinevus ja muutmisvõimaluste erinevus tuleb meeles pidada.

Nõuanded edasiseks õppeks

Selles artiklis oleme käsitlenud “C keele char massiivi” põhialatest kuni rakendusteni järk-järgult. Lõpuks vaatame artikli sisu üle ja tutvustame edasise õppe suuniseid.

Mida selles artiklis õppisime

  • char-taustade roll ja deklaratsioonimeetod C-keeles ei ole stringitüüpi olemas, seetõttu stringide käsitlemiseks kasutatakse char-tüüpi massiivi.
  • String literalide ja null-merkide (\0) tähtsus Stringi esitamiseks on lõpus null-merk hädavajalik.
  • Standard library functionide kasutamine stringide manipuleerimiseks , , , Kui kasutada neid, saab tõhusalt stringe töödelda.
  • char-taheliste massiivi ja char-pointri erinevus Massiivid ja pointrid on sarnased, kuid mitte samad ning neil on selged erinevused mälu struktuuri ja muutmise võimaluse osas.
  • Kuidas funktsioonidele massiivi edastada ja ohutuse tagamine Massiivid edastatakse tegelikult punktiirina, seetõttu tuleb olla ettevaatlik muudatuste ja suuruse haldamisega.
  • Arusaamise kinnistumine praktiliste näidiste ja tavapäraste vigade kaudu Õppisin praktilise koodi rakendamise ja vigade käsitlemise kaudu realistlikumat kasutamist.

Nõuanded edasiseks õppeks

Char massiivi kasutamise mõistmine on esimene samm C keeles mäluoperatsioonide aluste mõistmiseks. Siin õpitud teadmisi saab rakendada järgmistes sammudes, nagu allpool näidatud.

  • Näituri aritmeetika
  • Dünaamiline mälu haldaminemallocfree
  • struktuuriga kombinatsioon

Lisaks saab teiste kirjutatud koodi lugemise kaudu omandada vaatenurki ja kirjutamisstiile, mis sul endal puuduvad. Tegelike projektide ja OSS (avatud lähtekoodiga tarkvara) lugemise harjumus on samuti väga kasulik.

C keel on väga paindlik, kuid kui seda valesti kasutada, võib see olla ohtlik. Kui aluseid hoolikalt üles ehitad, saab see olema väga võimas tööriist. Char massiivi mõistmine on see esimene samm. Palun kasuta seda artiklit juhendina ja tõsta oma oskusi kindlalt edasi.

侍エンジニア塾