[Powered by Google Translate] Ni parolos pri structs.
Structs provizi nin per maniero kolekti aron da variabloj kune
en bela pako.
Verŝajne plej facile por vidi ekzemplon al la momento,
do ni diru struct,
poste malfermante frizita streĉa,
kaj en ĉi struct, ni havas int aĝo,
a char * nomon,
kaj tio estas ĝi.
Ĝi povas ŝajni stranga kun punktokomo post frizita streĉa,
sed estas fakte necesa kun structs.
Neniu valida tipo povas iri en la struct difino.
Tie, ni uzis int kaj char *,
sed vi povus ankaŭ uzi tabelo, de diru, 100 elementoj
aŭ eĉ alian struct.
Kiam vi uzas structs en C,
vi kreas novan tipoj
el kolekto de aliaj tipoj.
Tie, ni farante novan tipon
el entjera kaj char *.
Kiel ni vidos poste, struct tipo
estas en tereno de manieroj ekvivalenta al ajna alia tipo vi kutimi.
Kutime, mi povas kompari kiel struct tipo
estas simila al entjero tipo.
Dum la kodo oni skribis validas C,
ĝi ne estas tre utila,
kaj clang donos al ni averton.
Memoru, kiamaniere structs kaj lia estas similaj?
Nu, ni esence nur diris
int,
kiu ne estas tre helpema linio.
Do ni vere deklaras variablon de tiu tipo
donante al ĝi nomon antaux la punktokomo.
Ni vokos la variablo studento.
Nun ni deklaris variablo nomita studento
kun la tipo donita per la struct.
Kiel ni atingos la variabloj ene la struct?
Teknike, la nomoj por tiuj variabloj
estas membroj.
Por aliri ajna aparta membro en studenta struct,
vi aldonas punkton al la variablo nomo,
sekvata de la nomo de la membro vi volas.
Do jen, la nur 2 validajn ebloj
estas student.age
kaj student.name.
Kaj ni povas fari ion kiel
student.age = 12
kaj student.name = lernanto.
Nun kio se ni volis fari duan studento?
Vi povus pensi kopii kaj alglui ĉi tiujn liniojn
kaj ŝanĝi lernanto studento 2 aŭ ion,
kaj kiu funkcios,
sed teknike, lernanto kaj lernantino 2
ne havas la sama tipo.
Vidu, vi ne povos atribui ilin al unu la alian.
Ĉi tio estas ĉar, ĝis nun,
vian struct estis anonima.
Ni devas doni nomon.
Por fari tion, ni enmetas la nomon de la struct
post la vorto struct.
studento,
sekvata de la difino.
Ni povas ankoraŭ tuj deklari variablon de tipo
struct studento, kiel ni faris antaŭe.
Ni nomas ĝin S1
Por doni la struct nomon,
ni povas nun uzi struct studento
en preskaŭ la ĝusta sama maniero ni uzus int.
Do ni povas deklari variablon de tipo struct studento,
kiel
struct studento S2.
Kiel arrays, structs ofertas ŝparvojo inicialización sintakso,
do ni povas diri, struct studento S2
egalas
maldekstra frizita streĉa 3, S2.
Ĉi tie, S2.age estos 3,
kaj S2.name notos al S2.
Pensu pri ĉiuj aĵoj vi povas fari kun int tipo
kaj la plimulto de ili vi povas fari kun struct studento tipo.
Ni povas uzi struct studento kiel tipo de funkcio parametro.
Ni povas uzi struct studento ene de nova struct.
Ni povas havi puntero al struct studento.
Ni povas fari grandeco de struct studento.
Struct studento estas tipo
samkiel int estas tipo.
Ni povas ankaŭ asigni S1 al S2
ekde ambaŭ estas de la sama tipo, do ni povas fari
S1 = S2.
Kio okazas se ni faros
S1.age = 10?
Ĉu S2 ŝanĝo ajn?
Denove, pensu pri la structs same regula entjeroj.
Se ni atribui iun int X al iuj int Y,
kiel X = Y
kaj poste ŝanĝi X,
kiel en X + +,
tio Y ŝanĝi ajn?
Y ne ŝanĝas tie, do ne faras S2 supre.
S2.age estas ankoraŭ 3.
Sed rimarku ke kiam atribui unu struct al alia,
ĉiuj punteros ankoraŭ indikas la saman aferon,
pro tio ke estis nur kopiis.
Se vi ne volas ke la punteros esti dividitaj,
vi devas permane manipuli ke,
eble por malicking unu bloko de memoro por unu el la indikoj atentigi al
kaj kopii la datumoj super.
Ĝi povus esti ĝena havi skribi struct studento ĉie.
Uzanta tipo def, ni povas fari
tipo def
struct
kaj ni nomas ĝin studento.
Nun, ni povas uzi studento ĉie
ke ni kutimis uzi struct studento.
Ĉi tiu tipo def estas anonima struct
kaj nomas ĝin studento.
Sed se ni ankaŭ subteni la lernanto ensalutilo
apud la vorto struct, kiel en typedef struct studento,
ni povus uzi ambaŭ struct lernanto kaj studento interŝanĝebla nun.
Ili eĉ ne devas havi la sama nomo.
Ni povis tajpi def struct studento al Bob
kaj tiam struct studento kaj Bob
estus interŝanĝebla tipoj.
Sendepende de la tipo def,
ni bezonas la identigilo apud struct
se la difino de la struct
estas rekursie.
Ekzemple,
tipo def struct nodo
kaj estos difinita kiel int val
kaj ĝi havos puntero kiu notas al alia struct nodo.,
kiel en struct nodo * proksima.
Kaj tiam ni nomas ĝin nodo.
Ĉi struct estas rekursie,
ekde la difino de struct nodo enhavas en ĝi
puntero al struct nodo.
Rimarku ke ni devas diri struct nodo * sekva
ene de la difino de la struct nodo,
ekde la tipo def ne finis ankoraŭ ni permesos simpligi ĉi
justaj nodo * proksima.
Vi lernos pli pri structs simila al tiu
kiam kontraktanta kun ligitaj lertaj kaj arboj.
Kio pri structs en funkcio?
Ĉi tiu estas ankaŭ perfekte valida.
Ni povis esti
neniigas func
kiu prenas kiel argumento,
studento j
kaj ĝi faras ion kun tiu studento.
Kaj tiam ni povas pasi ĝin kiel studento struct kiel tia.
Func de S1 de antaŭ.
La struct kondutas
precize kiel entjero estus kiam pasis al funkcio.
Func ricevas kopion de S1
kaj pro tio ne povas modifi S1;
pli ĝuste, nur la kopion de ĝi ke tio stokitaj en S.
Se vi volas ke la funkcio por povi modifi S1,
func bezonos preni studento * S,
kaj vi devos pasi S1 de adreso, kiel tia.
Studenta * S, func & S1.
Estas alia kialo por preterpasi per adreso tie.
Kio se nia struct enhavis 100 kampoj?
Ĉiu unuopa momento ni pasis studento al func,
nia programo bezonas kopii ĉiujn el tiuj 100 kampoj enen func la argumento S,
eĉ se ĝi neniam uzas la vasta plimulto de ili.
Do eĉ se func ne intencas modifante la studento,
se povas ankoraŭ esti valora por pasi de adreso.
Konsentite, kio se ni volas krei puntero al struct?
Ni povus fari ion kiel
studento * S
egalas malloc
grandeco de studento.
Rimarku ke grandeco de ankoraŭ laboras tie.
Nu do kiel ni nun aliri la aĝo membro
de la bloko ke S punktoj al?
Vi eble unue pensas fari
* S.age = 4,
sed ĉi tio ne tute funkcias.
Ekde ĉi tiu estos efektive esti interpretita kiel
* S.age en krampoj = 4,
kiu eĉ ne kompili,
ekde S estas ne struct aŭ pli ĝuste puntero al struct,
kaj tiel la punkto ne funkcios ĉi tie.
Ni povus fari
(* S). Aĝo = 4
sed la krampoj povas akiri tedas kaj konfuza.
Feliĉe, ni havas specialan sago operatoro
kiu similas iun kiel
S-> aĝo = 4.
Tiuj 2 manieroj de referenco aĝo
estas ekvivalento
kaj ni ne vere iam bezonas la sago operatoro,
sed ĝi faras tion aspektas pli bela.
Ekde S estas puntero al iu bloko de memoro kiu enhavas la struct,
vi povas pensi de S> aĝo kiel sekvi la puntero sago
kaj kroĉi la evo membro.
Do kial ni cxiam uzas structs?
Estas definitive eblas foriri kun nur la komenca entjeroj,
signoj, punteros kaj similaj
ke ni uzis por;
anstataŭ S1 kaj S2 antaŭ,
ni povis havi age1, age2, name1, kaj name2
ĉiuj al apartaj variabloj.
Ĉi tio estas tre bone kun nur 2 lernantoj,
sed kio se ni havis 10 el ili?
Kaj kio se anstataŭ nur 2 kampoj,
la lernanto struct havis 100 kampoj?
GPA, kursoj, haro koloro, sekso, kaj tiel plu.
Anstataŭ nur 10 structs, ni bezonas 1.000 apartaj variabloj.
Ankaŭ, konsideri funkcion
kiu portas tiun struct kun 100 kampoj kun lia sola argumento
kaj presas ĉiujn kampojn.
Se ni ne uzas struct,
ĉiun solan fojon ni nomas tiun funkcion,
ni bezonas por pasi tute 100 variabloj,
kaj se ni havas 100 variabloj por studento 1,
kaj 100 variabloj por studento 2,
ni bezonas esti certa ne hazarde pasi iuj variabloj de studento 1
kaj iuj variabloj de studento 2.
Estas neeble fari tiun eraron kun struct,
ĉar ĉiuj 100 variabloj estas enhavita en sola pako.
Nur kelkaj fina notoj:
Se vi komprenis cxion ĝis ĉi tiu punkto, granda.
La resto de la video estas nur por kompleteco mem.
Ĉar structs povas teni ajna tipo de pointer,
ili povas ankaŭ teni funkcio punteros.
Se vi estas familiara kun objektema programado,
ĉi havigas maniero uzi structs plani en objektema stilo.
Pli sur funkcio punteros alifoje.
Ankaŭ, foje oni povas havi 2 structs
kies difinoj dependas de unu alia.
Ekzemple,
ni povus havi struct A,
kiu estas difinita kiel
puntero al struct B,
struct B * X,
kaj nun ni povas havi struct B
kiu estas difinita kiel puntero
al struct A,
struct A * Y.
Sed ĉi tio ne kompili,
ekde struct B ne ekzistas en la momento ke struct A estas kompilitaj.
Kaj se ni interŝanĝi struct A kaj struct B,
tiam ni havus nur resti kun la sama problemo;
ĉi tiun fojon, kun struct A ne ekzistanta.
Por solvi tion ĉi, ni povas skribi
struct B;
antaŭ la difino de struct A.
Tiu nomiĝas antaŭen deklaro.
Tiu simple lasas la tradukilo scias, ke
struct B estas valida tipo kiu estos plene difinita poste aŭ aliloke.
Mia nomo estas Rob Bowden, kaj ĉi tiu estas CS50.
[CS50.TV]