4

I'm trying to understand how pointers work here. The findTheChar function searches through str for the character chr. If the chr is found, it returns a pointer into str where the character was first found, otherwise nullptr (not found). My question is why does the function print out "llo" instead of "l"? while the code I wrote in main return an "e" instead of "ello"?

#include <iostream>
using namespace std;

const char* findTheChar(const char* str, char chr)
{
    while (*str != 0)
    {
        if (*str == chr)
            return str;
        str++;
    }
    return nullptr;
}

int main()
{
    char x[6] = "hello";
    char* ptr = x;
    while (*ptr != 0)
    {
        if (*ptr == x[1])
            cout << *ptr << endl; //returns e
            ptr++;
    }
    cout << findTheChar("hello", 'l') << endl; // returns llo
}

5 Answers 5

5

A C-string is a character buffer that is terminated by a '\0' character. Passing them around involves just passing a pointer to the first element.

All the library routines know that they may read characters starting at the address they are given, until they reach '\0'. Since that's how operator<< for std::cout is designed, it assumes you pass it the starting address of a C-string. That's the contract.

If you want to print a single character, you'll need to dereference that pointer.

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

Comments

3
cout << findTheChar("hello", 'l') << endl; //returns llo

Return type of findTheChar is const char *. When you try to print a const char * with std::cout it would print the character array pointed by the address upto terminating \0 character.

str -> +---+---+---+---+---+---+
       | h | e | l | l | o | \0|
       +---+---+---+---+---+---+
                 ^
                 |
         findTheChar(str, 'l')

If you want just one character, dereference the address (If it is not null). If you want to print the return address, you can typecast it to void *.

while the code i wrote in main return an "e" instead of "ello"

cout << *ptr << endl; //returns e

Here you are explicitly dereferencing the ptr as *ptr and thus you are printing a char and not const char *.

As you are using C++, you would be better with std::string and iterators.

// Returns offset of first occurance if found
// Returns -1 if not found
int findTheChar(const std::string& str, char chr );

Comments

3

My question is why does the function print out "llo" instead of "l"?

Because you are asking it to, when you print what the function returns.

The return value of your function is a string: const char*.

As a result, cout will start printing the string, starting from where the pointer points to (a char), until it meets a null-C-string-terminator ('\0').

If you wanted just the character, you should dereference the returned pointer during the printing phase, like this:

const char* ptr = findTheChar("hello", 'l');
if(ptr)
    cout << *ptr << endl; //prints l
else
    cout << "Character not found" << endl;

BTW, unrelated to your question, did you compile your code with warnings enabled (e.g. by using Wall and Wextra flags)?

In function 'int main()':
21:9: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
         if (*ptr == x[1])
         ^~
23:13: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
             ptr++;
             ^~~

It comes from this part:

if (*ptr == x[1])
        cout << *ptr << endl; //returns e
        ptr++;

3 Comments

If you wanted just the character, you should return const char instead. or more simply, you should dereference the returned pointer at the call site; no need to alter the function.
+1, but I'd mention that it has to be checked against NULL before being printed, as if the character isn't found it may segfault the program. It's worth noting that in general it is quite silly to print the dereferenced value - by the findTheChar contract, either you get a null pointer (so you cannot dereference it), or you get the letter you asked for.
@gsamaras TBH, I didn't downvote - there was nothing wrong in your answer to begin with, and the part about the missed warnings is valid and unique to your post; it just missed a few bits to be actually good on the main matter.
2

A pointer of type char* points to a memory location and the content is interpreted as a single character. So if you write

char* x = "Hallo";

x points to 'H'. If you write

std::cout << *x << std::endl;

the output operator of std::cout is called with the single char.

But if you write

std::cout << x << std::endl;

you have the special case, where the output operator of std::ostream interprets the char* as a pointer to a C like string which is null terminated. So x points to a single char but ostream operator for char* interprets this as a pointer to the first character of a string.

2 Comments

Thank you that was very clear. Is this special case specific to just c-strings or is it all types of arrays?
@BnE: Yes, this is special to char pointers. A pointer to e.g. an int will be printed as pointer. That is a relict from old c times where a string is represented as a char array which ends with a '\0'. That convention is not used on other places. A e.g. int array can naturally contain 0 as valid value.
0

Return *str and change the function return type. This should work just fine.

Comments

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.