Çözüldü arg arguments ne işe yarar?

  • Konuyu açan Konuyu açan TheAdmin33
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 8
  • Gösterim Gösterim 552
Bu konu çözüme ulaştırılmıştır. Çözüm için konuya yazılan tüm yorumları okumayı unutmayın. Eğer konudaki yorumlar sorununuzu çözmediyse yeni bir konu açabilirsiniz.
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.

TheAdmin33

Geliştirme günlüğü olmayan adam
Geliştirici
Yardımsever Üye
Usta Üye
Editör
Mesaj
1.017
Çözümler
57
Beğeni
2.550
Puan
1.849
Ticaret Puanı
0
kodlara bakarken bir çok kez

arg1, arg1[0], arg1[256], arg1[512], arg1[64+1]

gibi kodlar görüyorum bu arguments tam olarak ne işe yarıyor , bu sayılar neyi temsil ediyor ve neden bazılarında +1 ekli ? bunun gibi bir de buf[256 + 1] vs. var onlar da ne işe yarıyor?
 
Son düzenleme:
Çözüm
arg argument'den gelir. Türkçe karşılığı ise argüman.
Bir fonksiyon içinde işlenecek komut verilerini belirler.

Mesela cmd_gm.cpp içindeki oyuncunun skillerini P/G vb. yapma koduna bakalım:
C++:
Genişlet Daralt Kopyala
char arg1[256], arg2[256], arg3[256];
argument = two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
one_argument(argument, arg3, sizeof(arg3));

if (!*arg1 || !*arg2 || !*arg3 || !isdigit(*arg3))
{
    ch->ChatPacket(CHAT_TYPE_INFO, "Syntax: setskillother <target> <skillname> <lev>");
    return;
}

