Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вопрос про преобразование строк (Прошу сильно новичка не пинать:)  (Прочитано 24539 раз)
0 Пользователей и 1 Гость смотрят эту тему.
kvv157
Гость
« : 13-11-2007 14:49 » 

У меня есть некая функция
char* HexForUrl(char Source[1024])
{
   int StrLen;
   int iCounterCicle=0;
   char Destination[1024]="inputmessage=";
              ................
              ................
              тут всякие вычисления и на выходе имею строку Destination
              ................

         return Destination;
}

Я ее вызываю из main().
В main() определена переменная
                 char cOUT_String[1024]="\0";
далее вызывается функция:
                 cOUT_String = HexForUrl(cIN_String);
Ну дык вот Улыбаюсь на последней строчке вылезает ошибка:  error C2440: '=' : cannot convert from 'char *' to 'char [1024]'
Ошибка понятна: не могу сконвертировать один тип в другой. Непонятно вот что: как мне вернуть именно массив из функции? если возвращаемое значение написать char[1024] Улыбаюсь)))))  вылезает ошибка (естественно). Вот соль вопроса: как в С++ функцией вернуть строку как строку-массив а не просто char* (указатель на строку Не понял) или как обходится в подобных ситуациях. Заранее спасибо за ответ.
з.ы. если кто-нибудь еще подскажет как правильно объявлять глоб переменные, чтобы они были видны во всех модулях (срр) буду очень рад. Заранее спасибо всем за ответ!!!   
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 13-11-2007 15:52 » 

kvv157,
Цитата
Ну дык вот  на последней строчке вылезает ошибка:  error C2440: '=' : cannot convert from 'char *' to 'char [1024]'
даже если бы дали присвоить , то это было бы не правильно : ты присваиваешь указатель указателю, а тебе надо скопировать строки -

во первых, нужно знать длину вернутых данных. Её (длину) должна вернуть функция или же тебе длина заранее известна - у тебя это 1024. Кстати, лучше оформить её в виде именованой константы.

копирование:
Код:
const char* p=HexForUrl(cIN_String);
::memmove(cOUT_String,p,1024);

Если будешь использовать библиотеку MFC , то используй тип CString - там много работы со строкой делается в два счёта , всё в классе прописано уже

--------
кстати, всё равно у тебя так ничего не получится:
Код:
char Destination[1024]="inputmessage=";
- локальный массив, видимый только внутри функции. Наружу передаёшь уже бессмысленный указатель , ни на что не указывающий.
Массив Destination нужно сделать глобальным (хуже) или создать до входа в функцию (лучше). Можно создать динамически или статически.

например так:

Код:
enum
{
   e_len=1024,
};

main(...)
{
 char Source[e_len];//статический массив
 //обнуляем
 ::memset(Source,0,e_len);

 if(HexForUrl(Source))
 {
    ...
 }
 
 ...

 return 0;
}

bool HexForUrl(char* Source)
{
   int StrLen;
   int iCounterCicle=0;

   ::memmove(Source,"inputmessage=",e_len);

              ................
              ................
              тут всякие вычисления и на выходе имею строку Source
              ................

         return true;
}

с динамическим массивом выглядило бы так:
Код:
main(...)
{
 char* Source= new BYTE[e_len];//динамический массив

 //обнуляем
 ::memset(Source,0,e_len);

 if(HexForUrl(Source))
 {
    ...
 }


 ...

 //обязательно возвращаем выделенную память в кучу, когда массив больше не нужен
 if(Source)
 {
   delete [] Source;
   Source=0;
 }
 
 ...

 return 0;
}

« Последнее редактирование: 13-11-2007 16:08 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 13-11-2007 16:46 » 

Мой вариант.
Код: (C++)
char* HexForUrl(char *src)
{
    char *dest = new char[1024];

    strcpy("inputmessage=", dest);

    // ........

    return dest;
}

int main()
{
    char *str = HexForUrl("");

    // ......

    delete[] str;
    return 0;
}
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 13-11-2007 16:54 » 

kvv157, сильно пинать не будем. Ага Лёшкин трактат постораюсь формулировать покороче.

У меня есть некая функция
char* HexForUrl(char Source[1024])

Откуда ф-я? Понимаешь, у тебя проблема не с ошибкой, а с принципиальным пониманием конструкций языка C++.
Так что давай по-порядку. С чего начинаешь? Чем пользуешься? Ну и чего хочешь? Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
kvv157
Гость
« Ответ #4 : 13-11-2007 18:48 » 

