Как узнать длину char c

от admin

Get Length of Char Array in C

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.

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.

Determining length of a char* string in C++

I was looking to do this with sizeof() and I just gave up. As minimal as I can make it, I was wondering if there was a less crude way of doing the const char * as a convenience. I thought about doing this as a template, but I thought having another bit of generated code every time it is called seemed kinda dumb for me.

Jamal's user avatar

2 Answers 2

While we are at it:

Other notes on your code:

You have these two the wrong way around.
Make the int cpl(const char * c) version do the work. As noted above you are not mutating the object so it provides some slight protection from simple mistakes.

Also you will find the int cpl(char * c) version becomes unnecessary. As the compiler will automatically add const (ness) to parameters for you so you don’t actually need the this version.

Other comments are same as @Konrad Rudolph

Note on the use of const.

If you put const on the right or left is a style thing. Peronally I always put it on the right. As there are a couple of corner cases (with typedef) were it does make a difference and I want to be consistent.

Note: cost always binds to the type on its left . unless it is the left-most part of a type declaration then it binds right. Read type right to left.

Basically str1 and str3 are identical. But the consistency of always thinking that const binds to the left makes it neater in my mind.

One place where it can make a difference is typedefs. This is because the typedef has already formed a type so any external const are applied to the typedef type as a whole thing (not as individual parts).

So two reasons not to put const as the left-most part of the type.

Martin York's user avatar

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.

Two things to note:

  1. Don’t use C-style casts, they hide bugs and are generally strongly discouraged; use C++ casts instead – const_cast in this case.
  2. 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.

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:

Some people would instead write it as follows; the result is more or less indistinguishable:

(And note that here, we do need postfix increment.)

Finally, here’s a recursive implementation, just to get a one-liner:

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).

Как получить реальную и общую длину char * (массив символов)?

Однако я не могу сделать это, чтобы получить длину char * с помощью:

Потому что, я знаю, a здесь указатель, так что length здесь всегда будет 4 (или что-то другое в других системах).

Мой вопрос в том, как я могу впоследствии получить длину char * ? Я знаю, что кто-то может оспорить меня, что вы уже знаете его 10 , потому что вы только что его создали. Я хочу знать это, потому что этот этап определения его длины может пройти долгий путь с момента его создания, и я не хочу возвращаться долго, чтобы проверить это число. Более того, я также хочу знать его реальную длину.

Чтобы быть более конкретным

  • как я могу получить его настоящий length=5 ?
  • как я могу получить его общее количество length=10 ?
Читать:
Ошибок отсутствия страницы в памяти что это

Для следующего примера:

15 ответов

Вы не можете. Во всяком случае, не со 100% точностью. Указатель не имеет длины / размера, кроме своего собственного . Все, что он делает, — это указывает на конкретное место в памяти, в котором хранится символ. Если этот символ является частью строки, то вы можете использовать strlen , чтобы определить, какие символы следуют за тем, на который в данный момент указывает, но это не означает, что массив в вашем случае таков. большой.
По сути:

pointer не является массивом , поэтому ему не нужно знать каков размер массива. Указатель может указывать на одно значение, поэтому указатель может существовать даже без массива. Ему даже все равно, где расположена память, на которую он указывает (только чтение, куча или стек . не имеет значения). Указатель не имеет длины, отличной от себя. Указатель — это просто .
Учти это:

Указатель может быть как одиночным символом, так и началом, концом или серединой массива .
Думайте о символах как о структурах. Иногда вы выделяете одну структуру в куче. Это тоже создает указатель без массива.

Используя только указатель, определить размер массива, на который он указывает, невозможно. Самое близкое к нему — использовать calloc и подсчитывать количество последовательных \ 0 символов, которые вы можете найти с помощью указателя. Конечно, это не сработает после того, как вы назначили / переназначили что-то для ключей этого массива, и это также не сработает, если память только вне массива также содержит \0 . Так что использование этого метода ненадежно, опасно и вообще глупо. Не надо. Делать. Это.

Еще одна аналогия:
Думайте о указателе как о дорожном знаке, он указывает на город X . Знак не знает, как выглядит этот город, и не знает и не заботится (или не заботится) о том, кто там живет. Его работа — сказать вам, где найти Town X . Он может только сказать вам, как далеко этот город, но не насколько он большой. Эта информация не имеет отношения к дорожным знакам. Это то, что вы можете узнать, только посмотрев на сам город, а не на дорожные знаки, указывающие вам в его направлении.

Итак, используя указатель, единственное, что вы можете сделать, это:

Но это, конечно, работает только в том случае, если массив / строка оканчиваются \ 0.

Фактически присваивает size_t (тип возврата sizeof ) int , лучше всего написать:

Поскольку size_t является беззнаковым типом, если sizeof возвращает большие значения, значение length может оказаться неожиданным .

Как получить реальную и общую длину char * (массив char)?

Тем не менее, я не могу сделать так, чтобы получить длину char * от:

потому что я знаю, a вот указатель, такой что length здесь всегда будет 4 (или что-то другое в разных системах).

Мой вопрос заключается в том, как я могу получить длину char * после этого? Я знаю, что кто-то может бросить мне вызов, что вы уже знаете его 10 потому что вы только что создали это. Я хочу знать это, потому что этот шаг получения его длины может пройти долгий путь от его создания, и я не хочу возвращаться далеко назад, чтобы проверить это число. Кроме того, я также хочу знать его реальную длину.

Чтобы быть более конкретным

  • как я могу получить его реально length=5 ?
  • как я могу получить его общее length=10 ?

для следующего примера:

Решение

Ты не можешь Во всяком случае, не со 100% точностью. Указатель не имеет длины / размера, но имеет свои. Все, что он делает, это указывает на определенное место в памяти, которое содержит символ. Если этот символ является частью строки, то вы можете использовать strlen определить, какие символы следуют за указанным в данный момент, но это не означает, что массив в твоем случае такой большой.
В принципе:

указатель это не массив, так что это не необходимость знать, каков размер массива. Указатель может указывать на одно значение, поэтому указатель может существовать, даже не будучи массивом. Его даже не волнует, где находится память, на которую он указывает (только чтение, куча или стек … не имеет значения). Указатель не имеет длины, отличной от себя. Указатель просто …
Учти это:

Указатель может быть одним символом, а также началом, концом или серединой массива …

Думайте о символах как о структурах. Иногда вы выделяете одну структуру в куче. Это также создает указатель без массива.

Используя только указатель, определить, на какой массив он указывает, невозможно. Самое близкое, к которому вы можете добраться, это использование calloc и подсчет количества последовательных символов \ 0, которые вы можете найти через указатель. Конечно, это не сработает, если вы присвоили / переназначили материал для ключей этого массива, и это также даст сбой, если память просто вне массива случается держать \0 , тоже. Поэтому использование этого метода ненадежно, опасно и просто глупо. Не. Делать. Это.

Еще одна аналогия:
Думайте о указателе как о дорожном знаке, он указывает на Город Х. Знак не знает, как выглядит этот город, и не знает и не заботится (или может не заботиться) о том, кто там живет. Это работа, чтобы сказать вам, где найти Город Х. Он может только сказать вам, насколько далеко этот город, но не насколько он большой. Эта информация считается неактуальной для дорожных знаков. Это то, что вы можете узнать, только взглянув на сам город, а не на дорожные знаки, указывающие вам его направление

Итак, используя указатель, вы можете только:

Но это, конечно, работает, только если массив / строка заканчивается \ 0.

В качестве помощника:

на самом деле присваивает size_t (возвращаемый тип sizeof ) для int Лучше всего написать:

поскольку size_t тип без знака, если sizeof возвращает большие значения, значение length может быть что-то, чего ты не ожидал …

Другие решения

Если char * 0-терминатор, вы можете использовать strlen

В противном случае невозможно определить эту информацию.

Есть только два способа:

Если указатель памяти на ваш char * представляет строку C (то есть, она содержит символы, которые имеют 0-байт, чтобы отметить его конец), вы можете использовать strlen(a) ,

В противном случае вам нужно где-то хранить длину. На самом деле указатель указывает только на один char , Но мы можем обращаться с ним так, как будто он указывает на первый элемент массива. Поскольку «длина» этого массива неизвестна, вам нужно где-то хранить эту информацию.

Учитывая только указатель, вы не можете. Вы должны будете держать длину, которую вы прошли new[] или лучше используйте std::vector чтобы следить за длиной, и освободить память, когда вы закончили с ним.

Примечание: этот ответ касается только C ++, но не C.

  • В C ++:

Просто используйте std::vector<char> которые сохраняют (динамический) размер для вас. (Бонус, управление памятью бесплатно).

Или же std::array<char, 10> которые сохраняют (статический) размер.

  • В чистом C:

Создайте структуру для хранения информации, например:

char * a = новый символ [10];

Мой вопрос заключается в том, как я могу получить длину символа *

Это очень просто. �� Достаточно добавить только одно утверждение

Теперь вы можете получить размер выделенного массива

Многие упоминали здесь C стандартную функцию std :: strlen. Но он не возвращает фактический размер массива символов. Возвращает только размер хранимого строкового литерала.

Разница в следующем. если взять в качестве примера фрагмент кода

тогда std :: strlen (a) вернет 5 вместо 6, как в вашем коде.

Таким образом, вывод прост: если вам нужно динамически выделить массив символов, рассмотрите использование класса std::string , Он имеет размер metaof и длину синонима, что позволяет в любой момент получить размер массива.

Это может звучать как Зло ™, и я не проверял его, но как насчет инициализации всех значений в массиве при выделении ‘\0’ а затем с помощью strlen() ? Это даст вам ваш так называемый реальная стоимость так как он перестанет считать на первом ‘\0’ это встречает.

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

Кроме того, для выделенной памяти или Общая память Вы можете использовать следующие функции, если ваша среда предоставляет их:

Вы можете реализовать свой собственный new а также delete функции, а также дополнительный get-size функция:

Кроме того, вы можете переопределить new а также delete операторы аналогичным образом.

Похожие статьи