Почему указатель на элемент в 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 и измените тип возвращаемого значения функции. Это должно работать просто отлично.