Цитата
Откуда ф-я? Понимаешь, у тебя проблема не с ошибкой, а с принципиальным пониманием конструкций языка C++.
Так что давай по-порядку. С чего начинаешь? Чем пользуешься? Ну и чего хочешь? Ага
Функцию стряпаю сам для url-кодирования переданной строки. Причем в  эту функцию уже должна приходить подписанная строка закрытым ключом. Далее будет формироваться HTTP запрос и отправляться на сервер. Пользуюсь VS 2003-2005. В итоге хочу получить DLL (как внешнюю компоненту к 1С) с помощью которой можно будет принимать платежи в плат. системе Киберплат из 1С + получу бесценный опыт программироания на С++.
Всем огромное спасибо за ответы. Изучаю... Улыбаюсь))
« Последнее редактирование: 13-11-2007 18:56 от Алексей1153++ » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 14-11-2007 04:45 » 

Понятно. Тогда посоветую тебе начать с какой-нить книжки по С++. Например "изобретателя" С++ Страуструпа. Его полно в инете.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
kvv157
Гость
« Ответ #6 : 14-11-2007 05:08 » 

Понятно. Тогда посоветую тебе начать с какой-нить книжки по С++. Например "изобретателя" С++ Страуструпа. Его полно в инете.
Книжек полно и в твердом и в электронном виде (Давно хотел начать изучать С++). Просто мне тут за 5 мин объяснили, сам бы в книгах рылся гораздо дольше.
Я уже посмотрел справочник по С++ и понял что главная ошибка у меня - я не правильно передавал в функцию массив и вообще неправильно его создавал. Теперь дошло. надо создавать динамический массив, а обратно возвращать указатель на него.
Еще вопрос: при написании HTTP клиента что лучше использовать winsockets или MFC ?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 14-11-2007 05:15 » 

kvv157, передают обычно не массив , а указатель на него

насчёт создания динамически - если внутри функции создаёшь, отрази это в названии функции (чтоб не забыть удалить потом массив). Лучше всё же снаружи функции создавать , а ещё лучше - написать классик , который будет иметь методы - создать массив, удалить массив. А в деструкторе проверить - если массив был создан, удалить его. Тогда создаёшь экземпляр такого класса, передаёшь указатель в функцию , она вызывает метод создания. После выхода из функции работаешь (через методы) с массивом, потом удаляешь. Если забыл удалить - деструктор класса сам удалит
Записан

kvv157
Гость
« Ответ #8 : 14-11-2007 06:03 » 

kvv157,
Цитата
с динамическим массивом выглядило бы так:
Код:
main(...)
{
 char* Source= new BYTE[e_len];//динамический массив

 //обнуляем
 ::memset(Source,0,e_len);

 if(HexForUrl(Source))
 {
    ...
 }


 ...

 //обязательно возвращаем выделенную память в кучу, когда массив больше не нужен
 if(Source)
 {
   delete [] Source;
   Source=0;
 }
 
 ...

 return 0;
}

У меня создано приложение как консольное, вероятно тип BYTE не опеределен. Посмотрел в MSDN там написано, что опеределен в WINDEF.H. Подключаю у меня лезет ошибка:
error C2146: syntax error : missing ';' before identifier 'ContextRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\WinNT.h(3568) : error C2501: '_EXCEPTION_POINTERS::PCONTEXT' : missing storage-class or type specifiers...
Как мне подключить BYTE? (Пока буду пробовать как статический массив)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 14-11-2007 06:17 » 

вместо BYTE используй
unsigned char

а в твоём случае просто char )
Записан

kvv157
Гость
« Ответ #10 : 14-11-2007 06:19 » 

kvv157, передают обычно не массив , а указатель на него

насчёт создания динамически - если внутри функции создаёшь, отрази это в названии функции (чтоб не забыть удалить потом массив). Лучше всё же снаружи функции создавать , а ещё лучше - написать классик , который будет иметь методы - создать массив, удалить массив. А в деструкторе проверить - если массив был создан, удалить его. Тогда создаёшь экземпляр такого класса, передаёшь указатель в функцию , она вызывает метод создания. После выхода из функции работаешь (через методы) с массивом, потом удаляешь. Если забыл удалить - деструктор класса сам удалит
Я после 1С неустаю восхищаться свободой в С++ (конечно сравнение неправильно, но все же). Захотел так сделал, а не захотел другими 1000 способов можно найти. Думаю сначала разберусь с массивами "в чистом виде",  а после этого начну изучать понятие классы с создания вот такого класса.
Спасибо огромное Алексей.