Burada ki arg verilerinin tamamı char türündedir. Yani string. Burada sayılar da string'e dahildir.
char arg1[256] = 256 ise bu string verisinin karakter sayısını temsil eder. (0 dan 255'e kadar)
Yani arg1 argümanı 257 karakter olarak gelirse...
arg argument'den gelir. Türkçe karşılığı ise argüman.
Bir fonksiyon içinde işlenecek komut verilerini belirler.

Mesela cmd_gm.cpp içindeki oyuncunun skillerini P/G vb. yapma koduna bakalım:
C++:
Genişlet Daralt Kopyala
char arg1[256], arg2[256], arg3[256];
argument = two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
one_argument(argument, arg3, sizeof(arg3));

if (!*arg1 || !*arg2 || !*arg3 || !isdigit(*arg3))
{
    ch->ChatPacket(CHAT_TYPE_INFO, "Syntax: setskillother <target> <skillname> <lev>");
    return;
}

Burada ki arg verilerinin tamamı char türündedir. Yani string. Burada sayılar da string'e dahildir.
char arg1[256] = 256 ise bu string verisinin karakter sayısını temsil eder. (0 dan 255'e kadar)
Yani arg1 argümanı 257 karakter olarak gelirse kod çalışmayıp syserr verecektir. Her arg, bir komutu temsil eder.

Buna bağlı olarak aşağıdaki tanım daha kolay anlamayı sağlayacaktır:
Kod:
Genişlet Daralt Kopyala
arg1[256] = <target> Temsil eder.
arg2[256] = <skillname> Temsil eder.
arg3[256] = <lev> Temsil eder.

Örnek kullanıma bakınca da:
Kod:
Genişlet Daralt Kopyala
/setskillother Kaiser 78 40
Görüldüğü üzere Kaiser(target), 78(skill kodu) ve skill leveli olarak 40 şeklinde 3 argüman gönderiliyor.
Bunların her birinin en fazla alacağı karakter sayısı ise 256'dır.

arg[0] ise genellikle tanım olarak değil koşul olarak kullanılır.
Mesela yukarıdaki örnekten giderek şöyle bir örnek vereyim:
C++:
Genişlet Daralt Kopyala
if(arg2[0] == 0)
{
    ch->ChatPacket(CHAT_TYPE_INFO, "Skill index 0 ile başlayamaz.");
    return;
}

Burada arg2 verisinin(skill kodunun) 0.karakterini yani ilk karakterinin 0'a eşit olup olmadığı kontrol edilir. Eğer GM karakterle şöyle bir komut girilirse:
Kod:
Genişlet Daralt Kopyala
/setskillother Kaiser 03 40
Yukarıda verdiğim kod çalışıp hata verecektir.
 
Çözüm
arg argument'den gelir. Türkçe karşılığı ise argüman.
Bir fonksiyon içinde işlenecek komut verilerini belirler.

Mesela cmd_gm.cpp içindeki oyuncunun skillerini P/G vb. yapma koduna bakalım:
C++:
Genişlet Daralt Kopyala
char arg1[256], arg2[256], arg3[256];
argument = two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
one_argument(argument, arg3, sizeof(arg3));

if (!*arg1 || !*arg2 || !*arg3 || !isdigit(*arg3))
{
    ch->ChatPacket(CHAT_TYPE_INFO, "Syntax: setskillother <target> <skillname> <lev>");
    return;
}

Burada ki arg verilerinin tamamı char türündedir. Yani string. Burada sayılar da string'e dahildir.
char arg1[256] = 256 ise bu string verisinin karakter sayısını temsil eder. (0 dan 255'e kadar)
Yani arg1 argümanı 257 karakter olarak gelirse kod çalışmayıp syserr verecektir. Her arg, bir komutu temsil eder.

Buna bağlı olarak aşağıdaki tanım daha kolay anlamayı sağlayacaktır:
Kod:
Genişlet Daralt Kopyala
arg1[256] = <target> Temsil eder.
arg2[256] = <skillname> Temsil eder.
arg3[256] = <lev> Temsil eder.

Örnek kullanıma bakınca da:
Kod:
Genişlet Daralt Kopyala
/setskillother Kaiser 78 40
Görüldüğü üzere Kaiser(target), 78(skill kodu) ve skill leveli olarak 40 şeklinde 3 argüman gönderiliyor.
Bunların her birinin en fazla alacağı karakter sayısı ise 256'dır.

arg[0] ise genellikle tanım olarak değil koşul olarak kullanılır.
Mesela yukarıdaki örnekten giderek şöyle bir örnek vereyim:
C++:
Genişlet Daralt Kopyala
if(arg2[0] == 0)
{
    ch->ChatPacket(CHAT_TYPE_INFO, "Skill index 0 ile başlayamaz.");
    return;
}

Burada arg2 verisinin(skill kodunun) 0.karakterini yani ilk karakterinin 0'a eşit olup olmadığı kontrol edilir. Eğer GM karakterle şöyle bir komut girilirse:
Kod:
Genişlet Daralt Kopyala
/setskillother Kaiser 03 40
Yukarıda verdiğim kod çalışıp hata verecektir.
anladığım kadarıyla bu argümanlar spesifik bir veriyi içinde barındırıyor ve oradaki sayıda veri boyutunu belirliyor, 0 olursa da koşul olmuş oluyor.
tmm ama bu veri nerden geliyor bu veri ne nasıl bilebiliriz,
mesela;

cmd_general.cpp:
Genişlet Daralt Kopyala
ACMD(do_safebox_password)
{
    char arg1[256];
    one_argument(argument, arg1, sizeof(arg1));
    ch->ReqSafeboxLoad(arg1);
}

burada ki veri ne ve neden if (!*arg1) {return;} sorgusu yok

Ve bu argümanların kullanım alanı ne? sistemlerdeki textboxların paket boyutu için kullanılan bir sınırlama önlemimi?
 
anladığım kadarıyla bu argümanlar spesifik bir veriyi içinde barındırıyor ve oradaki sayıda veri boyutunu belirliyor, 0 olursa da koşul olmuş oluyor.
tmm ama bu veri nerden geliyor bu veri ne nasıl bilebiliriz,
mesela;

cmd_general.cpp:
Genişlet Daralt Kopyala
ACMD(do_safebox_password)
{
    char arg1[256];
    one_argument(argument, arg1, sizeof(arg1));
    ch->ReqSafeboxLoad(arg1);
}

burada ki veri ne ve neden if (!*arg1) {return;} sorgusu yok

Ve bu argümanların kullanım alanı ne? sistemlerdeki textboxların paket boyutu için kullanılan bir sınırlama önlemimi?
Çünkü orası kontrol yapılan blok değil, şifrenin tutulduğu blok.
Blok içinde ch->ReqSafeboxLoad(arg1); diye bir gönderme var.
İşleme alınan şifreyi doğrudan buraya gönderiyor.
char.cpp:
C++:
Genişlet Daralt Kopyala
void CHARACTER::ReqSafeboxLoad(const char* pszPassword)
{
    if (!*pszPassword || strlen(pszPassword) > SAFEBOX_PASSWORD_MAX_LEN)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> À߸øµÈ ¾ÏÈ£¸¦ ÀÔ·ÂÇϼ̽À´Ï´Ù."));
        return;
    }
    else if (m_pkSafebox)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í°¡ ÀÌ¹Ì ¿·ÁÀÖ½À´Ï´Ù."));
        return;
    }

    int iPulse = thecore_pulse();

    if (iPulse - GetSafeboxLoadTime()  < PASSES_PER_SEC(10))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í¸¦ ´İÀºÁö 10ÃÊ ¾È¿¡´Â ¿ ¼ö ¾ø½À´Ï´Ù."));
        return;
    }
    else if (GetDistanceFromSafeboxOpen() > 1000)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> °Å¸®°¡ ¸Ö¾î¼ â°í¸¦ ¿ ¼ö ¾ø½À´Ï´Ù."));
        return;
    }
    else if (m_bOpeningSafebox)
    {
        sys_log(0, "Overlapped safebox load request from %s", GetName());
        return;
    }

    SetSafeboxLoadTime();
    m_bOpeningSafebox = true;

    TSafeboxLoadPacket p;
    p.dwID = GetDesc()->GetAccountTable().id;
    strlcpy(p.szLogin, GetDesc()->GetAccountTable().login, sizeof(p.szLogin));
    strlcpy(p.szPassword, pszPassword, sizeof(p.szPassword));

    db_clientdesc->DBPacket(HEADER_GD_SAFEBOX_LOAD, GetDesc()->GetHandle(), &p, sizeof(p));
}
Buradan da paket aracılığı ile kontrol yapılıp (eğer şifre yanlışsa) paketi direkt aşağıdaki client src koduna gönderiyor:

