Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > указатель на строку


Автор: LiRienko 10.9.2014, 11:28
Подскажите мне пожалуйста, насколько правильно определять указатель на строку таким образом:

Код

char* pStr = "First string!";
;

Или все-таки лучше определять указатель на строку так
Код

char* pStr = new char [strlen("First string!")];
strcpy(pStr, "First string!");
;

Автор: feodorv 10.9.2014, 11:39
Цитата(LiRienko @  10.9.2014,  12:28 Найти цитируемый пост)
насколько правильно определять указатель на строку таким образом

Все зависит от того, что вы с этой строкой будете делать. Если собираетесь ее менять, то первый вариант никак не подходит:
Цитата(LiRienko @  10.9.2014,  12:28 Найти цитируемый пост)
const char* pStr = "First string!";
Потому что область памяти, которая будет содержать в себе строку "First string!", будет доступна (скорее всего) только для чтения. Запись в неё приведет к краху программы.


Второй вариант:
Цитата(LiRienko @  10.9.2014,  12:28 Найти цитируемый пост)
char* pStr = new char [strlen("First string!")+1];
strcpy(pStr, "First string!");

возможен, но какой-то он корявый. Почему не просто:
Код

char pStr[] = "First string!";

И высвобождать память потом не понадобится. Если потом собираетесь менять содержимое pStr, то всегда нужно помнить, что под строку "First string!" отведено ограниченное число байт.


Если же строка не будет меняться, то первый вариант (с учетом const) вполне подходит.

Автор: kemiisto 10.9.2014, 11:40
Так, ну, судя по new это C++. Со строками в С++ надо работать посредством класса std::string cтандартной библиотеки. Сишечные извращения оставьте сишникам. smile 

Автор: LiRienko 10.9.2014, 11:55
Цитата

Все зависит от того, что вы с этой строкой будете делать.


А если есть допустим такая задача: Написать свою функцию для объединения  двух строк.

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

Наверное тут лучше использовать указатели на строки, передать их в свою функцию. В ней перевыделить память для первой строки, дописать в нее вторую и вернуть указатель на этот новый участок памяти.

Добавлено через 2 минуты и 53 секунды
Вот к примеру 
Код

#include <iostream>
#include <cstring>
using namespace std;
 
char* giveNewMem(char *pstr1, int reqSize);
 
int main()
{
    setlocale(LC_ALL, "rus");
 
    int strSize1 = strlen("строка 1 ") + 1;
    int strSize2 = strlen("+ строка 2") + 1;
    
    char* pStr1 = new char[strSize1];
    strcpy_s(pStr1, strSize1, "строка 1 ");
        
    char* pStr2 = new char[strSize2];
    strcpy_s(pStr2, strSize2, "+ строка 2");
 
    cout << "1)" << pStr1 << endl;
    cout << "2)" << pStr2 << endl << endl;
 
    cout << "pStr1 занимает " << strSize1 << " байт памяти c \\0" << endl;
    cout << "pStr2 занимает " << strSize2 << " байт памяти c \\0" << endl;
 
    // strcat_s(pStr1, strSize1, pStr2); // НЕПРАВИЛЬНО! НЕДОСТАТОЧНО ПАМЯТИ В pStr1
    
    int requiredSize = (strSize1 + strSize2) - 1;
    cout << "\nНеобходимо " << requiredSize << " байт памяти для объединения строк." << endl << endl;
 
    pStr1 = giveNewMem(pStr1, requiredSize); //функция, которая перевыделит память
    
    strcat_s(pStr1, requiredSize, pStr2);
    cout << "pStr1: " << pStr1 << endl << endl;
    
    delete[] pStr1; // освобождаем память, которая была перевыделена в функции для strInFunc 
    delete[] pStr2; // освобождаем память, которая была выделена в main 
 
    return 0;
}
 
char* giveNewMem(char *pstr1, int reqSize)
{
    char* strInFunc = new char[reqSize]; // для копирования строки pstr1 перед удалением памяти
    
    strcpy_s(strInFunc, reqSize, pstr1);
        
    delete [] pstr1; // освобождаем память pstr1
 
    return strInFunc;
}

Автор: math64 10.9.2014, 12:23
Ну тогда стоит добавить функцию для первоначального выделения памяти:
Код

char* giveFirstMem(const char *pstr1, int& reqSize)
{
    reqSize = strlen(pstr1) + 1;
    char* strInFunc = new char[reqSize]; // для копирования строки pstr1
    
    strcpy_s(strInFunc, reqSize, pstr1);
        
    return strInFunc;
}

int strSize1;
char* pStr1 = giveFirstMem("строка 1 ", strSize1);

Но лучше пользоваться std::string, как советовал kemiisto, QString если пользуете Qt и т.п.

Автор: feodorv 10.9.2014, 12:38
Цитата(LiRienko @  10.9.2014,  12:55 Найти цитируемый пост)
    int strSize1 = strlen("строка 1 ") + 1;
    int strSize2 = strlen("+ строка 2") + 1;
    
    char* pStr1 = new char[strSize1];
    strcpy_s(pStr1, strSize1, "строка 1 ");
        
    char* pStr2 = new char[strSize2];
    strcpy_s(pStr2, strSize2, "+ строка 2");

Честно говоря, я в таком коде смысла не вижу. Вам даже приходится дважды упоминать один и тот же текст строк.


В приведенном коде Вы первоначальные строки не меняете. Соответственно, можно позволить себе:
Код

const char *pStr1 = "строка 1 ";
const char *pStr2 = "+ строка 2";
char *cStr = concatenatetwo( pStr1, pStr2);



Цитата(LiRienko @  10.9.2014,  12:55 Найти цитируемый пост)
В ней перевыделить память для первой строки, дописать в нее вторую и вернуть указатель на этот новый участок памяти.

Это лишние телодвижения, которые вдобавок предполагают, что у Вас строки аллоцированные. А если нет? Я теперь не могу делать так:
Код
concatenatetwo( "Output: ", string);
??? За что?)))


Самое простое решение:
Код

char *concatenatetwo( const char *pStr1, const char *pstr2)
{
  size_t len1 = strlen(pStr1);
  size_t len = len1 + strlen(pstr2) + 1;
  char *cStr = new char[len];
  strcpy( cStr, pStr1);
  strcpy( &cStr[len1], pStr2);
  return cStr;
}

Здесь есть, конечно, что пооптимизировать и добавить, но идея, мне кажется, ясна.

Автор: LiRienko 10.9.2014, 14:44
Спасибо всем за участие в этом обсуждении. Главное, что мне стало понятно - это то, что ничего страшного в указателях на строковую константу нет
 
Код

const char *pStr1 = "строка 1 ";
const char *pStr2 = "+ строка 2";


 и их можно спокойно применять в программе )))

А чтобы объединить такие строки, лучше объявить отдельный указатель и присвоить ему значение (адрес), которое вернет функция, объединяющая две строки.  smile 


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