з.ы. Алексей а как мне нужно объявить константу со значением int 1024, чтобы её было видно во всех модулях.
« Последнее редактирование: 14-11-2007 06:30 от kvv157 » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 14-11-2007 07:00 » 

объявить в неком заголовочном файле , обзови его , скажем, "MyGlobalConstanstZ.h" (добавь файл в проект и в папку проекта)

в нём впиши объявление константы

затем сделай инклуд во все файлы, где нужна константа
#include "MyGlobalConstanstZ.h"

---
а свобода эта, как уже выяснялось, иногда и мешает ) Хотя чаще помогает, конечно
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 14-11-2007 09:32 » 

kvv157, Молодец!

Ну раз времени у тебя в обрез, а голова судя по всему варит, то тогда лучше делать так.

Почему? - Лучше создавать буфер там где его используешь и можешь спокойно удалить.
Не очень чисто, когда ф-я возвращает указатель на буфер ею созданный.

Возможны два варианта: ф-я заполняет массив определённой длины, ф-я заполняет буфер заранее неизвестной длины.

1. Выглядит так

bool MyFunction(byte *pData, const int &nDataSize)
{
        заполняем буфер данными пока не достигнем nDataSize
        возвращаем флаг успешного окончания заполнения.
}

int nDataSize = 1024;
byte *pData = new byte[nDataSize];

if(MyFunction(pData, nDataSize))
{
    ...
}


2. Тут немного сложней. Делается два вызова ф-ции


Ну раз времени у тебя в обрез, а голова судя по всему варит, то тогда лучше делать так.

Почему? - Лучше создавать буфер там где его используешь и можешь спокойно удалить.
Не очень чисто, когда ф-я возвращает указатель на буфер ею созданный.

Возможны два варианта: ф-я заполняет массив определённой длины, ф-я заполняет буфер заранее неизвестной длины.

1. Выглядит так

bool MyFunction(byte *pData, int &nDataSize)
{
        if(pData)
       {
            заполняем буфер данными пока не достигнем nDataSize
            возвращаем флаг успешного окончания заполнения.
       }
        else
       {
             nDataSize = подсчитать размер данных
       }
}

Работа

int nDataSize = 0;
if(MyFunction(NULL, nDataSize)  && nDataSize>0)
{
    byte *pData = new byte[nDataSize];
    MyFunction(pData, nDataSize);
   
    дальше по тексту
}

Еще вопрос: при написании HTTP клиента что лучше использовать winsockets или MFC ?

Если есть возможность, то конечно MFC. Конечно меньше поймёшь, но быстрей достигнешь результата. Если есть время, то рекомендую разобраться с winsockets. Самое главное знать про MFC, что это только ООП обёртка над виндовскоим API.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
kvv157
Гость
« Ответ #13 : 14-11-2007 11:01 » 

У меня еще вопросик появился:
есть код
Код:
         strcat(cIN_String,String1_1);
strcat(cIN_String,sOperatorGateaway);
strcat(cIN_String,String1_2);
strcat(cIN_String,String1_2);
strcat(cIN_String,String2);
strcat(cIN_String,String3);
strcat(cIN_String,cSizeSource);
strcat(cIN_String,cSizeSource);

видел где то что можно более "красиво" записать типа
cIN_String << String1_1 << sOperatorGateaway << String1_2 и т.д.
Это я так понимаю надо перегрузкой оператора делать ?  Не понял

З,Ы,
Еще раз большое всем за ответы, благодаря форуму Класс! я очень продвинулся.
Сейчас закончу составлять строку-заголовок HTTP запроса и буду изуть то что Джон написал  Здесь была моя ладья... и класс составлять. Что, съел?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 14-11-2007 11:14 » 

Насчёт красивостей - не знаю ... Чисто субъективно - мне так некрасиво. Я бы сделал так (повторяю - чисто субъективно Улыбаюсь )
Код:
{
  const char* Arr[]=
  {
    String1_1,
    sOperatorGateaway,
    String1_2,
    String1_2,
    String2,
    String3,
    cSizeSource,
    cSizeSource,
    0
  };

  for(int i=0;Arr[i];i++)
  {
    strcat(cIN_String,Arr[i]);
  }
}
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #15 : 14-11-2007 12:07 » 

