How Char By Char Traversal is possible? - c#

When i apply IEnumerator and perform MoverNext() will it traverse like
C-Style 'a' 'p' 'p' 'l' 'e' '\o' until it finds null character?I thought it would return the entire string.How does the enumeration work here?
string ar = "apple";
IEnumerator enu = ar.GetEnumerator();
while (enu.MoveNext())
{
Console.WriteLine(enu.Current);
}
I get output as
a
p
p
l
e

Strings are not null-terminated in C#. Or, rather, the fact that strings are null-terminated is an implementation detail that is hidden from the user. The string "apple" has five characters, not six. You ask to see those five characters, we show all of them to you. There is no sixth null character.

The null character is not an inherent part of a CLR / .Net string and hence will not show up in the enumeration. Enumerating a string will return the characters of the string in order

An enumerator returns each element of the underlying container per iteration (MoveNext() call). In this case, your container is a string and its element type is char, so the enumerator will return a character per each iteration.
Also, the length of the string is known by the string type, which may be leveraged by the enumerator implementation to know when to terminate its traversal.

C# strings are stored like COM strings, a length field and a list of unicode chars. Therefore there's no need of a terminator. It uses a bit more memory (2 bytes more) but the strings themselves can hold nulls without any issues.
Another way to parse strings that uses the same functionality as your code only is more C#-like is:
string s="...";
foreach(char c in s)
Console.WriteLine(c);

Related

Wrong result when Split a string when the given characters are not found

When I tried to split a string value of some text here with ++. I expected the result to be an empty list. Since the ++ is not found in the string some text here, the result of a Count on the List should be 0.
However, the result I get is 1 (when I Count on the List).
How am I able to determine if the string has no ++ in it ? (a Count did not work)
List<string> l = value.Split("++").ToList();
The observed behavior is by design. If delimiter is not found a collection with a single item is returned. As documentation states:
If this instance does not contain any of the characters in separator, the returned array consists of a single element that contains this instance.
If you want to check if delimiter exists you can use .Contains("++") or .IndexOf("++") != -1
By default, if no matches are found it returns the string in a array of size one.
How am I able to determine if the string has no ++ in it ?
if (value.Contains("++"))
edit: wow a bunch of answers already while i was writing this. :D
As #Gilad and others have pointed out, this is indeed the expected output. If a string does not contain the split value, the entire string is returned as the first item in the list.
If you plan on using this split value later, you can still use the .Split() method to determine if your split string is contained within the string, by simply checking if the count is equal to 1:
List<string> l = value.Split(new[] {"++"}).ToList();
if (l.Count == 1) {
//++ was not found in the string
} else {
//++ was found in the string (l.Count-1) times
}
Note of caution: It's less efficient to split a string, and allocate an array, than simply just checking with a method such as .Contains(). Use the above solution, if you may actually use the above split items later in the code.
If there is no "++" in the string, you get back the original string. If there are n "++"'s in the string, you get n+1 splits returned. You code is fine except that it needs an array passed:
var l = value.Split(new string[] {"++"}, StringSplitOptions.None).ToList();
So when l.Count() == 1 then there is no "++" in the string

How to let user leave blank textboxes that are assigned as Char [duplicate]

