[英]Why do we need a pointer here
我是 C++ 的新手,在浏览指针时我不太明白为什么我需要在下面的while
循环条件检查中使用*p
。
这是一个非常简单的函数,用于计算数组中字符x
的出现次数,调用示例如下面的main()
函数。 我们在这里假设p
将指向一个字符数组。 纯粹为了演示。
int count(char* p, char x) {
int count = 0;
while (*p != NULL) { // why *p requried here if p is already a pointer?
if (x == *p) count++;
p++;
}
return count;
}
int main(){
char a[5] = {'a','a','c','a',NULL};
char* p = a;
std::cout << count(p, 'a') << std::endl;
}
为什么我需要
while (*p != NULL)
由于p
已经是一个指针,我想
while (p != NULL)
应该足够了,但是程序崩溃了。
递增指针将使它指向字符数组中的下一个元素。 递增指针永远不会使其等于空指针或NULL
。
C 字符串以 nul 结尾。 字符串的末尾用值为'\0'
的元素标记。 在 main 中,这是数组的最后一个元素,函数中的循环将在到达最后一个元素时停止。
p
是指向元素的指针。 *p
是元素。
在该条件下使用NULL
具有误导性。 NULL
不应再在 C++ 中使用。 空指针是nullptr
,字符串中的终止符是'\0'
。 尽管如此,该代码仍然有效,因为NULL
恰好等于0
和'\0'
。 很难,它是用于指针,而不是用于char
。
代码可以这样写:
int count(char* p, char x) {
int count = 0;
while (*p != '\0') { // why *p requried here if p is already a pointer?
if (x == *p) count++;
p++;
}
return count;
}
int main(){
char a[5] = {'a','a','c','a','\0'};
std::cout << count(a, 'a') << std::endl;
}
或者更好,使用std::string
和std::count
:
#include <string>
#include <algorith>
int main() {
std::string s{"aaca"};
std::cout << std::count(s.begin(),s.end(),'a');
}
请注意,字符串文字会自动包含终止符。 所以"aaca"
是一个const char[5]
,一个 5 个字符的数组,最后一个是'\0'
。 使用std::string
的细节有点复杂,但s[4]
也是'\0'
。 请注意,这与其他容器形成对比,其中container[container.size()]
是越界和错误的。
p
是指向char
的指针。 因此,如果您检查p
的值,它将是该char
的地址(字符串或数组中的第一个char
)。 因此,无论您指向第一个字符还是最后一个字符,该地址都将是非零的。
在 C 或 C++ 中,字符串传统上以 null 终止,这意味着字符串的结尾由 null 终止符标记,它是值为 0 的单个字符。要检查指针p
指向的char
的值,您需要取消引用它。 取消引用是通过在表达式前加上*
来完成的。 在这种情况下,我们提取p
指向的值而不是p
指向的地址。
你基本上有一个char
数组,作为一个例子,它在内存中可能看起来像这样:
地址 | ASCII 值 | 价值 |
---|---|---|
1000 | 97 (0x61) | 一种 |
1001 | 97 (0x61) | 一种 |
1002 | 99 (0x63) | C |
1003 | 97 (0x61) | 一种 |
1004 | 0 (0x00) | 无效的 |
首先将指向第一个字符,即地址1000,因此p
的值为1000, *p
的值为97或'a'。 当您递增p
时,它将变为 1001、1002 等,直到达到 1004,其中p
的值为 1004, *p
的值为 0。
如果你写while (p != NULL)
而不是*p
你基本上会检查1004 != 0
是否为真,并且你会继续超过字符串的末尾。
我知道很多(较旧的)教程都是从(裸)指针和“C”样式数组开始的,但它们实际上并不是您应该首先使用的东西。 如果可能,在 C++ 中尝试编写不依赖于指针的解决方案。 要保存文本,请使用 std::string。
#include <string> // stop using char* for text
#include <algorithm> // has the count_if method
#include <iostream>
int count_matching_characters(const std::string& string, char character_to_match)
{
int count{ 0 };
// range based for loop, looping over al characters in the string
for (const char c : string)
{
if (c == character_to_match) count++;
}
return count;
// or using a lambda function and algorithm
/*
return std::count_if(string.begin(), string.end(), [&](const char c)
{
return (character_to_match == c);
});
**/
}
int main()
{
int count = count_matching_characters("hello world", 'l');
std::cout << count;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.