2

After programming a little in C I decided to jump right into C++. At first I was pleased with the presence of the string class and being able to treat strings as whole units instead of arrays of characters. But I soon found that the C-style strings had the advantage of letting the program move through it character by character, using pointer arithmetic, and carry out a desired logical operation.

I have now found myself in a situation that requires this but the compiler tells me it is unable to convert from type string to the C-style strings. So I was wondering, is there a way to use pointer arithmetic to reference single characters or to pass arguments to a function as the address of the first character while still using the string class without having to create arrays of characters or do I just want to have my cake and eat it too?

3
  • there's char *string::c_str() const Commented Feb 26, 2011 at 21:58
  • 2
    You can do foo = string('hello'); cout << foo[2]; (prints l). Commented Feb 26, 2011 at 21:58
  • 1
    I think @The Communist Duck's comment is what the OP had in mind: looking at individual characters in the string and possibly mutating them, which c_str() doesn't allow. You might want to post that as an answer. Commented Feb 26, 2011 at 22:00

2 Answers 2

4

string characters can be accessed by index, pointers, and through the use of iterators.

if you wanted to use iterators, you could make a function that checks whether a string has a space in it or not:

bool spacecheck(const string& s)
{
    string::const_iterator iter = s.begin();
    while(iter != s.end()){
        if (isspace(*iter))
            return true;
        else
            ++iter;
    }
}

At the beginning of the function, I initialized an iterator to the beginning of the string s by using the .begin() function, which in this case returns an iterator to the first character in a string. In the while function, the condition is that iter != s.end(). In this case end() returns in iterator referring to the element after the last character of the string. In the body, (*iter), which is the value pointed to by iter, is sent to the function isspace(), which checks if a character is a space. If it fails, iter is incremented, which makes iter point to the next element of the string.

I am learning c++ myself and by writing all of this stuff out it has helped my own understanding some. I hope I did not offend you if this all seemed very simple to you, I was just trying to be concise.

I am currently learning from Accelerated c++ and I could not recommend it highly enough!

Sign up to request clarification or add additional context in comments.

5 Comments

Why do you hate for loops? It can be much cleaner with a for loop: for (string::const_iterator iter = s.begin(); iter != s.end(); ++iter) { if (isspace(*iter)) return true; }
You are totally right Tim. I actually like for loops, I don't know why I didn't use one there. I guess I was trying to break everything down mentally.
+1 for iterators, which is really the "C++ way" to do it. Of course, you should probably use the existing find() for this specific case, but it's valuable as an example.
Nothing to do with the question, but remember to convert a character to unsigned char before passing it to isspace. It's invalid to pass a negative value (other than EOF) to isspace even if char is signed on the implementation. C++ introduces two-parameter std::isspace that avoids this, since it actually takes a char as parameter rather than what C-style isspace does, which is take an int that is either the unsigned char value of a character or else EOF.
No, quite the contrary. It made things a lot easier. Most people just post code and expect you to automatically understand it but with your example it took a lot less effort especially so thanks a lot and I think I'll look into getting Accelerated C++.
4

You can use &your_string[0] to get a pointer to the initial character in the string. You can also use your_string.begin() to get an iterator into the string that you can treat almost like a pointer (dereference it, do arithmetic on it, etc.)

You might be better off telling us more about what you're trying to accomplish though. Chances are pretty good that there's a better way to do it than with a pointer.

Edit: For something like counting the number of vowels in a string, you almost certainly want to use an algorithm -- in this case, std::count_if is probably the most suitable:

struct is_vowel {
    bool operator()(char ch) { 
        static const char vowels[] = "aeiouAEIOU";
        return strchr(vowels, ch) != NULL;
    }
};

int vowels = std::count_if(my_string.begin(), my_string.end(), is_vowel());

We're still using begin(), but not doing any pointer(-like) arithmetic on it.

4 Comments

Is std::string memory guaranteed to be contiguous (like std::vector since C++03)?
@FredOverflow: Theoretically no, but it will be in C++0x, largely because nobody on the committee knew of a conforming implementation where it wasn't contiguous (and given that it's going to be guaranteed soon, I can't imagine anybody doing a non-contiguous implementation now).
Since am still learning C++, it was an exercise to count the number of vowels in a string. I think using the begin() function will do. Thanks for your help.
Wow that's a lot better than the 20 lines or so of code that I wrote to implement the algorithm that even involved the use of a very large switch statement. But it looks like I'll have to learn more about iterators. They are still very new and up until this post unknown to me. Thanks again. You probably just saved me days of poring through volumes of C++ literature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.