Arrays in C/C++ are really primitive, and do not have as many built-in capabilities like those in C#/Java. For this reason, there are various wrappers around arrays in the C++ language's standard library.
I get that arrays are just sequential spots in memory until reaching an inevitable /0 but is this really the "best practice" way of doing things in C++? |
(1) There is no "inevitable" '\0' (null character) at the end. If you pass in an array that is not null-terminated, it will go past the end of the array's buffer. Just wanted to make that more clear. It is the caller's responsibility to do so.
(2) Best practice in C++ is to not have to use c-style strings, and to prefer std::strings instead under normal circumstances. See further down.
Yes, working with pointers, in general, is error-prone. Prefer to use the standard library's string type.
I'm not sure what you mean by this. I guess you mean "pointer to array", but that's not how arrays work in C++, unlike C#/Java land. To answer your title question:
How to know a char* is an array? |
You can't.
int func(char arr[]);
and
int func(char* arr);
are the same function signature.
Because an array degrades into a pointer when being passed into a function, there is no way to know whether or not p is truly just a pointer to a single char, or a pointer to a null-terminated char array.
However, the good news is just like how C# has a string type in its library, so does C++.
In C++, a string's length is simply string.length().
1 2 3 4 5 6 7 8 9 10
|
// Example program
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "Hello";
cout << str.length() << '\n';
}
|
If you want to make it clear that char* p should be an array, I would call it "arr" or "str" instead of "p" at the very least, and make the signature look like:
1 2 3 4
|
int count_x(char str[], char x)
{
// ...
}
|
Now, it is expected that char str[] should be a null-terminated since you're saying it's a str (string), despite the actual logic being the same.
Edit:
1 2 3
|
for (; p!=nullptr; ++p)
if (*p==x)
++count;
|
This is wrong. You should not be checking if p is a nullptr in the loop. If p was not a nullptr to begin with, incrementing it will never make it a nullptr.
___________________________________________________
Example:
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
|
#include <iostream>
#include <string>
using std::cout;
// count the number of occurrences of ch in p[]
// p is assumed to point to a zero-terminated array of char (or to nothing)
int count(const char* p, char ch)
{
if (p == nullptr) return 0;
int count = 0;
for (; *p != '\0'; ++p) // loop until we're pointing to a null character
{
if (*p == ch)
++count;
}
return count;
}
int main()
{
// "string literals" are implicitly null-terminated
cout << count(nullptr, 'x') << '\n';
cout << count("hello", 'l') << '\n';
char arr[] = "mississippi";
cout << count(arr, 's') << '\n';
// individual characters that form an array are not implicitly null-terminated
char arr2[] = { 'a', 'b', 'c', 'd', '\0' };
cout << count(arr2, 'f') << '\n';
}
|
Note that my signature is
const char*. "const" means "read only". This means "pointer to const (read-only) char", which is what the signature needs to be if you ever pass in string literals to the function, because you cannot modify string literals.