C++:
Genişlet Daralt Kopyala
bool CPythonNetworkStream::RecvSafeBoxWrongPasswordPacket()
{
    TPacketGCSafeboxWrongPassword kSafeboxWrongPassword;

    if (!Recv(sizeof(kSafeboxWrongPassword), &kSafeboxWrongPassword))
        return false;

    PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "OnSafeBoxError", Py_BuildValue("()"));
    return true;
}

OnSafeBoxError kısmı game.py içindedir ve "Yanlış şifre girdin." hatasını gösterir.
Yani arg mevzusu, kullanım amacına göre farklılık gösterebilir.
Bir önceki mesajımdaki örnek, sadece oyuncudan alınan verilerin karakter(string) kontrolünü sağlıyordu.
Ancak depo şifresi gibi spesifik durumlarda, veritabanı kontrolü gibi kontroller yapıldığı için paketler de olaya dahil oluyor ve kullanım değişebiliyor.
 
Çünkü orası kontrol yapılan blok değil, şifrenin tutulduğu blok.
Blok içinde ch->ReqSafeboxLoad(arg1); diye bir gönderme var.
İşleme alınan şifreyi doğrudan buraya gönderiyor.
char.cpp:
C++:
Genişlet Daralt Kopyala
void CHARACTER::ReqSafeboxLoad(const char* pszPassword)
{
    if (!*pszPassword || strlen(pszPassword) > SAFEBOX_PASSWORD_MAX_LEN)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> À߸øµÈ ¾ÏÈ£¸¦ ÀÔ·ÂÇϼ̽À´Ï´Ù."));
        return;
    }
    else if (m_pkSafebox)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í°¡ ÀÌ¹Ì ¿·ÁÀÖ½À´Ï´Ù."));
        return;
    }

    int iPulse = thecore_pulse();

    if (iPulse - GetSafeboxLoadTime()  < PASSES_PER_SEC(10))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í¸¦ ´İÀºÁö 10ÃÊ ¾È¿¡´Â ¿ ¼ö ¾ø½À´Ï´Ù."));
        return;
    }
    else if (GetDistanceFromSafeboxOpen() > 1000)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> °Å¸®°¡ ¸Ö¾î¼ â°í¸¦ ¿ ¼ö ¾ø½À´Ï´Ù."));
        return;
    }
    else if (m_bOpeningSafebox)
    {
        sys_log(0, "Overlapped safebox load request from %s", GetName());
        return;
    }

    SetSafeboxLoadTime();
    m_bOpeningSafebox = true;

    TSafeboxLoadPacket p;
    p.dwID = GetDesc()->GetAccountTable().id;
    strlcpy(p.szLogin, GetDesc()->GetAccountTable().login, sizeof(p.szLogin));
    strlcpy(p.szPassword, pszPassword, sizeof(p.szPassword));

    db_clientdesc->DBPacket(HEADER_GD_SAFEBOX_LOAD, GetDesc()->GetHandle(), &p, sizeof(p));
}
Buradan da paket aracılığı ile kontrol yapılıp (eğer şifre yanlışsa) paketi direkt aşağıdaki client src koduna gönderiyor:

C++:
Genişlet Daralt Kopyala
bool CPythonNetworkStream::RecvSafeBoxWrongPasswordPacket()
{
    TPacketGCSafeboxWrongPassword kSafeboxWrongPassword;

    if (!Recv(sizeof(kSafeboxWrongPassword), &kSafeboxWrongPassword))
        return false;

    PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "OnSafeBoxError", Py_BuildValue("()"));
    return true;
}

OnSafeBoxError kısmı game.py içindedir ve "Yanlış şifre girdin." hatasını gösterir.
Yani arg mevzusu, kullanım amacına göre farklılık gösterebilir.
Bir önceki mesajımdaki örnek, sadece oyuncudan alınan verilerin karakter(string) kontrolünü sağlıyordu.
Ancak depo şifresi gibi spesifik durumlarda, veritabanı kontrolü gibi kontroller yapıldığı için paketler de olaya dahil oluyor ve kullanım değişebiliyor.
Cevaplar için teşekkürler kafamda bir şeyler oluştu ama tam da anlayabildim diyemem dingin kafayla sabah bir daha bakıcam şuan kafam almıyor .

Mesela bu argüman kontrolünü yaptırmazsak ne olabilir? bug yapılıp oyunun hata verip ch kapatmasına vs. sebep olurmu?(paylaştığım sistemlerde kullanmam gerekiyormuydu acaba :unsure: )

Bu buf[32] larda argümanmı oluyor yoksa onlar daha başka bir şeymi?
 
bu buf lar ne işe yarıyor?
C++:
Genişlet Daralt Kopyala
                                char buf[21];
                                snprintf (buf, sizeof (buf), "%u", item2->GetID());
                                LogManager::instance().ItemLog (this, item, "CLEAN_SOCKET", buf);
C++:
Genişlet Daralt Kopyala
                                char buf[21];
                                snprintf (buf, sizeof (buf), "%u", item2->GetID());
                                LogManager::instance().ItemLog (this, item, "CHANGE_ATTRIBUTE", buf);
Kod:
Genişlet Daralt Kopyala
                                char buf[21];
                                snprintf (buf, sizeof (buf), "%u", item2->GetID());
                                LogManager::instance().ItemLog (this, item, "CHANGE_COSTUME_ATTR", buf);

gibi gibi kodlar var bu buff tam olarak ne işe yarıyor? @Kaiser
 
bu buf lar ne işe yarıyor?
C++:
Genişlet Daralt Kopyala
                                char buf[21];
                                snprintf (buf, sizeof (buf), "%u", item2->GetID());
                                LogManager::instance().ItemLog (this, item, "CLEAN_SOCKET", buf);
C++:
Genişlet Daralt Kopyala
                                char buf[21];
                                snprintf (buf, sizeof (buf), "%u", item2->GetID());
                                LogManager::instance().ItemLog (this, item, "CHANGE_ATTRIBUTE", buf);
Kod:
Genişlet Daralt Kopyala
                                char buf[21];
                                snprintf (buf, sizeof (buf), "%u", item2->GetID());
                                LogManager::instance().ItemLog (this, item, "CHANGE_COSTUME_ATTR", buf);

gibi gibi kodlar var bu buff tam olarak ne işe yarıyor? @Kaiser
Snprintf mesela getid değerini alıyor buf bunu hafızada tutuyor sonrasında log kullanarak hafızada tutulan değeri sana veriyor
 
Snprintf mesela getid değerini alıyor buf bunu hafızada tutuyor sonrasında log kullanarak hafızada tutulan değeri sana veriyor
mesela zen fasülyesinde(70103) buf kullanılmamış ama derece meyvesinde(71107) kullanılmış ikiside aynı işe yarıyor neden birinde kullanırken diğerinde kullanmamışlar ki? Ve ben kendi paylaştığım Derece Meyvesi Sistemi 'nde buf kullanmalımıyım?
 
Bu tür geçici depolama alanlarının kullanılması veya kullanılmaması kişiye ve yapılan işleme göre değişir. O yüzden "kullanmalı mıyım?" vb sorular cevapsız kalır.

Mesela :
C++:
Genişlet Daralt Kopyala
char buf[21];
snprintf (buf, sizeof (buf), "%u", item2->GetID());
LogManager::instance().ItemLog (this, item, "CLEAN_SOCKET", buf);

Burada char buf[21] ile geçici bir depolama alanı oluşturuluyor. Görünürde sınır 21'dir ancak aslında 20'dir. Çünkü 0 dan başlar, 1'den değil.

C++:
Genişlet Daralt Kopyala
snprintf (buf, sizeof (buf), "%u", item2->GetID())

Bu kısımda item2->GetID() verisi "%u" türüne dönüştürülür ve dönüştürülürken sizeof (buf) ile overflow kontrolü yapar. Bir sıkıntı yoksa dönüşümü yapar ve item2->GetID() değerini, "%u" türünde buf belleğine atar.

Son olarak da;
C++:
Genişlet Daralt Kopyala
LogManager::instance().ItemLog (this, item, "CLEAN_SOCKET", buf);
Bu kısım ile de ItemLog fonksiyonua buf ile beraber diğer ilgili verileri gönderir.

Peki neden buf kullanılıyor ve neden %u türüne dönüştürülüyor?
C++:
Genişlet Daralt Kopyala
LogManager::instance().ItemLog (this, item, "CLEAN_SOCKET", item2->GetID());
Bu şekilde buf olmadan, doğrudan GetID değerini de gönderebilirdik diye düşünülebilir. Ancak bu sefer beklenen metinsel veriyi değil doğrudan tam sayı gönderilmiş olacak ve bu da sorunları beraberinde getirecek.

item2->GetID() verisi gördüğüm kadarıyla DWORD türünde tanımlanmış. Ancak hem ItemLog fonksiyonu, hem de MySQL bu veriyi NULL olmaması şartıyla beraber unsigned int türünde bekliyor. Dolayısıyla burada böyle bir kodun kullanılması da gayet normal olmuş.
Aslında kodların gittiği yönü takip ederek cevaplar rahatlıkla görülebiliyor.
 
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.
Üst