Yapı İşaretçilerini Aktarma
Coddy'nin C Journey'sinin Mantık & Akış bölümünün bir parçası. Ders 47 / 63.
Yapıları (structs) değer ile geçirmek veri okumak için iyi çalışsa da, tüm yapı kopyalandığı için büyük yapılarda verimsiz hale gelir. Daha da önemlisi, fonksiyonun içinden orijinal yapıyı değiştiremezsiniz. İşte bu noktada, yapılara işaretçiler (pointers to structs) geçirmek zorunlu hale gelir.
Yapının kendisi yerine bir işaretçiyi yapıya geçirdiğinizde, işlev özgün yapının bellek adresini alır. Bu yaklaşım iki temel avantaj sunar: daha verimlidir (kopyalama yapılmaz) ve işlevin özgün verileri değiştirmesine olanak tanır.
Bir yapıya işaretçi kabul eden bir işlevin söz dizimi şöyledir:
void functionName(struct StructureName *ptr) {
// ptr->member kullanan fonksiyon gövdesi
}Fonksiyonun içinde, yapı üyelerine erişmek ve onları değiştirmek için ok operatörünü kullanırsın. İşaretçi aracılığıyla yapılan tüm değişiklikler, çağıran fonksiyondaki özgün yapıyı doğrudan etkiler; bu da bu yaklaşımı yapı verilerini güncellemesi veya dönüştürmesi gereken fonksiyonlar için mükemmel kılar.
Bu teknik, işaretçilerin (pointers) gücünü yapıların (structs) düzeniyle birleştirdiği için karmaşık veri yapılarıyla çalışan verimli C programları oluşturmak için temeldir.
Görev
KolayVerileri verimli bir şekilde değiştirmek için struct işaretçilerinin işlevlere aktarılmasını gösteren bir C programı oluştur. Programın şunları yapması gerekir:
- Aşağıdaki üyelere sahip
structadlı birBankAccounttanımla:- Hesap numarasını saklamak için bir tamsayı
accountNumber - Hesap sahibinin adını saklamak için 30 boyutunda bir karakter dizisi
ownerName - Hesap bakiyesini saklamak için bir kayan noktalı sayı
balance - İşlem sayısını saklamak için bir tamsayı
transactionCount
- Hesap numarasını saklamak için bir tamsayı
- Şunları yapan
depositMoneyadlı bir işlev yaz:- Parametre olarak bir
BankAccountstruct işaretçisi ve kayan noktalı bir miktar al - Ok operatörünü kullanarak miktarı hesap bakiyesine ekle
- İşlem sayısını 1 artır
Deposit successful. New balance: [balance]yazdır
- Parametre olarak bir
- Şunları yapan
withdrawMoneyadlı bir işlev yaz:- Parametre olarak bir
BankAccountstruct işaretçisi ve kayan noktalı bir miktar al - Para çekme miktarının mevcut bakiyeden büyük olup olmadığını kontrol et
- Yetersiz bakiye varsa
Insufficient funds. Current balance: [balance]yazdır - Yeterli bakiye varsa miktarı bakiyeden çıkar, işlem sayısını artır ve
Withdrawal successful. New balance: [balance]yazdır
- Parametre olarak bir
- Şunları yapan
displayAccountadlı bir işlev yaz:- Parametre olarak bir
BankAccountstruct işaretçisi al - Hesap bilgilerini tam olarak şu biçimde yazdır:
Account Information:Account Number: [accountNumber]Owner: [ownerName]Balance: [balance]Transactions: [transactionCount]
- Parametre olarak bir
- main işlevinde:
BankAccountadlı biraccountdeğişkeni oluştur- Hesap numarasını, hesap sahibinin adını ve başlangıç bakiyesini girdiden oku
- İşlem sayısını 0 olarak ayarla
- Başlangıç hesap durumunu göstermek için
displayAccountişlevini çağır - Bir para yatırma miktarı oku ve
depositMoneyişlevini çağır - Bir para çekme miktarı oku ve
withdrawMoneyişlevini çağır - Son hesap durumunu göstermek için
displayAccountişlevini çağır
Bu görev, struct işaretçilerinin işlevlere aktarılmasının gücünü gösterir. Değerle aktarmanın aksine, işlevler özgün struct'ın bellek adresini alır ve böylece özgün verileri doğrudan değiştirebilir. Bu yaklaşım daha verimlidir (kopyalama yapılmaz) ve işlevlerin çağıran işlevdeki struct değerlerini kalıcı olarak değiştirmesini sağlar.
Kendin dene
#include <stdio.h>
#include <string.h>
// YAPILACAK: BankAccount yapısını (struct) burada tanımlayın
// YAPILACAK: depositMoney fonksiyonunu burada yazın
// YAPILACAK: withdrawMoney fonksiyonunu burada yazın
// YAPILACAK: displayAccount fonksiyonunu burada yazın
int main() {
// Girdiyi oku
int accountNum;
char ownerName[30];
float initialBalance;
float depositAmount;
float withdrawAmount;
scanf("%d", &accountNum);
scanf("%s", ownerName);
scanf("%f", &initialBalance);
scanf("%f", &depositAmount);
scanf("%f", &withdrawAmount);
// YAPILACAK: BankAccount değişkenini oluşturun ve başlatın
// YAPILACAK: Başlangıç durumunu göstermek için displayAccount fonksiyonunu çağırın
// YAPILACAK: Yatırılacak tutar ile depositMoney fonksiyonunu çağırın
// YAPILACAK: Çekilecek tutar ile withdrawMoney fonksiyonunu çağırın
// YAPILACAK: Son durumu göstermek için displayAccount fonksiyonunu çağırın
return 0;
}Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Mantık & Akış bölümündeki tüm dersler
1Pointer Temelleri
Pointer Nedir?Pointer TanımlamaAdres Operatörü (&)Dereference Operatörü (*)NULL Pointer'larÖzet: Pointer Temelleri4Proje: Basit Metin Aracı
Projeye Genel BakışKarakter Sayma2İşaretçiler ve Diziler
İşaretçi Olarak Dizi İsimleriDizi Elemanları - İşaretçilerİşaretçi Aritmetiğiİşaretçilerin KarşılaştırılmasıÖzet: İşaretçi ile Dizi Gezinme5İşaretçiler ve Fonksiyonlar
Değer ile GeçmeFonksiyonlara İşaretçi Göndermeİşaretçiler ile Değişkenleri DeğiştirmeKlasik Bir Örnek: SwapFonksiyonlara Dizi GöndermeÖzet: Fonksiyon İşaretçi Argümanları8Yapılar ve İşaretçiler
Yapılara İşaretçilerOk Operatörü (->)Yapıları Değer ile AktarmaYapı İşaretçilerini AktarmaYapıların Dinamik TahsisiÖzet: Yapıyı Değiştirme - Ptr11Son Tekrar Görevleri
Tekrar: Dinamik String BirleştirmeTekrar: Struct DizisiTekrar: Kelime Frekans Sayacı3Karakter Dizileri ve Stringler
char Dizisi Olarak StringlerNull Sonlandırıcıscanf ile String Girişistrlen() Kullanımıstrcpy() Kullanımıstrcat() Kullanımıstrcmp() KullanımıÖzet: Temel String FonksiyonlarıKendi başına pratik yap: Online C derleyicisi