Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > Конвертация string в char*


Автор: Luchi 21.8.2012, 23:01
Доброго времени суток!
Пишу на C++. Версия компилятора 2.95.2 19991024.
Чтобы каждый раз не компилировать программу для смены текста в сообщении, нужно вводить текст в консоли, а дальше чтобы происходила конвертация в char * и сообщение уходило.

Код

#include <windows.h>
#include <winsock.h> //подключение готовых библиотек типа winsock, с ф-ми для отправления и приема сообщений по сети
#include <string>  //библиотека, необходимая для работы объекта string
#include <numeric>  //библиотека, необходимая для работы объекта cin
#include <stdio.h>
#include <conio.h> //библиотека, необходимая для работы оператора getch()

WSADATA ws; //интерфейс между приложением и транспортным протоколом
SOCKET s; //объявляем дескриптор, который может получать или отправлять данные
struct sockaddr_in addr; //объявим переменную для хранения адреса
hostent *d_addr; //структура, в которую будет помещен IP адрес, при возврате
char text[1024];

int main()
{
    string a; //объявление строковой переменной
    cin >> a; //введение значения строковой переменной
    char *textmail = a; //как сконвертировать в char *?
   char textmail[128]; //размер буфера для текста
    
  //инициализируем сокеты
  if (FAILED (WSAStartup (MAKEWORD( 1,1 ), &ws))) //инициализируем сокеты
  { 
    printf("Error in WSAStartup(...)\n");
    return 1;
  }

  //создаем сокет
  s = socket (AF_INET,     //протокол (TCP/IP, IPX...)
              SOCK_STREAM, //тип сокета (SOCK_STREAM/SOCK_DGRAM)
              0            //для Windows приложений может быть 0
             );
  if (s == INVALID_SOCKET) 
  {
     //сообщение с номером ошибки
    printf("Error in socket(...)\n");
    return 1;
  }
  
  //получаем адрес сервера
  d_addr = gethostbyname ("smtp.yandex.ru");
  if (d_addr==NULL)
  {
    printf("Error in gethostbyname(...)\n");
    return 1;
  };

  //заполняем параметры адреса
  addr.sin_family = AF_INET; 
  addr.sin_addr.s_addr = *((unsigned long *) d_addr->h_addr);
  addr.sin_port = htons (25);

  //устанавливаем соединение
  if (SOCKET_ERROR == (connect (s, (sockaddr *) &addr,
                       sizeof (addr)))) 
  { 
    printf("Error in connect(...)\n");
    return 1;
  }

  //ждем ответ от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //приветствуем сервер
  strcpy(text,"EHLO smtp.yandex.ru\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  
  strcpy(text,"AUTH LOGIN\r\n");
  send(s,text,strlen(text),0);
  
  strcpy(text,"вставляю свой логин в base64\r\n");//здесь логин в base64 кодировке
  send(s,text,strlen(text),0);
  
  strcpy(text,"вставляю свой пароль в base64\r\n");//здесь пароль в base64 кодировке
  send(s,text,strlen(text),0);
  
  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //начинаем отправлять конверт состоящий из полей
  //MAIL FROM: и RCPT TO: После каждого поля ждем
  //подтверждение

  //сообщаем отправителя
  strcpy(text,"MAIL FROM: указываю адрес отправителя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //сообщаем получателя
  strcpy(text, "RCPT TO: указываю адрес получателя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //подаем команду, что готовы начать передачу письма
  strcpy(text,"DATA\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);
    
  //передаем заголовок

  //от кого письмо
  strcpy(text,"FROM: указываю адрес отправителя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //кому письмо
  strcpy(text,"TO: указываю адрес получателя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
        
  //тема письма
  strcpy(text,"SUBJECT: test\r\n\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //текст письма
  strcpy(textmail,a); //здесь нужно подставить значение со строковой переменной!!!
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //говорим, что закончили
  strcpy(text,"\r\n.\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //прощаемся с сервером
  strcpy(text,"QUIT");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //закрываем сокет
  closesocket(s);
  
  printf("\n");
  printf("Press any key\n");
  getch(); //команда задержки экрана

  return 0;
}


Подскажите как в с++ происходит конвертация string в char *? На прямую выдает ошибку конвертации, понятно что так конвертировать нельзя. Специальных функций для этого не нашел. Возможно есть альтернатива strcpy для заполнения буфера данными, которая не будет const и будет принимать данные после запуска программы?

Автор: Cheloveck 21.8.2012, 23:03
http://www.cplusplus.com/reference/string/string/c_str/

Автор: feodorv 22.8.2012, 23:28
Цитата(Luchi @  22.8.2012,  00:01 Найти цитируемый пост)
    string a; //объявление строковой переменной
    cin >> a; //введение значения строковой переменной

Программа вся из себя такая сишная, и вдруг... Зачем здесь C++?

Можно просто написать:
Код

char textmail[128]; //размер буфера для текста
fgets( textmail, sizeof(textmail), stdin);


А вот здесь неправильно:
Цитата(Luchi @  22.8.2012,  00:01 Найти цитируемый пост)
  //текст письма
  strcpy(textmail,a); //здесь нужно подставить значение со строковой переменной!!!
  send(s,text,strlen(text),0);
  printf("send - %s", text);

Копируете в textmail, а посылаете text smile 

Автор: borisbn 23.8.2012, 11:24
sorry за оффтоп, но не проще вместо 156 строк кода написать
Код
curl --mail-from "указываю адрес отправителя" --mail-rcpt "указываю адрес получателя" -T - < "текст письма"

а потом, если уж нужно именно из Си++, то вызывать system( "curl --mail-from ... и т.д." );
?

Автор: Luchi 23.8.2012, 18:48
Это первая моя программа, поэтому если можно ответы простым языком

Вопрос был в том, чтобы ввести строку в консоли - занести её в char* - затем занести её в текст письма strcpy. Для упрощения задачи программа разделена на основную для отправки и конвертация.
Спасибо Cheloveck за ссылку, как поставить тебе + за ответ? Из прочитанного получилось следующее:

Программа переводящая введенную строку в консоли в char* дальше она я так понимаю находится в буфере. Эта часть работает.

Код

#include <conio.h> //библиотека, необходимая для работы оператора getch() и printf()
#include <string> //библиотека, необходимая для работы объекта string и cin

using namespace std;

int main ()
{
  char * cstr;
  
  string str;
  cin >> str;
    
  cstr = new char [str.size()+1];
  strcpy (cstr, str.c_str());
  printf("strcpy - %s", cstr);
  
  delete[] cstr;  
    
  printf("\n");
  printf("Press any key\n");
  getch(); //команда задержки экрана

  return 0;
}


Далее основная программа, для отправки писем. Эта часть тоже работает.

Код

#include <conio.h> //библиотека, необходимая для работы оператора getch()
#include <stdio.h>
#include <windows.h>
#include <winsock.h> //подключение готовых библиотек типа winsock, с ф-ми для отправления и приема сообщений по сети

WSADATA ws; //интерфейс между приложением и транспортным протоколом
SOCKET s; //объявляем дескриптор, который может получать или отправлять данные
struct sockaddr_in addr; //объявим переменную для хранения адреса
hostent *d_addr; //структура, в которую будет помещен IP адрес, при возврате
char text[1024];

int main()
{
  //инициализируем сокеты
  if (FAILED (WSAStartup (MAKEWORD( 1,1 ), &ws))) //инициализируем сокеты
  { 
    printf("Error in WSAStartup(...)\n");
    return 1;
  }

  //создаем сокет
  s = socket (AF_INET,     //протокол (TCP/IP, IPX...)
              SOCK_STREAM, //тип сокета (SOCK_STREAM/SOCK_DGRAM)
              0            //для Windows приложений может быть 0
             );
  if (s == INVALID_SOCKET) 
  {
     //сообщение с номером ошибки
    printf("Error in socket(...)\n");
    return 1;
  }
  
  //получаем адрес сервера
  d_addr = gethostbyname ("smtp.yandex.ru"); //d_addr = gethostbyname ("smtp.mail.ru");++++++++
  if (d_addr==NULL)
  {
    printf("Error in gethostbyname(...)\n");
    return 1;
  };

  //заполняем параметры адреса
  addr.sin_family = AF_INET; 
  addr.sin_addr.s_addr = *((unsigned long *) d_addr->h_addr);
  addr.sin_port = htons (25);

  //устанавливаем соединение
  if (SOCKET_ERROR == (connect (s, (sockaddr *) &addr,
                       sizeof (addr)))) 
  { 
    printf("Error in connect(...)\n");
    return 1;
  }

  //ждем ответ от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //приветствуем сервер
  strcpy(text,"EHLO smtp.yandex.ru\r\n"); //strcpy(text,"HELO smtp.mail.ru\r\n");++++++++++++++
  send(s,text,strlen(text),0);  //int send(_in SOCKET s,_in const char *buf,_in  int len,_in int flags);
  printf("send - %s", text);
  
  strcpy(text,"AUTH LOGIN\r\n");  //const char* - это константная строка, то есть та, которую изменить нельзя в принципе, например если в функции в ка-ве параметра стоит const char*, то можно ей передать не переменную, а её значение, например:strcpy(str,"test");strcpy - функция для копирования строки. в строку char* str  копируется константная строка "test"
  send(s,text,strlen(text),0);
  
  strcpy(text,"вставляю свой логин в base64\r\n");//здесь логин в base64 кодировке
  send(s,text,strlen(text),0);
  
  strcpy(text,"вставляю свой пароль в base64\r\n");//здесь пароль в base64 кодировке
  send(s,text,strlen(text),0);
  
  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //начинаем отправлять конверт состоящий из полей
  //MAIL FROM: и RCPT TO: После каждого поля ждем
  //подтверждение

  //сообщаем отправителя
  strcpy(text,"MAIL FROM: указываю адрес отправителя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //сообщаем получателя
  strcpy(text, "RCPT TO: указываю адрес получателя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //подаем команду, что готовы начать передачу письма
  strcpy(text,"DATA\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);
    
  //передаем заголовок

  //от кого письмо
  strcpy(text,"FROM: указываю адрес отправителя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //кому письмо
  strcpy(text,"TO: указываю адрес получателя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
        
  //тема письма
  strcpy(text,"SUBJECT: test\r\n\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //текст письма
  strcpy(text,"text, текст\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //говорим, что закончили
  strcpy(text,"\r\n.\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //прощаемся с сервером
  strcpy(text,"QUIT");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //закрываем сокет
  closesocket(s);
  
  printf("\n");
  printf("Press any key\n");
  getch(); //команда задержки экрана

  return 0;
}


Это их объединение, где возникает ошибка

Код

#include <conio.h> //библиотека, необходимая для работы оператора getch() и printf()
#include <stdio.h>
#include <windows.h>
#include <winsock.h> //подключение готовых библиотек типа winsock, с ф-ми для отправления и приема сообщений по сети
#include <string> //библиотека, необходимая для работы объекта string и cin

WSADATA ws; //интерфейс между приложением и транспортным протоколом
SOCKET s; //объявляем дескриптор, который может получать или отправлять данные
struct sockaddr_in addr; //объявим переменную для хранения адреса
hostent *d_addr; //структура, в которую будет помещен IP адрес, при возврате
char text[1024];

using namespace std;

int main()
{
    char * cstr;
    string str;
  
  //инициализируем сокеты
  if (FAILED (WSAStartup (MAKEWORD( 1,1 ), &ws))) //инициализируем сокеты
  { 
    printf("Error in WSAStartup(...)\n");
    return 1;
  }

  //создаем сокет
  s = socket (AF_INET,     //протокол (TCP/IP, IPX...)
              SOCK_STREAM, //тип сокета (SOCK_STREAM/SOCK_DGRAM)
              0            //для Windows приложений может быть 0
             );
  if (s == INVALID_SOCKET) 
  {
     //сообщение с номером ошибки
    printf("Error in socket(...)\n");
    return 1;
  }
  
  //получаем адрес сервера
  d_addr = gethostbyname ("smtp.yandex.ru");
  if (d_addr==NULL)
  {
    printf("Error in gethostbyname(...)\n");
    return 1;
  };

  //заполняем параметры адреса
  addr.sin_family = AF_INET; 
  addr.sin_addr.s_addr = *((unsigned long *) d_addr->h_addr);
  addr.sin_port = htons (25);

  //устанавливаем соединение
  if (SOCKET_ERROR == (connect (s, (sockaddr *) &addr,
                       sizeof (addr)))) 
  { 
    printf("Error in connect(...)\n");
    return 1;
  }

  //ждем ответ от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //приветствуем сервер
  strcpy(text,"EHLO smtp.yandex.ru\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  
  strcpy(text,"AUTH LOGIN\r\n");
  send(s,text,strlen(text),0);
  
  strcpy(text,"вставляю свой логин в base64\r\n");//здесь логин в base64 кодировке
  send(s,text,strlen(text),0);
  
  strcpy(text,"вставляю свой пароль в base64\r\n");//здесь пароль в base64 кодировке
  send(s,text,strlen(text),0);
  
  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //начинаем отправлять конверт состоящий из полей
  //MAIL FROM: и RCPT TO: После каждого поля ждем
  //подтверждение

  //сообщаем отправителя
  strcpy(text,"MAIL FROM: указываю адрес отправителя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //сообщаем получателя
  strcpy(text, "RCPT TO: указываю адрес получателя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //подаем команду, что готовы начать передачу письма
  strcpy(text,"DATA\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //ждем подтверждение от сервера
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);
    
  //передаем заголовок

  //от кого письмо
  strcpy(text,"FROM: указываю адрес отправителя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //кому письмо
  strcpy(text,"TO: указываю адрес получателя\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
        
  //тема письма
  strcpy(text,"SUBJECT: test\r\n\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  
  cin >> str; //ввожу текст письма
  cstr = new char [str.size()+1]; //заполняю буфер текстом письма
  
  //текст письма
  strcpy(cstr, str.c_str()); //отправляю текст письма, здесь нужно подставить значение со строковой переменной!!!
  strcat(cstr,"\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  
  delete[] cstr;
  
  //говорим, что закончили
  strcpy(text,"\r\n.\r\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);
  recv(s,text,sizeof(text),0);
  printf("recv - %s", text);

  //прощаемся с сервером
  strcpy(text,"QUIT");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

  //закрываем сокет
  closesocket(s);
  
  printf("\n");
  printf("Press any key\n");
  getch(); //команда задержки экрана

  return 0;
}


Ошибка выглядит следующим образом:
g++.exe -x c++ -c D:\CREATE~1\C__~1\MAIL~1.CPP -o D:\CREATE~1\C__~1\MAIL~1.o  -Wall -fpermissive 
D:\CREATE~1\C__~1\MAIL~1.CPP:7: `struct WSADATA ws' redeclared as different kind of symbol
..\lib\gcc-lib\i386-mingw32\2.95.2\..\..\..\..\include\iostream.h:39: previous declaration of `class istream & ws(istream &)'
Failure

Как я понял ошибка связана с пространством имен, пересекаются имена?

Автор: Cheloveck 23.8.2012, 18:56
Цитата(Luchi @  23.8.2012,  19:48 Найти цитируемый пост)
Как я понял ошибка связана с пространством имен, пересекаются имена? 

У тебя две глобальные переменные с одинаковыми именами. Глобальные переменные -- зло, избегай их всегда, если это возможно. Если не возможно, подумай, как можно переделать и избежать их.


Цитата(Luchi @  23.8.2012,  19:48 Найти цитируемый пост)
Спасибо Cheloveck за ссылку, как поставить тебе + за ответ?

Набрать 100 сообщений, вернуться в эту тему и поставить плюс smile

Автор: feodorv 23.8.2012, 23:00
Цитата(Luchi @  23.8.2012,  19:48 Найти цитируемый пост)
 cin >> str; //ввожу текст письма
  cstr = new char [str.size()+1]; //заполняю буфер текстом письма
  
  //текст письма
  strcpy(cstr, str.c_str()); //отправляю текст письма, здесь нужно подставить значение со строковой переменной!!!
  strcat(cstr,"\n");
  send(s,text,strlen(text),0);
  printf("send - %s", text);

Опять-таки, копирование идёт в cstr, а в сеть уходит text.
Можно вообще отказаться от копирования, посылать непосредственно str.c_str()...

Хуже того, для cstr выделено str.size()+1 байт (этого хватит на собственно текст письма и завершающий '\0'), но затем добавляется ещё один символ: strcat(cstr,"\n"), места для которого уже нет. При определённых условиях strcat может вызвать крах программы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)