-1

In my program, I am checking whole cstring, if any spaces or punctuation marks are found, just add empty character to that location but the complilor is giving me an error: empty character constant.

Please help me out, in my loop i am checking like this

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

This is where my errors are please correct me.

for eg the word is str,, ing, output should be string.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
user3215228
  • 313
  • 1
  • 3
  • 13

5 Answers5

0

There is no such thing as an empty character.

If you mean a space then change '' to ' ' (with a space in it).

If you mean NUL then change it to '\0'.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Paul
  • 139,544
  • 27
  • 275
  • 264
  • No i dont mean null character , I just want spaces and punctuation marks to be replaced with empty spaces. – user3215228 Feb 13 '14 at 19:01
  • @user3215228 What is an "empty space?" Do you mean the space character? Or do you actually want to *remove* the spaces and punctuations from the string? – Angew is no longer proud of SO Feb 13 '14 at 19:02
  • Do you mean you want to remove those characters? You can't do that by assigning them a value. You need to shift all the characters in the string after that position back one position or something. – Paul Feb 13 '14 at 19:04
  • for eg the word is str,, ing, output should be string – user3215228 Feb 13 '14 at 19:04
  • @user3215228 As paulpro mentioned you want to **remove** the characters. That's a completely different operation, I recommend to use `std::string` for doing this, otherwise copy the rest of the string to the location where you found one of your characters in question. – πάντα ῥεῖ Feb 13 '14 at 19:07
0

Edit: the answer is no longer relevant now that the OP has edited the question. Leaving up for posterity's sake.

If you're wanting to add a null character, use '\0'. If you're wanting to use a different character, using the appropriate character for that. You can't assign it nothing. That's meaningless. That's like saying

int myHexInt = 0x;

or

long long myIndeger = L;

The compiler will error. Put in the value you wanted. In the char case, that's a value from 0 to 255.

m24p
  • 664
  • 4
  • 12
0

UPDATE:

From the edit to OP's question, it's apparent that he/she wanted to trim a string of punctuation and space characters.

As detailed in the flagged possible duplicate, one way is to use 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

Examining your question, replacing spaces with spaces is redundant, so you really need to figure out how to replace punctuation characters with spaces. You can do so using a comparison function (by wrapping std::ispunct) in tandem with std::replace_if from the 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;
}

This outputs:

THisisa test
THisisa test         another
jrd1
  • 10,358
  • 4
  • 34
  • 51
-1

Try this (as you asked for cstring explicitly):

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

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

Well, doing this just in pure language, there are more efficient solutions (have a look at @MichaelPlotke's answer for details).

But as you also explicitly ask for , I'd recommend a solution as follows:

Note you can use the standard c++ algorithms for 'plain' c-style character arrays also. You just have to place your predicate conditions for removal into a small helper functor and use it with the std::remove_if() algorithm:

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

And later use it like:

#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
}

See this compilable and working sample also here.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    I'm not the downvoter, but I can conjecture that it may have something to do with this answer: http://stackoverflow.com/a/6987247/866930. – jrd1 Feb 13 '14 at 19:52
  • What's bad with using strncpy() in [tag:c++]?? I have many situations, where I simply can't afford the conveniences and usage of `std::string ` ... – πάντα ῥεῖ Feb 13 '14 at 20:10
  • Your use of `remove_if` on the C-String is _completely_ wrong as `remove_if` won't remove the characters from a statically allocated array, but only keep the contents in memory unreplaced in the remainder of the string. – jrd1 Feb 13 '14 at 20:33
  • @jrd1 At least [this](http://ideone.com/WV9xQc) works fine?? It doesn't matter if the array is statically allocated or not IMHO (did you mean **const** inputs??)! – πάντα ῥεῖ Feb 13 '14 at 20:37
  • See this: http://stackoverflow.com/a/19139765/866930 – jrd1 Feb 13 '14 at 20:41
  • @jrd1 Good research, but not really relevant for what's asked for here, it's not necessary to _'shrink'_ anything. If it has a fixed size, it has a fixed size, and nothing in my answer will ever act outside the array boundaries at any time ... – πάντα ῥεῖ Feb 13 '14 at 20:44
  • 1
    Hadn't seen `remove_if` before. Seems cool. Still, I find my c-style answer more readable. – Michael Plotke Feb 13 '14 at 20:58
  • @MichaelPlotke Which ever more than a single line code could be **more readable** than `remove_if()`?? The behavior is pretty well defined and you can easily find the [reference for it](http://en.cppreference.com/w/cpp/algorithm/remove). – πάντα ῥεῖ Feb 13 '14 at 21:11
  • @πάνταῥεῖ Admittedly `remove_if` is intuitively named and, as you say, documented. On the other hand, C++ hides things in a way that makes them difficult to truly grasp. What is going on under the hood? Nothing good (based on efficiency comparisons). – Michael Plotke Feb 13 '14 at 21:40
  • @MichaelPlotke Refer to my _other comment_ please ... – πάντα ῥεῖ Feb 13 '14 at 21:42
  • I don't get the downvotes on this answer! May be s.o. can explain or propose improvements?? – πάντα ῥεῖ Feb 14 '14 at 01:59
-1

As I don't like the accepted answer, here's mine:

#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;
}

Which outputs cur = 18; bad = 14; str = string

This has the advantage of being more efficient and more readable, hm, well, in a style I happen to like better (see comments for a lengthy debate / explanation).

Michael Plotke
  • 951
  • 1
  • 15
  • 38
  • Yes, after fixing your code a bit [it works fine](http://ideone.com/FNapEm) and is more efficient (at least vs. the `strncpy()` version). It would be nice to have a confirmation, that the `remove_if()` sample **really is** less efficient as what's given from your answer. – πάντα ῥεῖ Feb 13 '14 at 21:02
  • 1
    @πάνταῥεῖ Yes, your code really truly is **significantly** less efficient. About 16 times less efficient (on my machine). I've just been bench-marking each. Feel free to duplicate my findings. – Michael Plotke Feb 13 '14 at 21:30
  • Good point, then! Could you show a bit more about your benchmarking methods? I'm concerned, since `remove_if()` could be easily implemented in a similar manner as you did, and I usually assume that the standard implementations **are** as efficient as ever possible to cover the applicable use cases. Sadly, that might not be true for _all_ compiler and c++ standard library implementations! – πάντα ῥεῖ Feb 13 '14 at 21:37
  • The bench-mark simply uses [the top answer's method](http://stackoverflow.com/questions/1468596/c-programming-calculate-elapsed-time-in-milliseconds-unix) to time a loop of 10000000 iterations of each method with the string "str,, ing". – Michael Plotke Feb 13 '14 at 21:43
  • To cite the reference of `remove_if`: _'Removing is done by shifting the elements in the range in such a way that elements to be erased are overwritten. '_ That let's me assume a correct implementation should follow your algo ... – πάντα ῥεῖ Feb 13 '14 at 21:46
  • Hmm, I'm currently trying to replicate the benchmark tests as you proposed on [ideone](http://ideone.com/rp5NxA). I seem to got stuck on [this one](http://stackoverflow.com/questions/7760951/gettimeofday-c-inconsistency) :( ... Could you clarify about your toolchain used for the benchmark (I'm afraid it's a toolchain specific problem as mentioned)? (My previous comments emphasis should have been on _shifting_ BTW) – πάντα ῥεῖ Feb 13 '14 at 22:00
  • Linux 3.12.9-2-ARCH #1 SMP PREEMPT Fri Jan 31 10:22:54 CET 2014 x86_64 GNU/Linux | g++ (GCC) 4.8.2 20140206 (prerelease) | While gettimeofday is not the best bench-marking method, it is fairly accurate and simple to implement. I've never had trouble with it... – Michael Plotke Feb 13 '14 at 22:05
  • OK! I've just been able to have your benchmarks compiled on ideone (a bit strange, it's necessary to include `time.h` **and** `sys\time.h` :( ): [**remove_if()** sample](http://ideone.com/rp5NxA), [**c-style while loop** sample](http://ideone.com/GEjP9W), and I must admit your findings about the performance deficiencies seem right. That really makes me concerned about GCC's implementation (I've been using an older version for the samples, but I don't think that matters much). May be a good reason to spawn another question on SO about this! – πάντα ῥεῖ Feb 13 '14 at 22:27
  • This one relaxes me a lot: [std::remove_if GCC implementation isn't efficient?](http://stackoverflow.com/questions/21767415/stdremove-if-gcc-implementation-isnt-efficient#21767545) – πάντα ῥεῖ Feb 13 '14 at 23:13
  • So no real improvements from your solution, sorry ... – πάντα ῥεῖ Feb 13 '14 at 23:22
  • Confirmed. I still like c-style code better, but that's just me. Thanks for taking the time to figure this out. – Michael Plotke Feb 13 '14 at 23:41
  • _'Thanks for taking the time to figure this out.'_ De nada! I was just curios (and a bit concerned) myself ... My usual experience is: **you can't provide better efficiency easily** compared with c++ standard library implementations. But as we see (from my bad former sample) you might use them blatantly wrong :( ... – πάντα ῥεῖ Feb 13 '14 at 23:43
  • 1
    FWIW my C-style solution would be like `char *dst = str, *src = str; while (*src) { if !ispunct(*src) && !isspace(*src) { *dst++ = *src; } ++src; } *dst = 0;`. And that's almost exactly what `remove_if` will do *if* you can get everything properly inlined, except that of course it doesn't know about nul terminated strings. – Steve Jessop Feb 13 '14 at 23:52