I have what I think is an easy problem. For some reason the following code generates the exception, "String must be exactly one character long".
int n = 0;
foreach (char letter in charMsg)
{
// Get the integral value of the character.
int value = Convert.ToInt32(letter);
// Convert the decimal value to a hexadecimal value in string form.
string hexOutput = String.Format("{0:X}", value);
//Console.WriteLine("Hexadecimal value of {0} is {1}", letter, hexOutput);
charMsg[n] = Convert.ToChar(hexOutput);
n++;
}
The exception occurs at the charMsg[n] = Convert.ToChar(hexOutput); line. Why does it happen? When I check the values of CharMsg it seems to contain all of them properly, yet still throws an error at me.
UPDATE: I've solved this problem, it was my mistake. Sorry for bothering you.
OK, this was a really stupid mistake on my part. Point is, with my problem I'm not even supposed to do this as hex values clearly won't help me in any way.
What I am trying to do it to encrypt a message in an image. I've already encrypted the length of said message in last digits on each color channel of first pixel. Now I'm trying to put the very message in there. I lookt here: http://en.wikipedia.org/wiki/ASCII and said to myself without thinking that usung hexes would be a good idea. Can't belive I thought that.
Convert.ToChar( string s ), per the documentation requires a single character string, otherwise it throws a FormatException as you've noted. It is a rough, though more restrictive, equivalent of
public char string2char( string s )
{
return s[0] ;
}
Your code does the following:
Iterates over all the characters in some enumrable collection of characters.
For each such character, it...
Converts the char to an int. Hint: a char is an integral type: its an unsigned 16-bit integral value.
converts that value to a string containing a hex representation of the character in question. For most characters, that string will be at least two character in length: for instance, converting the space character (' ', 0x20) this way will give you the string "20".
You then try to convert that back to a char and replace the current item being iterated over. This is where your exception is thrown. One thing you should note here is that altering a collection being enumerated is likely to cause the enumerator to throw an exception.
What exactly are you trying to accomplish here. For instance, given a charMsg that consist of 3 characters, 'a', 'b' and 'c', what should happen. A clear problem statement helps us to help you.
Since printable unicode characters can be anywhere in range from 0x0000 to 0xFFFF, your hexOutput variable can hold more than one character - this is why error is thrown.
Convert.ToChar(string) would always check length a of string, and if it is not equal to 1 - it would throw. So it would not convert string 0x30 to hexadecimal number, and then to ascii representation, symbol 0.
Can you elaborate on what you are trying to archieve ?
Your hexOutput is a string, and I'm assuming charMsg is a character array. Suppose the first element in charMsg is 'p', or hex value 70. The documentation for Convert.ToChar(string) says it'll use just the first character of the string ('7'), but it's wrong. It'll throw this error. You can test this with a static example, like charMsg[n] = Convert.ToChar("70");. You'll get the same error.
Are you trying to replace characters with hex values? If so, you might try using a StringBuilder object instead of your array assignments.
Convert.ToChar(string) if it is empty string lead this error. instead use cchar()

How are strings VS chars handled in C# vs Javascript?

In JavaScript, single and double quotes are somewhat interchangeable and largely a matter of styles (There is a good discussion of why this isn't actually the case in one of the answers here: When to use double or single quotes in JavaScript?). How are chars and strings handled in C#?
For example:
string test = "hello world";
string test2 = 'hello world'; // Too many characters in character literal
char test3 = 'a';
char test4 = "a"; // Cannot implicitly convert type string to char
It looks like strings and chars are being handled as separate, interchangeable types, and that the use of single or double quotes demarcates this?
What is the relationship between chars and strings in typed languages? Specifically, would it be correct to say that a string is an array of chars?
would it be correct to say that a string is an array of chars
In .NET, a string is an object containing a contiguous block of memory containing UTF-16 code units. A char is another (primitive) data type that just contains one code point, with no object overhead.
From this interesting blog post from Jon Skeet, where he compares the .NET vs. Java implementation:
A long string consists of a single large object in memory. Compare this with Java, where a String is a “normal” type in terms of memory consumption, containing an offset and length into a char array – so a long string consists of a small object referring to a large char array.
C# uses the quotes to indicate the type - ' is always a char, " is always a string.
In .NET a string behaves like a read-only array of char, so:
// Treat string like an array
char c = "This is a string"[3];
int len = "This is a string".Length
// Now we have the char at pos 3
c == 's';
What you can't do is edit them:
// This fails
"This is a string"[3] = 'x';
// This is fine, because we get a new editable char[]
char[] c = "This is a string".ToCharArray();
c[3] = 'x';
This is true in any .NET language as they all use the same string implementation. Other strongly typed frameworks have different ways of handling strings.
In .NET char can be explicitly cast to an int and implicitly cast back, so:
char c = (char) 115; // 's'
int i = c; // 115
Finally char is a value type, while string (being a collection of character bytes under the covers) is actually an immutable reference type. These behave very similarly in code but are stored in different ways in memory - I think this is why C# makes the distinction in how they are delimited - "s" and 's' are different things and stored in different ways (entirely unlike the Javascript string).

String.Contains and String.LastIndexOf C# return different result?

I have this problem where String.Contains returns true and String.LastIndexOf returns -1. Could someone explain to me what happened? I am using .NET 4.5.
static void Main(string[] args)
{
String wikiPageUrl = #"http://it.wikipedia.org/wiki/ʿAbd_Allāh_al-Sallāl";
if (wikiPageUrl.Contains("wikipedia.org/wiki/"))
{
int i = wikiPageUrl.LastIndexOf("wikipedia.org/wiki/");
Console.WriteLine(i);
}
}
While #sa_ddam213's answer definitely fixes the problem, it might help to understand exactly what's going on with this particular string.
If you try the example with other "special characters," the problem isn't exhibited. For example, the following strings work as expected:
string url1 = #"http://it.wikipedia.org/wiki/»Abd_Allāh_al-Sallāl";
Console.WriteLine(url1.LastIndexOf("it.wikipedia.org/wiki/")); // 7
string url2 = #"http://it.wikipedia.org/wiki/~Abd_Allāh_al-Sallāl";
Console.WriteLine(url2.LastIndexOf("it.wikipedia.org/wiki/")); // 7
The character in question, "ʿ", is called a spacing modifier letter1. A spacing modifier letter doesn't stand on its own, but modifies the previous character in the string, this case a "/". Another way to put this is that it doesn't take up its own space when rendered.
LastIndexOf, when called with no StringComparison argument, compares strings using the current culture.
When strings are compared in a culture-sensitive manner, the "/" and "ʿ" characters are not seen as two distinct characters--they're processed into one character, which does not match the parameter passed in to LastIndexOf.
When you pass in StringComparison.Ordinal to LastIndexOf, the characters are treated as distinct, due to the nature of Ordinal comparison.
Another way to make this work would be to use CompareInfo.LastIndexOf and supply the CompareOptions.IgnoreNonSpace option:
Console.WriteLine(
CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(
wikiPageUrl, #"it.wikipedia.org/wiki/", CompareOptions.IgnoreNonSpace));
// 7
Here we're saying that we don't want combining characters included in our string comparison.
As a sidenote, this means that #Partha's answer and #Noctis' answer only work because the character is being applied to a character that doesn't appear in the search string that's passed to LastIndexOf.
Contrast this with the Contains method, which by default performs an Ordinal (case sensitive and culture insensitive) comparison. This explains why Contains returns true and LastIndexOf returns false.
For a fantastic overview of how strings should be manipulated in the .NET framework, check out this article.
1: Is this different than a combining character or is it a type of combining character? would appreciate if someone would clear that up for me.
Try using StringComparison.Ordinal
This will compare the string by evaluating the numeric values of the corresponding chars in each string, this should work with the special chars you have in that example string
string wikiPageUrl = #"http://it.wikipedia.org/wiki/ʿAbd_Allāh_al-Sallāl";
int i = wikiPageUrl.LastIndexOf("http://it.wikipedia.org/wiki/", StringComparison.Ordinal);
// returns 0;
The thing is C# lastindexof looks from behind.
And wikipedia.org/wiki/ is followed by ' which it takes as escape sequence. So either remove ' after wiki/ or have an # there too.
The following syntax will work( anyone )
string wikiPageUrl = #"http://it.wikipedia.org/wiki/Abd_Allāh_al-Sallāl";
string wikiPageUrl = #"http://it.wikipedia.org/wiki/#ʿAbd_Allāh_al-Sallāl";
int i = wikiPageUrl.LastIndexOf("wikipedia.org/wiki");
All 3 works
If you want a generalized solution for this problem replace ' with #' in your string before you perform any operations.
the ' characters throws it off.
This should work, when you escape the ' as \':
wikiPageUrl = #"http://it.wikipedia.org/wiki/\'Abd_Allāh_al-Sallāl";
if (wikiPageUrl.Contains("wikipedia.org/wiki/"))
{
"contains".Dump();
int i = wikiPageUrl.LastIndexOf("wikipedia.org/wiki/");
Console.WriteLine(i);
}
figure out what you want to do (remove the ', escape it, or dig deeper :) ).

Specified Cast is not Valid - trying to cast a char

I am trying to cast a char as follows:
while (Reader.Read())
{
VM VMResult = new VM();
VMResult.status = (char)Reader["status"];
VMList.Add(VMResult);
}
Then comes the fun part: Specified Cast is not Valid.
VMResult.status is a char
The returned data is a char(1) in sql
I assume there must be a difference in the C# / SQL char terminology.
What do you think?
I assume there must be a difference in the C# / SQL char terminology.
That's correct. A char in sql server is a fixed length character string. It can be nullable.
A char in .net is a structure that represents a single character as a UTF-16 code unit. It cannot be null since its a structure
There is no fixed length character string .Net unless you consider a char array or byte array a fixed length string.
Since most of the .net ecosystem has better support for strings than chars, char arrays or byte arrays, you're much better off just using the string that gets returned for the char(x) fields.
If you know for a fact that Reader["status"] will always be a char (or you only want the first char), and the current type of Reader["status"] is a string you can always
VMResult.status = (!string.IsNullOrEmpty(Reader["status"])) ?
Reader["status"].ToCharArray()[0] : '';
EDIT: null checking ftw.
OK so you basically want to cast a string to a char, this is going to assume that your "status" value is a single character string:
VMResult.status = Reader["status"].ToString()[0];
this also assumes Reader[] does not already return a string (if it did then the ToString is not required) and that the value is not null.

Categories

Resources