如何在c#中实现strlen()?

时间:2022-03-18 05:05:55

I was thinking to a solution to calculate length of string in c# without using Length property.

我正在考虑一个解决方案来计算c#中的字符串长度而不使用Length属性。

I thing which I can think of is getting this done is

我能想到的事情就是这样做

Program is in C#

程序在C#中

public static int strlen (string s)  
{   
    string temp = s + '/0';  
    char [] c = temp.ToCharArray();    
    int length = 0;    
    while (c[length]!='/0') length++;  
    length--;  
    return length;  
}

but this is very naive programming, it also uses 1 extra temp variable Can you guys think of better solution than this?

但这是非常天真的编程,它还使用了1个额外的临时变量你能想到更好的解决方案吗?

5 个解决方案

#1


The issue is the way strings are stored in C#. While in some languages it takes computation to figure out how long a string is, in C#, the only way to figure out the length of a string is through its Length property. If you thing about how strings are stored, there is an array of character, and a Length. Now, the strings are not null-terminated, so you need the Length field to know how much of the array you can access before you start reading memory that isn't part of the array. You can hide what you are doing through abstraction though. For example you can call the ToCharArray function, but in order to generate the null-terminated string which you use, it first has to access the Length value to allocated the right amount of memory for the char[] array and copy the right amount of characters. Or you could use a for each (char c in s) length++;

问题是字符串存储在C#中的方式。虽然在某些语言中需要计算来计算字符串的长度,但在C#中,计算字符串长度的唯一方法是通过其Length属性。如果关于字符串的存储方式,则有一个字符数组和一个Length。现在,字符串不是以空值终止的,因此您需要使用“长度”字段来了解在开始读取不属于数组的内存之前可以访问的数组量。您可以通过抽象隐藏您正在做的事情。例如,您可以调用ToCharArray函数,但是为了生成您使用的以null结尾的字符串,它首先必须访问Length值以为char []数组分配适当的内存量并复制正确的数量字符。或者你可以使用每个(char c in s)长度++;

as somebody else suggested. This is another way to hide the fact you are accessing the Length value. In order to iterate over the characters in this way, you must first access the Length value to see how many characters you are iterating over. Whether it does this in a library call, or it compiles it away to a different construct, I am not sure, but the end result is the same.

正如其他人所说的那样。这是隐藏您访问Length值的另一种方法。为了以这种方式迭代字符,您必须首先访问“长度”值以查看要迭代的字符数。无论是在库调用中执行此操作,还是将其编译为不同的构造,我都不确定,但最终结果是相同的。

#2


You can get the length at O(1) speed using unsafe code, since C# strings are prefixed with their length - this is probably what the get_Length function does internally (and thats why you should use the built-in way instead of writing your own):

您可以使用不安全的代码以O(1)速度获得长度,因为C#字符串以其长度为前缀 - 这可能是get_Length函数在内部执行的操作(这就是为什么您应该使用内置方式而不是编写自己的方式):

public static unsafe int strlen(string s) 
{
    if(s == null) {
        // Handle the error here
    }

    int length = 0;

    fixed(char *pStr = s) {
        length = *(((int *)pStr) - 1);
    }

    return length;
}

Or if you prefer more old schoolish approach:

或者,如果您更喜欢更古老的学校方法:

public static unsafe int strlen(string s) 
{
    if(s == null) {
        // Handle the error here
    }

    int length = 0;

    fixed(char *pStr = s) {
        char *pEnd   = pStr;    
        while(*pEnd++ != '\0'); 
        length = (int)((pEnd - pStr) - 1);            
    }

    return length;
}

#3


public static int strlen2 (string s) {
    int length = 0;
    foreach (char c in s) length++;
    return length
}

I am not sure what is the point of doing that though.

我不确定这样做有什么意义。

#4


I think to optimize a bit on Leiz's answer, I would use pre-increment instead of post increment on line 3 to read:

我想要对Leiz的答案进行一些优化,我会在第3行使用预增量而不是后增量来读取:

foreach(char c in s) ++length

Which would squeeze a tiny bit of performance out of it.

这将挤出一点点的性能。

#5


If you want the most efficient way you could try to mimic Microsoft's own String.Length function. Fire up .NET Reflector and load a small sample solution in that calls String.Length. Then you can simply burrow down into the dependencies and even do some disassembling.

如果你想要最有效的方法,你可以尝试模仿微软自己的String.Length函数。启动.NET Reflector并加载一个小样本解决方案,调用String.Length。然后你可以简单地挖掘依赖关系,甚至做一些拆解。

alt text http://i42.tinypic.com/35iwuhy.png

替代文字http://i42.tinypic.com/35iwuhy.png

#1


The issue is the way strings are stored in C#. While in some languages it takes computation to figure out how long a string is, in C#, the only way to figure out the length of a string is through its Length property. If you thing about how strings are stored, there is an array of character, and a Length. Now, the strings are not null-terminated, so you need the Length field to know how much of the array you can access before you start reading memory that isn't part of the array. You can hide what you are doing through abstraction though. For example you can call the ToCharArray function, but in order to generate the null-terminated string which you use, it first has to access the Length value to allocated the right amount of memory for the char[] array and copy the right amount of characters. Or you could use a for each (char c in s) length++;

问题是字符串存储在C#中的方式。虽然在某些语言中需要计算来计算字符串的长度,但在C#中,计算字符串长度的唯一方法是通过其Length属性。如果关于字符串的存储方式,则有一个字符数组和一个Length。现在,字符串不是以空值终止的,因此您需要使用“长度”字段来了解在开始读取不属于数组的内存之前可以访问的数组量。您可以通过抽象隐藏您正在做的事情。例如,您可以调用ToCharArray函数,但是为了生成您使用的以null结尾的字符串,它首先必须访问Length值以为char []数组分配适当的内存量并复制正确的数量字符。或者你可以使用每个(char c in s)长度++;

as somebody else suggested. This is another way to hide the fact you are accessing the Length value. In order to iterate over the characters in this way, you must first access the Length value to see how many characters you are iterating over. Whether it does this in a library call, or it compiles it away to a different construct, I am not sure, but the end result is the same.

正如其他人所说的那样。这是隐藏您访问Length值的另一种方法。为了以这种方式迭代字符,您必须首先访问“长度”值以查看要迭代的字符数。无论是在库调用中执行此操作,还是将其编译为不同的构造,我都不确定,但最终结果是相同的。

#2


You can get the length at O(1) speed using unsafe code, since C# strings are prefixed with their length - this is probably what the get_Length function does internally (and thats why you should use the built-in way instead of writing your own):

您可以使用不安全的代码以O(1)速度获得长度,因为C#字符串以其长度为前缀 - 这可能是get_Length函数在内部执行的操作(这就是为什么您应该使用内置方式而不是编写自己的方式):

public static unsafe int strlen(string s) 
{
    if(s == null) {
        // Handle the error here
    }

    int length = 0;

    fixed(char *pStr = s) {
        length = *(((int *)pStr) - 1);
    }

    return length;
}

Or if you prefer more old schoolish approach:

或者,如果您更喜欢更古老的学校方法:

public static unsafe int strlen(string s) 
{
    if(s == null) {
        // Handle the error here
    }

    int length = 0;

    fixed(char *pStr = s) {
        char *pEnd   = pStr;    
        while(*pEnd++ != '\0'); 
        length = (int)((pEnd - pStr) - 1);            
    }

    return length;
}

#3


public static int strlen2 (string s) {
    int length = 0;
    foreach (char c in s) length++;
    return length
}

I am not sure what is the point of doing that though.

我不确定这样做有什么意义。

#4


I think to optimize a bit on Leiz's answer, I would use pre-increment instead of post increment on line 3 to read:

我想要对Leiz的答案进行一些优化,我会在第3行使用预增量而不是后增量来读取:

foreach(char c in s) ++length

Which would squeeze a tiny bit of performance out of it.

这将挤出一点点的性能。

#5


If you want the most efficient way you could try to mimic Microsoft's own String.Length function. Fire up .NET Reflector and load a small sample solution in that calls String.Length. Then you can simply burrow down into the dependencies and even do some disassembling.

如果你想要最有效的方法,你可以尝试模仿微软自己的String.Length函数。启动.NET Reflector并加载一个小样本解决方案,调用String.Length。然后你可以简单地挖掘依赖关系,甚至做一些拆解。

alt text http://i42.tinypic.com/35iwuhy.png

替代文字http://i42.tinypic.com/35iwuhy.png