2012-01-09 4 views
2

Я знаю, что могу это сделать str.c_str(), , но я не хочу, чтобы символ был постоянным. Я хочу char, чтобы я мог внести некоторые изменения.преобразование строки в char

char* removeDup(char *s) 
{ 


     int len = strlen(s); 
     int p,q, idx = -1; 
    for(p = 0; p< len; p++) 
    { 
    char temp = s[p]; 
    bool flag = true; 
    for(q=0;q<p;q++) 
    { 
     if(s[q] == temp) 
     { 
      flag = false; 
      break; 
     } 
    } 
    if(flag == true) 
    { 
     s[++idx] = temp; 
    } 
} 
    s[++idx] = '\0'; 
    return s; 
} 

Если я вызываю эту функцию, как показано ниже, я получаю ошибки;

string s = "abcde"; 
removeDuplicate(s.c_str()); 

Мне нужно преобразовать это s в char и не const char.

+10

Мое предложение было бы перейти в 'string' вместо и пропустить' полукокса * 'полностью – Default

ответ

5

Чтобы получить исходные данные из std::string Вы можете использовать:

string::data() или string::c_str(), как вернуть const char *.

В любом случае возвращенные данные const char *, потому что память для него распределена в некоторой определенной области реализации только для чтения, которую пользовательская программа не может изменять. Любая попытка изменить возвращенный const char * приведет к Неопределенное поведение.

Таким образом, вы не можете и не должны (через const_cast) изменить возвращаемую строку символов.

Единственный правильный путь для достижения этой цели путем создания нового char*, выделите ее, а затем скопировать в содержимое из const char*:

std::string myString = "blabla"; 
char* myPtr = new char[myString.size() + 1]; 
myString.copy(myPtr, myString.size()); 
myPtr[myString.size()] = '\0'; 
+0

Спасибо, но я не хочу использовать любой дополнительный буфер – Roger

+0

@Roger затем использовать' 'const_cast но это плохая идея. Правильное решение - скопировать данные, как предлагает @Luchian Grigore. –

+1

@Roger хорошо, это невозможно. Приведение стиля C к символу 'char *' приведет к разрыву программы, так как это приведет к неопределенному поведению. Почему бы не использовать функции std: string для достижения того, что вы хотите? –

2

Я бы предложил сделать копию буфера, позвонив функцию, а затем установить исходную строку в новый буфер символов. Что-то вроде:

std::string str("some string"); 
char tmp[str.length() + 1]; 
memset(tmp, 0, sizeof(tmp)); 
copy(str.begin(), str.end(), tmp); 
str = removeDup(tmp); 

Используя константный буфер, возвращаемый c_str() непосредственно и изменение его рожон. Буфер принадлежит строковому объекту, и вы должны подумать о том, чтобы модифицировать это как нарушение инкапсуляции и при минимальной зависимости от реализации.

+0

Больше, чем разбить инкапсуляцию (которая, вероятно, может уйти), отбрасывание const является гарантированным Undefined Behavior. –

+0

Обратите внимание, что массивы переменной длины являются нестандартным расширением для C++. Если вы хотите переносимость, используйте 'std :: vector '. –

0

Я думаю, что вы хотите, этот метод из строки:

Копировать последовательность символов из строки: http://www.cplusplus.com/reference/string/string/copy/

например. Если у вас есть строка «str», вы можете сделать это:

char buf[str.len()+1] 
str.copy(buf, str.len()) 

//terminate with newline 
buf[str.len() = '\n'] 

Надеюсь, что это поможет.

1

Просто скопируйте его.

string str = "Hello"; 
char * cStr = new char[str.size()]; 
memcpy(cStr, str.c_str(), str.size()); 
+0

И не забудьте удалить динамический массив, когда закончите (или еще лучше используйте 'std :: vector '). Кроме того, похоже, что функция зла в вопросе требует строки с нулевым завершением, поэтому используйте 'str.size() + 1' для включения терминатора. –

1

Единственный способ законно вносить изменения в std::string через это функция-членов (в том числе путей доступа, они косвенно предоставляют).Таким образом, вы должны переписать removeDup принять std::string::iterator в качестве аргументов, что-то вроде:.

std::string 
removeDup(std::string& original) 
{ 
    std::string::iterator current = original.begin(); 
    std::string::iterator end = original.end(); 
    while (current != end) { 
     end = std::remove(current + 1, end, *current); 
     ++ current; 
    } 
    original.erase(end, original.end()); 
    return original; 
} 

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

С дизайнерской точки зрения это уродливо; Вы, вероятно, следует пропускать std::string const& и вернуть новый std::string:

std::string 
removeDup(std::string const& original) 
{ 
    std::string results; 
    std::bitset<UCHAR_MAX + 1> alreadySeen; 
    for (std::string::const_iterator current = original.begin(); 
      current != original.end(); 
      ++ current) { 
     if (! alreadySeen.test(static_cast<unsigned char>(*current))) { 
      results += *current; 
      alreadySeen.set(static_cast<unsigned char>(*current)); 
     } 
    } 
    return results; 
} 

Единственный раз, когда вы хотите, чтобы получить char* от std::string должен пройти его унаследованного кода (или C). В таких случаях std::string::c_str() является утвержденным методом ; если функция вы звоните требует char*, затем:

  • если функция реально не изменить строку (это не константные правильно, но это характерно для многих функций C), а затем использовать const_cast на возвращаемое значение std::string::c_str(), в противном случае

  • необходимо выделить локальный буфер, и передать его:

    станд :: вектор localBuffer (s.begin(), s.end()); localBuffer.push_back ('\ 0'); legacyFunction (& localBuffer [0], localBuffer.size());

0

В области «возможно» в противоположность «разумным» вы можете сделать:

std::string str("foo"); 
str = removeDup(std::auto_ptr<char>(strdup(str.c_str()).get()); 

Но переписывания в терминах станд :: строка будет лучше.

+1

Хотя это предполагает, что malloc и new являются синонимами для символов. –

Смежные вопросы