Почему указатель на элемент в c-строке не возвращает только элемент?

Я пытаюсь понять, как здесь работают указатели. findTheChar функция просматривает str для персонажа chr, Если chr найден, он возвращает указатель на str где персонаж был впервые найден, в противном случае nullptr (не найдено). У меня вопрос, почему функция распечатывает "llo" вместо "l"? в то время как код, который я написал в main вернуть "e" вместо "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 ответов

Решение
cout << findTheChar("hello", 'l') << endl; //returns llo

Тип возврата findTheChar является const char *, Когда вы пытаетесь распечатать const char * с std::cout это напечатало бы массив символов, указанный адресом до окончания \0 характер

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

Если вам нужен только один символ, разыменуйте адрес (если он не нулевой). Если вы хотите напечатать обратный адрес, вы можете ввести его void *,

в то время как код, который я написал в main, возвращает "e" вместо "ello"

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

Здесь вы явно разыменовываете ptr как *ptr и таким образом вы печатаете char и не const char *,

Поскольку вы используете C++, вам будет лучше с std::string и итераторы.

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

C-строка - это символьный буфер, который заканчивается '\0' персонаж. Передача их включает в себя просто передачу указателя на первый элемент.

Все библиотечные процедуры знают, что они могут читать символы, начиная с адреса, который им дан, до тех пор, пока они не достигнут '\0', Так как это operator<< за std::cout разработан, он предполагает, что вы передаете ему начальный адрес C-строки. Это контракт.

Если вы хотите напечатать один символ, вам нужно разыменовать этот указатель.

Мой вопрос: почему функция выводит "llo" вместо "l"?

Потому что вы спрашиваете, когда вы печатаете, что возвращает функция.

Возвращаемое значение вашей функции - строка: const char*,

В следствии, cout начнет печатать строку, начиная с того места, куда указывает указатель (char), пока он не встретит нулевой C-string-terminator ('\0').

Если вам нужен только символ, вы должны разыменовать возвращенный указатель на этапе печати, например:

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

Кстати, независимо от вашего вопроса, вы скомпилировали свой код с включенными предупреждениями (например, используя Wall а также Wextra флаги)?

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++;
             ^~~

Это происходит из этой части:

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

Указатель типа char* указывает на место в памяти, а содержимое интерпретируется как один символ. Так что если вы напишите

char* x = "Hallo";

х указывает на "Н". Если ты пишешь

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

оператор вывода std::cout вызывается с одним символом.

Но если вы напишите

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

у вас есть особый случай, когда оператор вывода std::ostream интерпретирует char* как указатель на C-подобную строку, которая заканчивается нулем. Так х указывает на один символ, но оператор ostream для char* интерпретирует это как указатель на первый символ строки.

Верните *str и измените тип возвращаемого значения функции. Это должно работать просто отлично.

Другие вопросы по тегам