String class and pointers

Can someone show me, or give me a link on how to use pointers with the string class? I've got a small program that i made a while back that uses c-strings and I want to 'upgrade' it to use the string class instead but i'm having trouble passing strings to a function. All i'm looking for is some examples to learn from and adapt to my program.
std::string::c_str

example:

1
2
3
4
5
6
7
8
9
10
11
12
//  an example of functions that take a string
void func_str(std::string v);             // notice, by value is okay
void func_refstr(const std::string& v);   // by const ref is okay too
void func_cstr(const char* v);            // by 'C-string' (ie: char array)

// how to call functions with a std::string
std::string mystring = "This is a string";

func_str( mystring );     // by value -- okay
func_refstr( mystring );  // same syntax

func_cstr( mystring.c_str() );  // need to "convert" to a c-string 


string::c_str can be used to work with any function that takes a const char* as its 'string' parameter.

Also note that passing a string by value does not necessarily involve a full copy of the string, and therefore is inexpensive to do. Passing by const reference is another option if you want to avoid passing by value.
Ah thankyou. I was trying to do it wth pointers like you would a c-string. e.g. ptr = str; so it would point to the first element in the string. Clearly i was wrong... :(

How would you use string pointers then? e.g. string *ptr; << which was what i was trying.
A pointer to a string works just like a pointer to anything else:

1
2
3
4
5
6
string obj;
string* ptr = &obj;  // point to one object

string array[5];
string* arptr = array;  // point to an array of strings
string* arptr2 = &array[0];  // alternative way to do exact same thing 


ptr = str; works with C-style strings because C-style strings are not really strings, they're arrays. By doing that you're simply pointing to the start of an array (as illustrated above by the 'arptr = array' line)

Although -- you generally don't need to use string pointers in code. So if you're considering this I'd suggest rethinking what you're doing.

Note that a string* pointer points to a string object. It does not point to the individual character data within a string.
Ok, yeah thats cleared up some blind spots for me. One question relating c-strings though. As i said before the original program i created used c-strings and i passed a user-inputted-string to a function via a pointer like so:

1
2
3
char *ptr;
ptr = str;
reverse(ptr, str);


Now due to working through the book I'm using i know that you can pass strings to functions like this but can you explain how? If ptr = str; means that the pointer 'ptr' is pointing to the 1st element in the 'str' array, how does the entire array eventually get passed to the function to be used? Because entire arrays cannot be passed at one time so i'm slightly confused.
Your question isn't clear to me. What is str in your example? If ptr == str, you are passing the same thing twice to the reverse function.

As far as arrays go, all arrays are passed to functions by passing the pointer to the first element. The receiving function has a pointer which can be incremented to iterate through the array. are you simply trying to leave the reverse function as is even though the other parts of the program use std::string?
Sorry, wrote without thinking. When i said
i know that you can pass strings to functions like this
i actually meant c-strings - a char array. 'str' is actually char array[80];

This is referring to the old program that didn't use the string class. Ask if you want me to post the code to clear up my question further.
how does the entire array eventually get passed to the function to be used?


Well technically you're not passing the entire array. What actually happens is a bit of pointer math.

First, let's step back and look at what an array is. An array is simply a group of variables that are stored one after the other.

 
int foo[5];  // has 5 'int's, stored sequentially 


Accessing the individual variables in that array is known as "indexing". You provide an index which indicates which variable from the group you want. C/C++ provides a very simple way to do this using the [] operator:

 
cout << foo[1];  // prints the second 'int' in the array (index 1) 


Now what is really going on with indexing is, the index is getting added to the start of the pointer, which gives you a pointer to the individual variable you want. Consider the following code:

1
2
3
int* ptr = foo; // point to start of the array
ptr += 2;  // add 2 to the pointer (this moves the pointer forward 2 'int's)
if(ptr == &foo[2])


The if statement here will come back as true, because by adding 2, 'ptr' now points to index 2 of the array. Realizing this... you realize that the [] operator is just a shortcut for pointer math:

 
foo[x]  



So "passing an array" to a function can be accomplished by passing a pointer to the first element, because elements after the first can be "found" with pointer math.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void func(int* ptr)
{
  ptr[2] = 10;
}

int main()
{
  int foo[5] = {1,2,3,4,5};
  func( foo );

  int i;
  for(i = 0; i < 5; ++i)
    cout << foo[i] << ", ";

  return 0;
}


This code would output "1, 2, 10, 4, 5, " -- because when we passed the foo pointer to our func, it changed foo[2].

char arrays work the same way. But with chars instead of ints. Functions can read the entire string as long as they know where the string starts.
I think it is a good idea to post the code that you are trying to upgrade. It could be a slimmed version provided that it compiles. Just show us a main with one or two of the functions that you are upgrading. Provide the whole thing if it is pretty compact. If you are trying to upgrade to use strings, I am unclear on why you are focusing on passing pointers to functions. I would think that you'd be passing string objects by value or by reference.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cstdlib>
using namespace std;

void reverse(char *ptr, int cnt);

int main()
{
    int cnt;
    char str[80];
    char *ptr;
    
    cout << "Please enter a string: ";
    gets(str);
    
    ptr = str;
    

    cnt = strlen(str);
    
    reverse(ptr, cnt); // Here is where i don't fully understand. Why doesn't it only send str[0] instead of the entire array, or am i getting confused?
    
    cin.get();
    return 0;
}

void reverse(char *ptr, int cnt)
{
        if(cnt<=0) 
         {
           cout << "\n\nNo characters left";
           return;
         }
        else
         {
           cnt--;
           cout << ptr[cnt];
           reverse(ptr, cnt);
           return;
         }
}


Please don't say about the code itself lol... i know functions like 'gets()' shouldn't be used etc but at the time i didn't know hence the upgrade now :)
Also i wanted to make a string reversing program and i had just learn recurrsion so i thought i'd throw that in.

@Disch ... thanks for the explanations you have given.

@kempfighter ... I have now changed the code to pass string objects by reference but I though that my previous code would work if i more or less changed the char arrays/pointers for string objects/pointers and a few others things (str.length(), getline()) etc... clearly I know less than i thought as this didn't work and this was where the whole problem started.

anyway if you look at the comment in my code thats where i am getting confused.
Why doesn't it only send str[0] instead of the entire array, or am i getting confused?


Because the function takes a pointer not a character. What you are passing is &str[0] or a pointer to the first element of the character array. Why would you want to only pass one character? You have to pass the entire string for the reverse function to work.

I've said this before and I'll say it again. You'd be better off using std::reverse which is a template algorithm and works for any container including but not limited to std::string. Instead of reinventing the wheel you could spend more time worrying about implementing your program's requirements. In fact, std::reverse would accept pointers to elements of a character array as well as iterators to a std::string object.
kempofighter i think you're misunderstanding why i'm getting confused.

I understand that i am passing &str[0], but what i dont understand is how &str[1], &str[2], &str[3] etc get to the function when I have only called the function with the pointer pointing to the first element of the array as the argument.

So if the user inputs "hello", the pointer ptr is pointing to 'h' right? So how does 'e', 'l', 'l', 'o' and '\0' get passed to the function when ptr is only pointing at 'h'?
I don't think he's looking for a way to reverse a string.

I think he's looking for an explanation as to WHY things work the way they do (ie: he's wanting to understand something -- not trying to make something work.)

I don't know how to explain it any better than I already did. Maybe some metaphores:

Let's say you have 500 people standing in a very long line. This line represents memory on a computer. Each person in line represents an int. When you supply a pointer, you're supplying the location of one person in that line. From there, you can easily find the next person in line, and the next, and the next, etc.

When you pass a pointer to an array, you're passing the location of the first element of that array. Further elements can be found simply by looking ahead in memory -- you don't need pointers to each and every element. All the elements are contiguous.


--- EDIT ---
or if you still want the char* example -- same thing as above but replace "int" with "char"
Last edited on
Disch you're corect in your assumptions, i'm looking for the WHY.


When you pass a pointer to an array, you're passing the location of the first element of that array. Further elements can be found simply by looking ahead in memory -- you don't need pointers to each and every element. All the elements are contiguous.


Am i correct in thinking then, that if you have a pointer pointing to the beginning of an array, and you use that pointer as an argument for a function like I have, the function will take the value it points to then looks ahead in memory and continues this cycle until there are no elements left in the array?
Last edited on
yes.

Although the size of the array cannot be determined by the pointer alone. This is why routines like memcpy() and memcmp() require you to give a size which tells them how big the array you're pointing to is.

C-strings get around this by marking the end of the string with a null terminator (0). This way, routines like strcmp() and strcpy() do their thing on each character until they come across the 0, which is when they stop.
C-strings get around this by marking the end of the string with a null terminator (0).


Is that implying that string objects do not contain a null terminator?
replying to the last post only...

no.. string class has a member variable which tells the size of the string. string object doesnt end with a 0.
Topic archived. No new replies allowed.