[ C / C++ ] — начинающим: задаем вопросы (архивная - 2015)

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by _Great_, 26 May 2007.

Thread Status:
Not open for further replies.
  1. Ra$cal

    Ra$cal Elder - Старейшина

    Joined:
    16 Aug 2006
    Messages:
    670
    Likes Received:
    185
    Reputations:
    78
    =)) советую все таки книжки для начинающих почитать. что такое область видимости, параметры по значению и по ссылке. имя параметра, принимаемого функцией, использовать у себя нельзя. иначе бы ты тупо запарился выбирать незанятые имена, да и ни к чему такое. хочешь проверить что передаешь - делай переменную со строкой, передавай ее и проверяй.

    char text [] = {"TEST"};
    MessageBox(0, text, "caption", MB_OK);
    if(strcmp(text, "TEXT") == 0{
    ...
    }

    и готовься к головной боли со строковыми функциями. ибо для анси, юникод и _TEXT свои функции... и вообще используй класс string. но для начала почитай книжки. не учится с++ методом глупого набирания кода и мольбы о работе.
     
    1 person likes this.
  2. Smapt

    Smapt Elder - Старейшина

    Joined:
    29 Jan 2008
    Messages:
    31
    Likes Received:
    32
    Reputations:
    3

    PHP:
        char pczHw "hello world!";
        
    char pczBuff[100];
        
    ZeroMemory(pczBuff,100);
        
    memcpy(pczBuff,pczHw+6,5);
    Memcpy кпирует 5 символов с 6, т.е. с 6 по 11.
     
    2 people like this.
  3. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Спасибо конечно, но проблему решил :)
    Code:
    string substr(const string &str, int start, int length)
    {
        if (start  < 0 ) start+=str.length();
        if (length < 0 ) length=str.length()+length-start;
        if (length < 0 ) return "";
        return str.substr(start,length);
    }
    Возникла новая проблема с winsock или _beginthread - точно не знаю. Если вызывать вот это http://forum.antichat.ru/showpost.php?p=373579&postcount=6 один раз, или по очереди (я изменил буффер до 5120 вместо 1023), товсе ок, принимается 5кб, но если же с помощью
    Code:
    _beginthread(Thread, 0, NULL); //Thread - void Thread (void *a) {http://forum.antichat.ru/showpost.php?p=373579&postcount=6}
    то принимается 2кб... В чем может быть проблема? УРЛ/ip подключения есс-но сменил.
     
  4. Smapt

    Smapt Elder - Старейшина

    Joined:
    29 Jan 2008
    Messages:
    31
    Likes Received:
    32
    Reputations:
    3
    Тебе именно 5 кб нужно принять? Пропробуй через while принимать пока не получишь 5 кб.

    Получишь весь ответ полностью...
    PHP:
    char response[1024]; // буффер под ответ

    while( recv(my_sock,(char*)response,sizeofresponse),0)!=SOCKET_ERROR && strlen((const char *)response)!=0)
        {
    printf("%s\n",response);
    ZeroMemory(response,sizeof(response));
    }
    Если нужно получать часть ответа и рвать соеденение - можно попробывать считать полученные данные...

    PHP:

    #define max_response_len 5120 // 5кб))

    char response[1024]; // буффер под ответ
    int response_len 0;
    while( 
    recv(my_sock,(char*)response,sizeofresponse),0) != SOCKET_ERROR && strlen((const char *)response)!=&& response_len max_response_len)
        {
    printf("%s\n",response);
    response_len+=strlen((const char *)response);

    ZeroMemory(response,sizeof(response));
    }
     
  5. razb

    razb Active Member

    Joined:
    24 Mar 2009
    Messages:
    658
    Likes Received:
    133
    Reputations:
    18
    Код в студию ...
     
  6. Gar|k

    Gar|k Moderator

    Joined:
    20 Mar 2009
    Messages:
    1,166
    Likes Received:
    266
    Reputations:
    82
    2 Smapt ппц код... && strlen((const char *)response)!=0 вот это ваще лишнее int recv возвращает количество принятых байт его и нужно проверять

    вообще чтобы точно в своей программе быть уверенем приняли ли вы все или отправили все нужные данные лучше пользоватся такими функциями вместо recv и send

    Code:
    //---TCP/IP функции
    
    // отослать ВСЕ ... - правильная функция
    int sendall(SOCKET s, char *buf, int len, int flags)
    {
        int total = 0;
        int n;
    
        while(total < len)
        {
            n = send(s, buf+total, len-total, flags);
            if(n == -1) { break; }
            total += n;
        }
    
        return (n==-1 ? -1 : total);
    }
    
    // принять ВСЕ ... - правильная функция
    int recvall(SOCKET s, char *buf, int len, int flags)
    {
        int total = 0;
        int n;
    
        while(total < len)
        {
            n = recv(s, buf+total, len-total, flags);
            if(n == -1) { break; }
            total += n;
        }
    
        return (n==-1 ? -1 : total);
    }
    
     
    _________________________
    1 person likes this.
  7. Smapt

    Smapt Elder - Старейшина

    Joined:
    29 Jan 2008
    Messages:
    31
    Likes Received:
    32
    Reputations:
    3
    2Gar|k, ну да, в теории ты прав... а на практике у меня получалось что сервер принимающий без "&& strlen((const char *)response)!=0" зацикливался при некоректном отключении клиента :confused: (например при плохом сетевом соеденении)... Понимаю, звучит это как-то бредово но нечего другого кроме strlen не помогло.
     
  8. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Такс... Проблему решил :) С циклом все ок работает. Но опять новая проблема =\

    PHP:
    void BlaBlaBlavoid *a)
    {
    int i;
    Get("/forum/profile.php?mode=viewprofile&u="+IntToStr(1000+i).c_str(),"tfile.ru"); // тут орет invalid pointer addition.
    i++;
    }

    void Get(char *urlchar *host)
    {
    BlaBlaBla
    }
    Задолбали эти типы данных в c++ =\ Конвертировать только :) Как это решить?
     
  9. Smapt

    Smapt Elder - Старейшина

    Joined:
    29 Jan 2008
    Messages:
    31
    Likes Received:
    32
    Reputations:
    3
    PHP:
     void BlaBlaBlavoid *a

    int i
    Get("tfile.ru","/forum/profile.php?mode=viewprofile&u=%d",1000+i);
    i++; 
    }




    void Get(charhostchar Format, ...)
    {
        
    va_list ap;          // For arguments
        
    va_startapFormat );
        
    int buff_size _vscprintf(Format,ap)+1;
        
    char buff = new char[buff_size];
        
    vsprintf(buff,Format,ap);

    //В переменной buff будет строчка "/forum/profile.php?mode=viewprofile&u=1000" (или не 1000 зависит от того что передашь)

        
    va_end  ap );
    delete[] buff;
    }
     
    #3589 Smapt, 25 Aug 2009
    Last edited: 25 Aug 2009
  10. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Code:
    void Get(char* host, char * Format, ...)
    1. Вместо троеточия что?
    2. Теперь ошибка, что ф-ции нету _vscprintf.
     
  11. Smapt

    Smapt Elder - Старейшина

    Joined:
    29 Jan 2008
    Messages:
    31
    Likes Received:
    32
    Reputations:
    3
    <stdio.h> подключена? Нужно именно проеточие... Функция будет работать по принципу функции printf, в переменную format передаётся "маска" напимер "name %s age %d\n" а в "троеточие" передаётся набор параметров:
    PHP:
    char name "nikolay";
    int age 18;
    printf("name %s   age %d\n",name,age);
    //выведит строку "name nikolay  age 18"
    точно так же будет работать и твой Get.
     
  12. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Подключена.
    ЗЫ: Работаю в Borland C++ Builder 6
     
  13. Smapt

    Smapt Elder - Старейшина

    Joined:
    29 Jan 2008
    Messages:
    31
    Likes Received:
    32
    Reputations:
    3
    Билдера нету под рукой... но попробуй так:
    PHP:
     void BlaBlaBlavoid *a

    int i
    Get("/forum/profile.php?mode=viewprofile&u="+IntToStr(1000+i),"tfile.ru");
    i++; 


    void Get(String urlchar *host

    BlaBlaBla 

     
  14. razb

    razb Active Member

    Joined:
    24 Mar 2009
    Messages:
    658
    Likes Received:
    133
    Reputations:
    18
    Ты пытаешься сложить два указателя на строки, а не их самих это не пхп, для конкатенации есть специальная ф-ция strcat() и если бы ты удосужился почитать хоть немножко любой учебник эти вопросы бы сразу отпали.
     
    1 person likes this.
  15. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Еще вопрос, есть код:
    Code:
    int id = 0;
    
    void Thread( void *a)
    {
    Get(IntToStr(1000+id).c_str());
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    int i;
    for(i=0;i<=1;i++)
    _beginthread(Thread, 0, NULL);
    }
    //---------------------------------------------------------------------------
    
    Вобщем я пишу парсер. Мне надо, чтобы каждый поток отдельно парсил аккаунты. id++ не поканает тут. Как реализовать это?
     
  16. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    void Thread( void *a)
    {
    int mid;

    mid = id++;
    Get(IntToStr(1000+mid).c_str());
    }
    Или как вариант можеш юзать синхронизацию при изменениии. или интерлоки юзать
    mid = InterlockedIncrement(&id) - 1;
    т.е. id увеличится 100% на 1 и вернется его текущее значение. от которого ты отнимиш 1 чтобы получить предыдущее. Антерлок онснован на атомарном доступе. т.е. блокировка шины памяти идет и в этоге никто другой не сможет изменить значение.
    В этоге такая конструкция (без учета того что это вызов апишки)представляет собой такой код:
    Code:
    mov ecx,[esp+4] ; ecx = адресу переменной X
    mov eax,1 
    lock xadd [ecx],eax; блокирем шину памяти, прибавляем значение регистра eax к тому участку памяти где хранится X а предыдущее значение закидываем в eax. 
    inc eax ; увеличиваем eax на 1 - хз зачем MS это делает. сам не понимаю. Типа вернет не старое значение а новое. тупость
    
    т.е. даже если после lock xadd [ecx],eax выполнение получит другой поток, то всё будет нормально потому что значение хранится в регисте, а при смене потока автоматом сохраняются значения всех регистров. И потом уже данные будут браться не их паременной X а из регистра eax.
    темболее что lock xadd [ecx],eax не может прерваться на половине выполнения. И даже если у тебя многопроцессорная система, то всё равно потоки другова процессора не смогут в этотже момент времяни изменить значение переменной.
    Вот такаявот хитро-простая синхронизация может быть сделана
     
    2 people like this.
  17. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    я так понял тебе нужно передавать в каждый поток переменную id, каждый раз инкрементируя ее. Для этого нужно почитать тут: http://msdn.microsoft.com/en-us/library/kdzttdcb%28VS.71%29.aspx

    Дальше есть неколько замечаний:
    - название функции должно отображать то, что она делает а не особенности ее реализации. Thread - так функцию никто не называет. То же касается и Get. Я например не уверен что вообще понял твой вопрос именно из-за дурацких названий функций. переменная 'a' вообще супер...

    - писать сетевые приложения на потоках не стоит, это приводит к потреблению кучи ресурсов. Юзай асинхронные сокеты, тем более в windows полно их разновидностей

    - хотел еще сказать что писать на борланд билдере не стоит вообще.. но тут вроде это уже говорили.
     
    #3597 bons, 26 Aug 2009
    Last edited: 26 Aug 2009
    1 person likes this.
  18. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Сетевые какраз и должны работать на потоках потому как работа с сетью - это самое медленное что может быть.
    Или если тебя устраивает скорость улитки, то вперед!
    Если не юзать потоки то тогда придется тебе работать с неблокируемыми сокетами. Это конечно удобно, но довольно проблематично для новечков.

    CPU C2D + Win2k3 и 500 тредов работы с сетью особото и не наггружают сервак зато дают скорость в 250 раз быстрее чем в один поток. потому как даже если у тебя мего скоростной канал, то ты идут большие задержки при ответе сервера. А если данные придут когда поток не выполняется, то они будут находиться в системном буфере и потом благополочку считаются из него. В современных условиях потеря памяти в 100 мб при хз каком кол-ве потоков - это неиграет роли вообще.
     
    #3598 slesh, 26 Aug 2009
    Last edited: 26 Aug 2009
  19. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    ога при достаточно широком канале потоков может быть очень и очень много. CPU C2D + Win2k3 - не у всех такая производительность. Интересно что подумает об авторе программы человек у компа которого оперативной памяти допустим 128. И если софт пишется не только для себя то было бы разумно потратить пару часов на изучение неблокирующих сокетов - повышение производительности капитальное
     
    1 person likes this.
  20. Ra$cal

    Ra$cal Elder - Старейшина

    Joined:
    16 Aug 2006
    Messages:
    670
    Likes Received:
    185
    Reputations:
    78
    если оперативы мало нада смотреть в сторону пула потоков. он как раз предназначен для балансирования потребления ресурсов\скорости работы потоков.

    ps: вроде как в буст все планировали добавить. но чет так и не посмотрел есть он там или нет...
     
Thread Status:
Not open for further replies.