Şimdi Ara

C++ array, pointer, fonksiyon return değeri

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
14
Cevap
0
Favori
2.166
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • Merhabalar, C++ ile bir kelimenin içindeki ünlüleri veren bir fonksiyon yazdım;
    string *KelimedekiUnluler(string kelime) 
    {
    string unluler[kelime.length()];
    string mevcutUnluler = "aeiou";
    int unluSayac = 0;
    for (int i = 0; i < kelime.length(); i = i + 1)
    {
    if (mevcutUnluler.find(kelime[i]) != -1)
    {
    if (kelime[i + 1] == '.')
    {
    unluler[unluSayac] = kelime.substr(i, 2);
    cout << unluler[unluSayac];
    unluSayac++;
    }
    else
    {
    unluler[unluSayac] = kelime.substr(i, 1);
    cout << unluler[unluSayac];
    unluSayac++;
    }
    }
    }
    return unluler;
    }

    Normalde fonksiyon çıktı yapmayacak, test etmek için cout koydum ve çalışıyor. Ama geriye döndürdüğü değerde bir sıkıntı var.
    Ben bu fonksiyondan gelen değerleri bir string dizisine aktarmak istiyorum, fakat geriye dönen pointerdan hiçbirşekilde veri alamıyorum.
     
    string kelime = "deneme";
    string* retVal = KelimedekiUnluler(kelime);
    cout << *(retVal + 1);

    Mesela bunu denediğimde ilk önde eee çıktısını alıyorum fonksiyon içi cout'lardan daha sonra da program çalışmayı durduruyor ve 3221225477 değeriyle kapanıyor.

    Bu fonksiyonu pointer kullanmadan yazamaz mıyım? C++'ta bir fonksiyonun geri dönüş değeri string arrayi olabilir mi?







  • Local değişkenin adresini dönüyorsunuz, pointerinizin gösterdiği değişken stack framede deallocate olacağı için yan etki oluşacaktır.
    Dynamic memory allocation ile çözebilirsiniz sorununuzu.
    Doğrudan fonksyon gövdesinde oluşturduğunuz bir diziyi dönemezsiniz.

    unluler değişkeninizi
     
    string* unluler = new string[kelime.length()];

    şeklinde tanımlarsanız sıkıntı olmayacaktır.

    Diziyle işiniz bittikten sonra delete etmeyi unutmayın :)



    < Bu mesaj bu kişi tarafından değiştirildi Fatih513 -- 29 Ekim 2014; 23:33:30 >
  • Bu işlem için vector biçilmiş kaftan.

    vector<string> KelimedekiUnluler(string kelime)
    {
    vector<string> unluler;
    ...
    unluler.push_back(kelime.substr(i, 2));

    Pointer yok, direkt nesneyi döndürüyorsun.



    < Bu mesaj bu kişi tarafından değiştirildi Guest-BF8E9B238 -- 30 Ekim 2014; 7:12:52 >
  • welrocken W kullanıcısına yanıt
    Bu fonksiyon pointer kullanmadan yazilabilir. Hatta string dizisine bile ihtiyaç yok. String in kendiside karakter dizisi olduğu için, string olarak dönmek daha kısa olacaktır.

     
    std::string kelimedekiUnluler(const std::string& kelime) {
    const std::string mevcutUnluler = "aeiou";
    std::string unluler;
    size_t harfSayisi = kelime.size();
    for (size_t harfIndeks = 0; harfIndeks < harfSayisi; ++harfIndeks) {
    if (std::binary_search(mevcutUnluler.begin(), mevcutUnluler.end(), kelime[harfIndeks])) {
    unluler.push_back(kelime[harfIndeks]);
    }
    }
    return unluler;
    }



    < Bu mesaj bu kişi tarafından değiştirildi leventg -- 30 Ekim 2014; 10:37:01 >
  • quote:

    Orijinalden alıntı: elektro_gadget

    Bu işlem için vector biçilmiş kaftan.

    vector<string> KelimedekiUnluler(string kelime)
    {
    vector<string> unluler;
    ...
    unluler.push_back(kelime.substr(i, 2));

    Pointer yok, direkt nesneyi döndürüyorsun.

    Hocam bu bir arkadaşın ödevi için ve öğrenmediği konuları kullanamıyorlar, o yüzden pointerdan da kurtulmak istemiştim. Yalnızca array öğrenmişler bu iş için kullanabileceğim. Vector bilseler keşke

    @Fatih513
    Ordaki pointerı kullanmadan olmuyor mu? Şöyle birşey denedim, fonksiyon içinde normal bi string arrayi tanımladım ve boyutunu kelime.length() yaptım, çünkü bir kelimede en fazla kelimenin uzunluğu kadar sesli harf olabilir, daha sonra da while döngüsü ile sadece dolu olan elemanları başka bir array'a atmayı düşündüm fakat fonksiyon return değeri pointer olduğu için kafam karıştı, array döndürebilir miyim, döndürürsem bir başka arrayi fonksiyona eşitleyebilir miyim bilemedim.

    @leventg
    Hocam string array kullanmamın nedeni geriye dönen her bir string tek bir harfi temsil edecek ve char kullanmamamın nedeni ise verilen ödevde "i." "ı" harfini, "o." "ö" harfini temsil ediyor. Dolayısıyla uzunluğu 2 olan harferimiz var. Ve tek bir string kullanırsam geride döndürdüğüm stringi tekrar karakter karakter yorumlamam gerekecek, öyle de çözebilirim muhtemelen, ama .push_back() i öğrenmemiş olabilirler sormam lazım.




  • welrocken W kullanıcısına yanıt
    Türkçe'ye özel harfleride kullanmak için wstring (unicode string) kullanılması daha mantıklı olurdu. Tabi ödev gereği kullanamazsanız diyorsa yapacak birşey yok. :)
  • welrocken W kullanıcısına yanıt
    Hocam öncelikle diğer arkadaşların önerdiklerini kullanmanızı tavsiye etmiyorum zira, vector de string de göreceli olarak büyük nesneler ve referans yada pointer dönmediğiniz sürece arada ek olarak 2 destructor ve 2 copy constructor çağırılır, boş yere işlem yapmanın anlamı yok.

    Fonksyonlardan doğrudan array dönüşü yapamazsınız, zira boyutu belli olmadığı için compiler nereyi ne kadar kopyalayacağını bilemez.
    Bu durumda kalan seçenekleriniz pointer veya referans.

    Ancak, fonksyon gövdesinde tanımladığınız bir değişkenin referansını fonksyondan dönemezsiniz, çünkü referansınızın gösterdiği değişken fonksyon bittiğinde yok edilir.

    Bu nedenle, diziyi dinamik olarak oluşturup, bu dizinin adresini dönmek en mantıklısıdır performans ve hafıza açısından.
  • quote:

    Orijinalden alıntı: welrocken

    verilen ödevde "i." "ı" harfini, "o." "ö" harfini temsil ediyor. Dolayısıyla uzunluğu 2 olan harferimiz var. Ve tek bir string kullanırsam geride döndürdüğüm stringi tekrar karakter karakter yorumlamam gerekecek, öyle de çözebilirim muhtemelen, ama .push_back() i öğrenmemiş olabilirler sormam lazım.

    Türkçe karakterler de 1 byte tır, 2 değil. Tek sorun buysa char kullanabilirsin. Sadece konsolda göstermek sıkıntı olabilir.

    Harfleri döndürürken de ya parametre olarak char dizisi geçip onun üzerine yazarsın, ki işaretçi döndürmekten iyidir. Ya da diziyi struct içine alıp döndürürsün, dizinin kopyası dönmüş olur.
  • sorununu pek anlamadım ama:

     
    string KelimedekiUnluler(string kelime)
    {
    string bulunanUnluler;
    int bulunanIndex = 0;

    while( (bulunanIndex = kelime.find_first_of("aeiou")) != string::npos )
    {
    bulunanUnluler += kelime[bulunanIndex];
    kelime.erase(bulunanIndex, 1);
    }

    return bulunanUnluler;
    }

    int main()
    {
    string stringTut = KelimedekiUnluler("deneme yazisi");

    for(int i = 0; i < stringTut.length(); i++)
    cout << "stringTut[" << i << "] = " << stringTut[i] << endl;


    getchar();
    return 0;
    }


    her bir harfi yeni bir string nesnesinde tutmak saçmalık olur bence bu daha iyi :)



    < Bu mesaj bu kişi tarafından değiştirildi lavara123 -- 30 Ekim 2014; 19:54:11 >
    < Bu ileti m.bolumsonucanavari.com kullanılarak atıldı >
  • @leventg , @elektro_gadget Ödev gereği o şekilde malesef ama sıkıntı olan kısmı şu; ödev tanımında şöyle söyleniyor: kullanıcıdan alınan kelime'de türkçe karakter olamaz, eğer kullanıcı o. u. veya i. yazmış işe bu karakterlerin türkçe karşılığı üzerinden işlem yapılır. Yalnızca ünlü harfler var çünkü ödev küçük & büyük ünlü uyumu. Türkçe karakter kullanımı tamamen yasak, türkçe karakter girildiğinde invalid input yazdırıyoruz ekrana.

    @Fatih513 Hocam ödevin verildiği kitle pointer bilmiyor dolayısıyla pointer kullanmamam lazım.

    @lavara123 sizin kodunuzun değişmiş halini kullanacağım gibi duruyor, diğer hiçbir konuyu öğrenmemişler çünkü. Her harfi bir string olarak tutmamın nedenini tekrar söylüyorum;
    kullanıcı, türkçe ünlü karakter içeren bir kelime girecekse (ki girecek, çünkü türkçe büyük ünlü uyumu ve küçük ünlü uyumu kontrolü yapan bir program yazıyoruz, sessiz harflerin bir önemi yok bu kurallar için dolayısıyla sadece ünlü türkçe karakterler) şu şekilde giriyor, örneği kelime "örnek" ise "o.rnek" dolayısıyla benim programım için "ö" harfi aslında "o." yani tek bir karakter değil, 2 boyutlu bir char dizisi veya bir string.

    Herkese cevapları için teşekkür ederim, şu pointerı hala anlayamadım ama bu ödevlik kullanmamız gerekmeyecek gibi. Fonksiyonun son hali ve kullanımı şöyle oldu;


    string KelimedekiUnluler(string kelime) 
    {
    string unluler;
    string mevcutUnluler = "aeiou";
    for (int i = 0; i < kelime.length(); i = i + 1)
    {
    if (mevcutUnluler.find(kelime[i]) != -1)
    {
    if (kelime[i + 1] == '.')
    {
    unluler += kelime.substr(i, 2) + ",";
    }
    else
    {
    unluler += kelime.substr(i, 1) + ",";
    }
    }
    }
    return unluler;
    }


    string kelime = "aei.ioo.uu.";
    string kelimedekiUnluler = KelimedekiUnluler(kelime);
    int virgulSayisi = 0;
    string geciciunl = kelimedekiUnluler;
    while(geciciunl.find(',') != string::npos)
    {
    virgulSayisi++;
    geciciunl.erase(geciciunl.find(','), 1);
    }
    string tumUnlu[virgulSayisi];

    for(int i = 0; i < virgulSayisi; i++)
    {
    int virgulPos = kelimedekiUnluler.find(',');
    tumUnlu[i] = kelimedekiUnluler.substr(0, virgulPos);
    kelimedekiUnluler.erase(0, virgulPos + 1);//Alternatif -> kelimedekiUnluler = kelimedekiUnluler.substr(virgulPos + 1, kelimedekiUnluler.length() - virgulPos - 1);
    }

    for(int i = 0; i < (sizeof(tumUnlu) / sizeof(*tumUnlu)); i++)
    {
    cout << i + 1 << "\'nci unlu: " << tumUnlu[i] << endl;
    }

    Herkese iyi çalışmalar, teşekkürler.




  • Dev C++'da yazdığım şekliyle çalışan kod Visual Studio'da tumUnlu arrayine variable size vermeme kızdı.
    string *tumUnlu = new string[virgulSayisi];
    Onu bu şekilde yapmak zorunda kaldım, yine geldi pointer. Birşekilde yedirme şansımız var mı bunu visual studio 2013'ün kullandığı derleyiciye veya hata ayıklayıcısına? (hatayı derleme aşamasında veriyor, devC++ çalıştırabildiği için hata ayıklayıcısı çıkarımı yaptım, saçmaladıysam özür dilerim)

    Daha sonra da delete ettim bu arada @Fatih513
  • Yüksek ihtimal string te yasaktır. Aksi halde işaretçiyi yasaklayıp stringe izin veren hocaya selamlarımı iletin.

    C++ ta VLA da yasak. Demekki msvc standart derleme yapıyor. Gcc de normalde derleyici uzantıları açıktır, bu yüzden vla ya izin verir. -pedantic-errors verirsen o da yasaklar. Yani aslında dilde mevcut olmadığı için vla nında kullanılmaması gerek.
  • quote:

    Orijinalden alıntı: elektro_gadget

    Yüksek ihtimal string te yasaktır. Aksi halde işaretçiyi yasaklayıp stringe izin veren hocaya selamlarımı iletin.

    C++ ta VLA da yasak. Demekki msvc standart derleme yapıyor. Gcc de normalde derleyici uzantıları açıktır, bu yüzden vla ya izin verir. -pedantic-errors verirsen o da yasaklar. Yani aslında dilde mevcut olmadığı için vla nında kullanılmaması gerek.

    Aslında yasakdan kastım işlenmeyen şeyler, yalnızca derste görülen şeyleri kullanmaları gerekiyormuş, hoca da benim hocam değil zaten arkadşın ödevi :)

    Vla dediğiniz pointer olarak array oluşturmak mı?
  • Merhabalar, öğrenmedikleri konulardan uzak durarak şu şekilde çözümledik;
    Kelimedeki Ünlüler;
    string KelimedekiUnluler(string kelime) 
    {
    string unluler;
    string mevcutUnluler = "aeiou";
    for (int i = 0; i < kelime.length(); i = i + 1)
    {
    if (mevcutUnluler.find(kelime[i]) != -1)
    {
    if (kelime[i + 1] == '.')
    {
    unluler += kelime.substr(i, 2) + ",";
    }
    else
    {
    unluler += kelime.substr(i, 1) + ",";
    }
    }
    }
    return unluler;
    }


    Küçük Ünlü Uyumu;
    bool minvh(string kelime) 
    {
    string ilkUnlu = firstvowel(kelime);
    string kelimedekiUnluler = KelimedekiUnluler(kelime);
    bool kuralBozuldu = false;
    string unlu;
    int virgulPos;
    while (kelimedekiUnluler.find(',') != string::npos)
    {
    virgulPos = kelimedekiUnluler.find(',');
    unlu = kelimedekiUnluler.substr(0, virgulPos);
    kelimedekiUnluler = kelimedekiUnluler.substr(virgulPos + 1, kelimedekiUnluler.length() - virgulPos - 1);
    if (ilkUnlu == "a" || ilkUnlu == "e" || ilkUnlu == "i." || ilkUnlu == "i")
    {
    if (unlu != "a" && unlu != "e" && unlu != "i." && unlu != "i")
    {
    kuralBozuldu = true;
    }
    }
    else if (ilkUnlu == "o" || ilkUnlu == "o." || ilkUnlu == "u" || ilkUnlu == "u.")
    {
    if (unlu != "o" && unlu != "o." && unlu != "u" && unlu != "u.")
    {
    kuralBozuldu = true;
    }
    }
    }
    return !kuralBozuldu;
    }


    Herkese cevapları için teşekkür ederim, iyi forumlar, iyi çalışmalar.




  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.