Как узнать длину char c
Перейти к содержимому

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

Как получить реальную и общую длину 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*. как определить размер строки.

Добрый день!
Вопрос вроде бы на первый взгляд простой, но ответ на него найти не получается.
Как определить разме строки?

Результат ниже приведенного кода:

rrrFer
  • 29.03.2015
  • #2

size, который вы пытались вызывать — это не функция, а макрос, который возвращает количество байт, занимаемое типом данных. Т.е. в данном случае видно, что элементы типа данных char* занимают на вашем компьютере 4 байта.

Тип данных char* — это указатель, который является целым неотрицательным числом. Именно поэтому там 4 байта.

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.

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.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *