2014-02-13 1 views
-1

В моей программе я проверяю целую строку cstring, если обнаружены пробелы или знаки препинания, просто добавьте пустой символ в это место, но комплитор дает мне ошибку: empty постоянная символа.Удалить символ из массива, где найдены пробелы и знаки препинания

Пожалуйста, помогите мне, в моем цикле я проверить, как этот

if(ispunct(str1[start])) { 
    str1[start]=''; // << empty character constant. 
} 
if(isspace(str1[start])) { 
    str1[start]=''; // << empty character constant. 
} 

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

например, например: str,, ing, вывод должен быть string.

+3

Что такое «пустой символ»? – Angew

+0

@Angew Удаленный один)) –

+0

@ jrd1 Нет, это не обман (особенно не относительно принятого ответа там)! Нет необходимости в _'shrinking'_ или динамическом изменении размера массива, см. Мой ответ и другие комментарии вниз ... –

ответ

-1

Попробуйте это (как вы просили cstring явно):

char str1[100] = "str,, ing"; 

if(ispunct(str1[start]) || isspace(str1[start])) { 
    strncpy(str1 + start, str1 + start + 1, strlen(str1) - start + 1); 
} 

Ну, делать это только в чистом языке, существуют более эффективные решения (см. ответ @MichaelPlotke).

Но вы явно попросить , я рекомендовал бы решение следующим образом:

Примечание вы можете использовать standard c++ algorithms для «простых» массивов символов C-стиля также. Вы просто должны разместить предикатные условия для удаления в небольшие хелперах функтор и использовать его с std::remove_if() алгоритмом:

struct is_char_category_in_question { 
    bool operator()(const char& c) const; 
}; 

А потом использовать его как:

#include <string> 
#include <algorithm> 
#include <iostream> 
#include <cctype> 
#include <cstring> 

// Best chance to have the predicate elided to be inlined, when writing 
// the functor like this: 
struct is_char_category_in_question { 
    bool operator()(const char& c) const { 
     return std::ispunct(c) || std::isspace(c); 
    } 
}; 

int main() { 
    static char str1[100] = "str,, ing"; 
    size_t size = strlen(str1); 

    // Using std::remove_if() is likely to provide the best balance from perfor- 
    // mance and code size efficiency you can expect from your compiler 
    // implementation. 
    std::remove_if(&str1[0], &str1[size + 1], is_char_category_in_question()); 

    // Regarding specification of the range definitions end of the above state- 
    // ment, note we have to add 1 to the strlen() calculated size, to catch the 
    // closing `\0` character of the c-style string being copied correctly and 
    // terminate the result as well! 

    std::cout << str1 << endl; // Prints: string 
} 

Смотрите этот компилируемый и рабочий образец также here.

+1

Я не являюсь нисходящим, но могу предположить, что он может иметь какое-то отношение к этому ответу: http://stackoverflow.com/a/ 6987247/866930. – jrd1

+0

Что плохого с использованием strncpy() в [tag: C++] ?? У меня много ситуаций, когда я просто не могу позволить себе удобства и использование 'std :: string' ... –

+0

@ jrd1 ОК, исправлено! –

0

Нет такой вещи, как пустой символ.

Если вы имеете в виду пробел, тогда измените '' на ' ' (с пробелом в нем).

Если вы имеете в виду NUL, тогда измените его на '\0'.

+0

Нет, я не имею в виду нулевой символ, я просто хочу, чтобы пробелы и знаки препинания заменялись пустым пространством. – user3215228

+0

@ user3215228 Что такое «пустое пространство»? Вы имеете в виду космический персонаж? Или вы действительно хотите * удалить * пробелы и пунктуации из строки? – Angew

+0

Вы хотите удалить эти символы? Вы не можете этого сделать, назначив им значение. Вам нужно перенести все символы в строке после этой позиции назад на одну позицию или что-то в этом роде. – Paulpro

0

Редактировать: ответ больше не уместен сейчас, когда ОП отредактировал вопрос. Оставим для потомства.

Если вы хотите добавить нулевой символ, используйте '\ 0'. Если вы хотите использовать другой символ, используйте для этого соответствующий символ. Вы не можете назначить ему ничего. Это бессмысленно. Это, как говорят

int myHexInt = 0x; 

или

long long myIndeger = L; 

компилятор выдаст ошибку. Поместите нужное значение. В случае полукокса, это значение от 0 до 255.

+0

Нет, я не имею в виду нулевой символ, я просто хочу, чтобы пробелы и знаки препинания заменялись пустым пространством. – user3215228

+0

Хорошо, тогда используйте космический символ. 'str1 [start] = '';' Просто не пытайтесь присваивать символ ни к чему. Это как сказать «int x =;» и надеется, что он скомпилируется. – m24p

+0

@ m24p OP хочет заменить космический символ пробелом char? –

0

UPDATE:

С правкой вопрос OP, это очевидно, что он/она хочет подрезать строка знаков и символов пробела.

Как подробно описано в помеченном возможном дубликате, один из способов заключается в использовании remove_copy_if:

string test = "THisisa test;;';';';"; 
string temp, finalresult; 

remove_copy_if(test.begin(), test.end(), std::back_inserter(temp), ptr_fun<int, int>(&ispunct)); 
remove_copy_if(temp.begin(), temp.end(), std::back_inserter(finalresult), ptr_fun<int, int>(&isspace)); 

ORIGINAL

Рассматривая свой вопрос, заменяющих пространств с пробелами избыточны, так что вам действительно нужно понять out как заменить знаки препинания пробелами. Вы можете сделать это, используя функцию сравнения (путем оборачивания std::ispunct) в тандеме с std::replace_if из STL:

#include <string> 
#include <algorithm> 
#include <iostream> 
#include <cctype> 
using namespace std; 

bool is_punct(const char& c) { 
    return ispunct(c); 
} 

int main() { 
    string test = "THisisa test;;';';';"; 
    char test2[] = "THisisa test;;';';'; another"; 

    size_t size = sizeof(test2)/sizeof(test2[0]); 

    replace_if(test.begin(), test.end(), is_punct, ' ');//for C++ strings 
    replace_if(&test2[0], &test2[size-1], is_punct, ' ');//for c-strings 

    cout << test << endl; 
    cout << test2 << endl; 
} 

Воспроизводит:

THisisa test 
THisisa test   another 
+0

К нисходящему, было ли что-то, что можно было бы улучшить? Если да, я бы приветствовал любую обратную связь. – jrd1

+0

@ πάνταῥεῖ: Нет проблем. Это честная ошибка: все это происходит. – jrd1

+0

_'To downvoter ..'_ Извините, это была не ошибка: вопрос требует ** удаления ** этих символов, а не замены пробелами ('' \ 0x32'')! Вы бы назвали 'std :: remove_if' ... –

-1

Как мне не нравится принятый ответ, вот мое :

#include <stdio.h> 
#include <string.h> 
#include <cctype> 

int main() { 
    char str[100] = "str,, ing"; 
    int bad = 0; 
    int cur = 0; 
    while (str[cur] != '\0') { 
     if (bad < cur && !ispunct(str[cur]) && !isspace(str[cur])) { 
       str[bad] = str[cur]; 
     } 
     if (ispunct(str[cur]) || isspace(str[cur])) { 
      cur++; 
     } 
     else { 
      cur++; 
      bad++; 
     } 
    } 
    str[bad] = '\0'; 
    fprintf(stdout, "cur = %d; bad = %d; str = %s\n", cur, bad, str); 
    return 0; 
} 

Какие выходы cur = 18; bad = 14; str = string

Это имеет то преимущество, что более эффективный и читаемый, хм, ну, в стиле, которому мне нравится больше (см. Комментарии для длительных дебатов/объяснений).

+0

Да, после исправления кода немного [работает отлично] (http://ideone.com/FNapEm) и более эффективен (по крайней мере, против версии 'strncpy()'). Было бы неплохо получить подтверждение, что 'sample_if()' sample ** действительно менее эффективен, чем то, что указано в вашем ответе. –

+1

@ πάνταῥεῖ Да, ваш код действительно действительно ** значительно менее эффективен. Примерно в 16 раз меньше (на моей машине). Я только что оценил каждую. Не стесняйтесь дублировать мои результаты. –

+0

Хорошая точка, то! Не могли бы вы немного подробнее рассказать о методах бенчмаркинга? Меня беспокоит, так как 'remove_if()' можно было легко реализовать так же, как и вы, и я обычно предполагаю, что стандартные реализации ** являются настолько эффективными, насколько это возможно, для покрытия применимых случаев использования. К сожалению, это может быть неверно для реализаций стандартных библиотек _all_ и C++! –

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

  • Нет связанных вопросов^_^