видел где то что можно более "красиво" записать

Посмотри стандартную библиотеку языка STL. В частности объект string.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
kvv157
Гость
« Ответ #16 : 14-11-2007 15:07 » 

У меня назрел еще один вопросик про WinSockets:
почему функция recv возвращает мне только заголовок запроса, а контент где ?
Вот как заголовок выглядит(который приходит обратно):

HTTP/1.1 200 OK
Date=Wed, 14 Nov 2007 15:01:25 GMT
Server=Apache
Content-Type=text/html; charset=windows-1251
А где контент?  Здесь была моя ладья...

Код следующий
Код:
while( bytesRecv == SOCKET_ERROR ) 
{
        bytesRecv = recv( m_socket, recvbuf,1024, 0 );
        if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )
{
            printf( "Connection Closed.\n");
            break;
        }
        if (bytesRecv < 0)
            return(1);
        cout<<"\n"<<" -------------------------------------------------------------------- "<<"\n";
printf( "Bytes Recv: %ld\n", bytesRecv );
cout<<recvbuf<<"\n";
    }

Аналогичный запрос отправляю с помощью HTTP снифера - заголовок тот же плюс контент есть.

И еще почему запрос проходит только когда IP адрес указан след. образом:
                        clientService.sin_addr.s_addr = inet_addr( "62.231.13.160" );
а вот так:
                  clientService.sin_addr.s_addr = inet_addr( "payment.cyberplat.ru" );
непроходит ?

Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #17 : 14-11-2007 16:32 » 

почему запрос проходит только когда IP адрес указан след. образом:
                        clientService.sin_addr.s_addr = inet_addr( "62.231.13.160" );
а вот так:
                  clientService.sin_addr.s_addr = inet_addr( "payment.cyberplat.ru" );
непроходит ?

Потому что ф-я парсит адрес в формате IP те цифры разделённые точками. Ты вобще-то в документацию заглядываешь? Рекомендую сначала заглянуть, узнаешь много новых тривиальных вещей. В часности там сказано:
http://msdn2.microsoft.com/en-us/library/ms738563.aspx


Цитата
Parameters
cp
    Null-terminated character string representing a number expressed in the Internet standard ".'' (dotted) notation.

По первому вопросу ща нет времени разбираться, но наверняка что-то в этом роде. Есть же куча туторов и примеров по сокетам. Метод научного тыка - "тыкну, а вдруг получится" - не для всех случаев хорош. Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #18 : 17-11-2007 07:37 » 

C++ это не C
Используйте std::string вместо char * или vector<char>, это удобней и надёжней если нет причины использовать обратное
зачем все эти
memmove
strcpy
ctrcmp
зачем глобальные переменные?
зачем int по константной ссылке слать? разницы нет он хоть по ссылке хоть по значенить займёт в стеке 4 байта

std::string HexForUrl(const std::string&);
std::string HexForUrl(const char *);

Прочтите хотябы правила программирования на C++ Алена Голуба(делов на пару часиков маленькая книжется), я уж не говорю про Герба Саттера
« Последнее редактирование: 17-11-2007 07:40 от LogRus » Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 17-11-2007 12:38 » 

LogRus, всё это дело привычки Улыбаюсь

мне, например , удобнее/надёжнее/понятнее char* и memmove
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #20 : 19-11-2007 14:53 » 

Наверно у меня привычка не закрепилась Улыбаюсь , да и ваще у нас за такое по рукам дают старшие товарищи.
« Последнее редактирование: 19-11-2007 14:59 от LogRus » Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 19-11-2007 15:10 » 

LogRus, у них тоже не закрепилась Улыбаюсь))
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #22 : 19-11-2007 16:13 » 

зачем int по константной ссылке слать? разницы нет он хоть по ссылке хоть по значенить займёт в стеке 4 байта

Правильно, зато наглядность хорошая, тк вторая ф-я уже передаёт НЕ константную ссылку.

Цитата
Прочтите хотябы правила программирования на C++ Алена Голуба(делов на пару часиков маленькая книжется), я уж не говорю про Герба Саттера

И чего только люди не попридумают. Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines