std::strlen
will give you the length a zero-terminated string, like Loki said. If you want to know how it’s implemented, just look up its implementation.
And Keith has given a short, albeit slightly cryptic, implementation.
But since this is Code Review, let’s go over your code, shall we. We’ll start at the end.
int cpl(const char * c)
{
char * ct = (char*) c;
return cpl(ct);
}
Two things to note:
- Don’t use C-style casts, they hide bugs and are generally strongly discouraged; use C++ casts instead –
const_cast
in this case. - Don’t use
const_cast
unless you really have to, it’s also quite dangerous. In particular, it can easily lead to undefined behaviour. And it’s unnecessary in your case: your code will never actually modify the string so why un-const
it?
In fact, your non-const
variant of the function is unnecessary since there’s an implicit conversion from char*
to char const*
.
Next, what does “cpl
” actually stand for? I have no idea. Use a meaningful name and avoid abbreviations in general.
Now to the main function. I’ll note right at the start that c
is a bad name for the argument. Single-letter names are sometimes OK but c
suggests that the type of the variable is actually char
. If you insist on a single-letter identifier, use s
for “string”.
The return type and the loop variable in your code are int
but they will never be negative. C++ provides a type for this – unsigned int
– which is more suitable here.
Next,
while (ct = *(c+i))
This is cryptic. First off, why do you write *(c+1)
instead of c[i]
? Secondly, while C++ allows assignments inside expressions, and some developers encourage this, it should still be used sparingly. You don’t really need the variable ct
here anyway. It certainly doesn’t help readability (especially not with the once again cryptic name).
Thirdly, C++ is once again forgiving and lets you test a character value for “truthiness”. But just because C++ understands this doesn’t make it understandable. I’d argue that testing a char for truthiness is a nonsensical operation. Use an explicit comparison instead, this is more readable.
The body of the loop contains nothing as much as redundancy. (I’ll note in passing that even with the if
in it, this could be two lines instead of eight, and would be more readable).
The if
is totally redundant. You are testing the same condition as in the loop head, and the condition inside the loop will never be true. You probably missed that because, as I noted above, the loop head is cryptic.
Finally, it’s convention in C++ to use prefix-++
instead of postfix unless necessary. The reason for this is that the prefix operation is sometimes faster, and never slower, than the postfix operation. Now, this is irrelevant in your case since you are incrementing an integer but it may play a role for user-defined types.
Your whole code can be condensed to this simple, readable code:
unsigned int length(char const* s) {
unsigned int i = 0;
while (s[i] != '')
++i;
return i;
}
Some people would instead write it as follows; the result is more or less indistinguishable:
unsigned int length(char const* s) {
unsigned int i = 0;
while (*s++ != '')
++i;
return i;
}
(And note that here, we do need postfix increment.)
Finally, here’s a recursive implementation, just to get a one-liner:
unsigned int length(char const* s) {
return *s == '' ? 0 : 1 + length(s + 1);
}
Note that although this is recursive, and not even tail recursive, modern compilers will very likely recognise this and produce efficient code that doesn’t overflow the stack for long strings (tested on GCC 4.7 with -O2
, works; but doesn’t without optimisations – not surprisingly).
You can’t. Not with 100% accuracy, anyway. The pointer has no length/size but its own. All it does is point to a particular place in memory that holds a char. If that char is part of a string, then you can use strlen
to determine what chars follow the one currently being pointed to, but that doesn’t mean the array in your case is that big.
Basically:
A pointer is not an array, so it doesn’t need to know what the size of the array is. A pointer can point to a single value, so a pointer can exist without there even being an array. It doesn’t even care where the memory it points to is situated (Read only, heap or stack… doesn’t matter). A pointer doesn’t have a length other than itself. A pointer just is…
Consider this:
char beep = 'a';
void alert_user(const char *msg, char *signal); //for some reason
alert_user("Hear my super-awsome noise!", &beep); //passing pointer to single char!
void alert_user(const char *msg, char *signal)
{
printf("%s%cn", msg, *signal);
}
A pointer can be a single char, as well as the beginning, end or middle of an array…
Think of chars as structs. You sometimes allocate a single struct on the heap. That, too, creates a pointer without an array.
Using only a pointer, to determine how big an array it is pointing to is impossible. The closest you can get to it is using calloc
and counting the number of consecutive chars you can find through the pointer. Of course, that doesn’t work once you’ve assigned/reassigned stuff to that array’s keys and it also fails if the memory just outside of the array happens to hold , too. So using this method is unreliable, dangerous and just generally silly. Don’t. Do. It.
Another analogy:
Think of a pointer as a road sign, it points to Town X. The sign doesn’t know what that town looks like, and it doesn’t know or care (or can care) who lives there. It’s job is to tell you where to find Town X. It can only tell you how far that town is, but not how big it is. That information is deemed irrelevant for road-signs. That’s something that you can only find out by looking at the town itself, not at the road-signs that are pointing you in its direction
So, using a pointer the only thing you can do is:
char a_str[] = "hello";//{h,e,l,l,o,}
char *arr_ptr = &a_str[0];
printf("Get length of string -> %dn", strlen(arr_ptr));
But this, of course, only works if the array/string is -terminated.
As an aside:
int length = sizeof(a)/sizeof(char);//sizeof char is guaranteed 1, so sizeof(a) is enough
is actually assigning size_t
(the return type of sizeof
) to an int
, best write:
size_t length = sizeof(a)/sizeof(*a);//best use ptr's type -> good habit
Since size_t
is an unsigned type, if sizeof
returns bigger values, the value of length
might be something you didn’t expect…
mibin 141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
||||
1 |
||||
29.03.2015, 18:26. Показов 65809. Ответов 39 Метки нет (Все метки)
Добрый день! Результат ниже приведенного кода: Код [MAIN] Size of string = 4 [PROC] Size of string = 4
0 |
Жарю без масла 867 / 749 / 225 Регистрация: 13.01.2012 Сообщений: 1,702 |
|
29.03.2015, 18:28 |
2 |
0 |
Prorok2323 173 / 131 / 74 Регистрация: 04.12.2013 Сообщений: 552 |
||||
29.03.2015, 18:28 |
3 |
|||
0 |
940 / 868 / 355 Регистрация: 10.10.2012 Сообщений: 2,706 |
|
29.03.2015, 18:55 |
4 |
sizeof(ch) ch – уазатель, sizeof(ch) возвращает размер указателя. Для 32х-битной платформы – это 4 байта. Добавлено через 2 минуты
std::cout << strlen(ch); Это тоже не размер строки, а количество символов строки без ”, что нужно учитывать, когда под строку выделяется память (не забыть увеличить на единицу то, что выдаёт strlen()).
1 |
mibin 141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
||||
29.03.2015, 19:07 [ТС] |
5 |
|||
Согласен…я наверное привел не совсем корректный пример, хотел сократить .
0 |
🙂 4773 / 3267 / 497 Регистрация: 19.02.2013 Сообщений: 9,046 |
|
29.03.2015, 19:10 |
6 |
Это тоже не размер строки, а количество символов строки без ”, Смотря в каком контексте использовать слово “размер”. Добавлено через 2 минуты
0 |
mibin 141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
||||
29.03.2015, 19:14 [ТС] |
7 |
|||
Да, вот код где я выделил память для buffer.
0 |
lss 940 / 868 / 355 Регистрация: 10.10.2012 Сообщений: 2,706 |
||||
29.03.2015, 19:16 |
8 |
|||
и пытаюсь понять его размер Странное пишешь. Сначала определяешь размер файла, чтобы выделить буфер нужного размера, а потом что-то пытаешься понять.
Добавлено через 1 минуту
1 |
retmas Жарю без масла 867 / 749 / 225 Регистрация: 13.01.2012 Сообщений: 1,702 |
||||
29.03.2015, 19:17 |
9 |
|||
1 |
mibin 141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
||||
29.03.2015, 19:21 [ТС] |
10 |
|||
Суть, в том чтобы передать в функцию некую строку и определить в этой функции размер строки, и совершенно не важно откуда эта строка взялась, была ли загружа из файла или кто-то руками что-то написал. Как мы видели выше, если написать строку руками, то все верно получается, размер определился корректно, но стоило загрузить строку из файла, то размер буфера не может определится. Добавлено через 4 минуты
Результат: Код File size = 79524 [PROC] Size of string = 4 [PROC_2] Size of string = 4
0 |
940 / 868 / 355 Регистрация: 10.10.2012 Сообщений: 2,706 |
|
29.03.2015, 19:21 |
11 |
Суть, в том чтобы передать в функцию некую строку и определить в этой функции размер строки, и совершенно не важно откуда эта строка взялась, была ли загружа из файла или кто-то руками что-то написал. Если это одна строка, то читай её текстовыми методами (функциями), а не бинарными, тогда в конце строки будет ”.
0 |
141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
|
29.03.2015, 19:23 [ТС] |
12 |
Через указатель, на динамически выделенную память, ты размер этой памяти не определишь. Получается char* ch = “Это пример” это не динамически выделенная память?
0 |
Жарю без масла 867 / 749 / 225 Регистрация: 13.01.2012 Сообщений: 1,702 |
|
29.03.2015, 19:23 |
13 |
сдается мне что код не перекомпилен после изменений…
0 |
141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
|
29.03.2015, 19:24 [ТС] |
14 |
Если это одна строка, то читай её текстовыми методами (функциями), а не бинарными, тогда в конце строки будет ”. Это не одна строка, это может быть строка, а может быть файл с изображением или музыкой и т.д. Добавлено через 47 секунд
сдается мне что код не перекомпилен после изменений… Сделал Build all и результат тот же.
0 |
🙂 4773 / 3267 / 497 Регистрация: 19.02.2013 Сообщений: 9,046 |
|
29.03.2015, 19:26 |
15 |
mibin, strlen() возвращает размер сишной строки, а такая строка подразумевает наличие нулевого символа в конце (”). Ты же читаешь файл с картинкой (судя по расширению jpg). Там этих нулей может быть воз и маленькая тележка, и судя по 4ке, которая у тебя выводится этот ноль как раз на 5ой позиции в файле.
1 |
940 / 868 / 355 Регистрация: 10.10.2012 Сообщений: 2,706 |
|
29.03.2015, 19:27 |
16 |
Получается char* ch = “Это пример” это не динамически выделенная память? Нет, это указтелю присваивается адрес строкового литерала, который находится в статической памяти.
1 |
Жарю без масла 867 / 749 / 225 Регистрация: 13.01.2012 Сообщений: 1,702 |
|
29.03.2015, 19:29 |
17 |
“D:\10004.jpg” понятненько… там же не строки как я понимаю и вызов strlen бессмыслен
0 |
940 / 868 / 355 Регистрация: 10.10.2012 Сообщений: 2,706 |
|
29.03.2015, 19:31 |
18 |
f = fopen(“D:\10004.jpg”, “r”); И файл неправильно открываешь. Чтобы fseek(), ftell() правильно работали, нужно для бинарного чтения открывать: “rb”.
1 |
Жарю без масла 867 / 749 / 225 Регистрация: 13.01.2012 Сообщений: 1,702 |
|
29.03.2015, 19:32 |
19 |
Суть, в том чтобы передать в функцию некую строку и определить в этой функции размер строки не выйдет. придется передавать размер. т.к. по сути у тебя не строка, а массив байт
0 |
141 / 84 / 24 Регистрация: 21.10.2009 Сообщений: 429 |
|
29.03.2015, 19:33 [ТС] |
20 |
И файл неправильно открываешь. Чтобы fseek(), ftell() праильно работали, нужно для бинарного чтения открывать: “rb”. ftell верно определил размер файла.
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
29.03.2015, 19:33 |
20 |
This tutorial will discuss about a unique way to get the length of char array in C++.
Get maximum number of elements an array can hold
We can get the length of a char array, just like an another array i.e. fetch the actual size of array using sizeof(arr)
, and divide it with the size of first element in array i.e. sizeof(arr[0])
. It will give us the size of array i.e. the number of maximum characters that this array can hold. For example,
char arr[10] = "sample"; // Get length of a char array size_t len = sizeof(arr) / sizeof(arr[0]); std::cout<< len << std::endl;
Output:
Advertisements
10
As the string in this char array contains only 5 characters. But as the char array can hold 10 characters, therefore it returned the value 10.
Get the number of characters in a char array (string)
We can use the strlen()
function from string.h
header file. It accepts a char array as an argument, and treats the value in char array as a null terminated string. It returns the number of character in string holded by the char array. It excludes the null character at the end of string.
Frequently Asked:
- Convert Char Array to Double or Number in C++
- Get the length of char array in C++
- Check if Char Array contains a char in C++
- Check if a Char Array is Null Terminated in C++
char arr[10] = "sample"; // Get number of characters in a char array size_t count = strlen(arr); std::cout<< count << std::endl;
Output:
6
As there were only six characters in the string, therefore it returned the value 6.
Let’s see the complete example,
#include <iostream> #include <string.h> using namespace std; int main() { char arr[10] = "sample"; // Get length of a char array size_t len = sizeof(arr) / sizeof(arr[0]); std::cout<< len << std::endl; // Get number of characters in a char array size_t count = strlen(arr); std::cout<< count << std::endl; return 0; }
Output :
10 6
Summary
Today we learned about several ways to get the length of char array in C++. Thanks.
- Use the
sizeof
Operator to Find Length of Char Array - Use the
strlen
Function to Find Length of Char Array
This article will explain several methods of getting the length of a char
array in C.
Use the sizeof
Operator to Find Length of Char Array
Array size can be calculated using sizeof
operator regardless of the element data type. Although, when measuring the array’s size, there might be some hideous errors if the inner details are ignored.
Namely, the following example is initializing two arrays named arr
and arr2
with different notations. Then sizes of both arrays are retrieved using the sizeof
operator and printed to the console.
Note that the second array size is equal to 18 bytes even though there are only 17 printed elements. The cause of this issue is hiding in the method of initialization, namely when char
array is initialized using a string literal value, the terminating null byte is also stored as a part of the array. Thus the sizeof
operator includes this byte in the sum of all elements and returns the corresponding result.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void printCharArray(char *arr, size_t len)
{
for (size_t i = 0; i < len; ++i) {
printf("%c, ", arr[i]);
}
printf("n");
}
int main(int argc, char *argv[]){
char arr[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
char arr2[] = "array initialized";
printCharArray(arr, sizeof arr);
printf("size = %lu bytes n", sizeof arr);
printf("n");
printCharArray(arr2, sizeof arr2-1);
printf("size = %lu bytes n", sizeof arr2);
exit(EXIT_SUCCESS);
}
Output:
a, b, c, d, e, f, g,
size = 7 bytes
size = 24 bytes
a, r, r, a, y, , i, n, i, t, i, a, l, i, z, e, d,
size = 18 bytes
size = 17 bytes
Use the strlen
Function to Find Length of Char Array
In some scenarios, char
arrays that were initialized or stored as the null-terminated character strings can be measured for size using the strlen
function, which is part of the C standard library string utilities.
If we run the previous example code with strlen
calculated values, we get different numbers caused by separate issues. The first – arr
object size is printed to be 24 bytes because the strlen
function iterates through a char array until the terminating null byte is encountered. Thus, calling strlen
on arr
object resulted in iterating over both arr
and arr2
, since the first array is not terminated with null byte and the compiler stored the arr2
continuously after it, resulting in a size equal to the sum of both arrays minus 1 (discarding the terminating null byte).
Note that, lengthOfArray
function implemented by us imitates the strlen
counting behavior and results in the same numbers. For the second array object – arr2
, strlen
returned the number of printed characters without the last null byte, which can be useful in some scenarios, but it does not represent the array’s actual size.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void printCharArray(char *arr, size_t len)
{
for (size_t i = 0; i < len; ++i) {
printf("%c, ", arr[i]);
}
printf("n");
}
long lengthOfArray(const char *arr)
{
long size = 0;
while (*arr) {
size += 1;
arr +=1;
}
return size;
}
int main(int argc, char *argv[]){
char arr[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
char arr2[] = "array initialized";
printCharArray(arr, sizeof arr);
printf("size = %lu bytes n", sizeof arr);
printf("size = %lu bytes n", strlen(arr));
printf("size = %lu bytes n", lengthOfArray(arr));
printf("n");
printCharArray(arr2, sizeof arr2-1);
printf("size = %lu bytes n", sizeof arr2);
printf("size = %lu bytes n", strlen(arr2));
printf("size = %lu bytes n", lengthOfArray(arr2));
exit(EXIT_SUCCESS);
}
Output:
a, b, c, d, e, f, g,
size = 7 bytes
size = 24 bytes
size = 24 bytes
a, r, r, a, y, , i, n, i, t, i, a, l, i, z, e, d,
size = 18 bytes
size = 17 bytes
size = 17 bytes