Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Can somebody tell me for what is allowed to use string.Substring(someIndex,0)?
string a = "abc";
var result = a.Substring(1,0);
Console.WriteLine(result);
This code will be compiled and will write nothing to console.
What is the reason that this is allowed?
In which case can this be used?
UPDATE
I will clarify that I know what is this method and that in this case it is returning empty string. I am NOT asking why the result is empty. I am asking why it's allowed to do this.
This code will be compiled and will write nothing to console.
First of all technically speaking, this statement is wrong: it writes a new line to the console. Thats where the Line in WriteLine comes in. But let's not be picky.
What is the reason that this is allowed?
There is no reason to disable it. Say for instance you want to make a string insertion method:
public static string StringInsert(String original, String toInsert, int index) {
return original.Substring(0,index)+toInsert+original.SubString(index);
}
Now our StringInsert method cannot know whether or first or second part will be empty (we could decide to insert at index 0). If we had to take into account that the first substring could have zero length, or the second, or both, then we would have to implement a lot of if-logic. Now we can use a one liner.
Usually one considers a string s a sequence of characters s=s0s1...sn-1. A substring from i with length j, is the string t=sisi+1...si+j-1. There is no ambiguity here: it is clear that if j is 0, then the result is the empty string. Usually you only raise an exception if something is exceptional: the input does not make any sense, or is not allowed.
Many things are allowed because there is no good reason to prohibit them.
Substrings of length zero are one such thing: in situations when the desired length is computed, this saves programmers who use your library from having to zero-check the length before making a call.
For example, let's say the task is to find a substring between the first and the last hash mark # in a string. Current library lets you do this:
var s = "aaa#bbb"; // <<== Only one # here
var start = s.IndexOf('#');
var end = s.LastIndexOf('#');
var len = end-start;
var substr = s.Substring(start, len); // Zero length
If zero length were prohibited, you would be forced to add a conditional:
var len = end-start;
var substr = len != 0 ? s.Substring(start, len) : "";
Checking fewer pre-requisites makes your library easier to use. In a way, Pythagorean theorem is useful in no small part because it works for the degenerate case, when the length of all three sides is zero.
The method you use has the following signature:
public string Substring(
int startIndex,
int length
)
where startIndex is
The zero-based starting character position of a substring in this
instance.
and length is
The number of characters in the substring.
That being said the following call is a pretty valid call
var result = a.Substring(1,0);
but is meaningless, since the number of charcaters in the substring you want to create is 0. This is why you don't get anything in the Console as an output.
Apparently, a call of Substring with passing the value of 0 as the value of second argument has no meaning.
From the documentation:
public string Substring(startIndex, length)
A string that is equivalent to the substring of length length that
begins at startIndex in this instance, or Empty if startIndex is equal
to the length of this instance and length is zero.
Basically, when you do someString.Substring(n, 0);, what you're getting back is a string that starts at n and has length 0.
The length parameter represents the total number of characters to extract from the current string instance.
Thats why nothing is printed to the console. The returned string is empty (has length 0).
EDIT:
Well, there is a limitation in place: the method throws an ArgumentOutOfRangeException if:
startIndex plus length indicates a position not within this instance.
-or-
startIndex or length is less than zero.
The reason they made the exception be thrown if length is less than zero and not if it is equal is most likely because, though pointless in most situations, requesting a string of 0 length is not an invalid request.
Related
While using LastIndexOf to search for a short string in a longer string I came across behavior that I find somewhat counterintuitive:
If I have a haystack and a needle:
var h = "abcabcabc";
var n = "abc";
And I tell LastIndexOf to start searching at index 3, 4, I would expect it to start looking there and proceed towards the start of the string, and hence return 3:
012345678
abcabcabc
abc <- try index 4, no
abc <- found at index 3
..but it actually locates the first abc and returns 0. It behaves like there is an assumption "user wants to start searching for a string of length 3 starting at index 4; the string couldn't possibly occur at any index higher than 2 so search will begin from index 2.. found at index 0" - while that would be true if one was starting from the very end of the string i.e. a needle of length 3 couldn't possibly be found any later than haystack.Length-3, I don't find it logical to adopt the approach in the middle of a string
Another way of looking at it is "the haystack is substringed so that it has a length equal to the startIndex and then the substringed haystack is searched" - but again, I don't find it reasonable to chop a document and remove a potential match
While I can reason the search logic out thus and try to remember it, it seems illogical to me to operate in such a manner, so I'm here asking if there is some underlying reason for this behavior that will make it easier to reason about?
Note: it's also fine to say "no, your logic of "start at 4, find at 3 is unreasonable because.." - it would help adjust my mental model of how I think LastIndexOf should work
from the documentation - it says
Reports the zero-based index position of the last occurrence of a
specified string within this instance. The search starts at a
specified character position and proceeds backward toward the
beginning of the string.
So it searches from the value to the beginning of the string. Different starting point as your expectation.
Update: as Matthew Watson mentioned in his comment from the source code
For LastIndexOf specifially, overloads which take a 'startIndex' and 'count' behave differently than their IndexOf counterparts. 'startIndex' is the index of the last char element that should be considered when performing the search. For example, if startIndex = 4, then the caller is indicating "when finding the match I want you to include the char element at index 4, but not any char elements past that point.
var h = "abcabcabc";
//index 012345678
// ^ last element that will be considdered "abca"
var n = "abc";
int result = h.LastIndexOf(n,3); //0
This question already has answers here:
compare two string value [closed]
(6 answers)
Closed 3 years ago.
I'm a beginner in c# and I'm making a console guess the number game. You enter a number and it tells you to guess higher or lower or if you guessed the number. Anyways, I'm having trouble comparing the answer with the users guess.
I've tried comparing string guess with string answer using a <= in an if statement. I got an error that says "Operator '<=' cannot be applied to operands of 'string' and'string'.
The code:
string answer = "537";
string guess = Console.ReadLine();
*if (guess <= answer)*
The code with asterisks is the code I'm getting an error from. Does anyone know what I'm doing wrong and a solution?
Since you've said that you're a beginner,
<= isn't valid for strings.
Imagine if I did this:
string foo = "Hello world";
string bar = "Wassup?"
if(foo <= bar)
{
/// do something
}
What, exactly, would foo <= bar mean in that context? We could trying to compare the length of the strings (bar is shorter than foo), the sum of the ASCII values of the characters in each string, or just about anything. It's possible to implement methods that do those things, but none of them make sense in the general case so the language doesn't try, and it shouldn't.
The difference between a string and an int is that the former is intended to contain character data, like a name or a sentence. Mathematical comparisons like <= apply to numeric data, like integers and floating point values. So, to get the behavior you're looking for, you need to convert your text data into a numeric type.
The nature of data types and how they are stored, comparisons, etc. is a nontrivial discussion. But, suffice it to say that the string "123" is NOT the same as the number (integer, most likely) 123.
The easiest fix for your code would be something like:
string answer = "537";
string guess = Console.ReadLine();
var intAnswer = Int32.Parse(answer);
var intGuess = Int32.Parse(guess);
if (intGuess <= intAnswer)
{
/// do something...
}
Note that this will throw an exception if the user enters anything in the console that is not a valid digit. (Look up TryParse for a better solution, but that's beyond the scope of this answer and I think it'll just confuse the issue in this case.)
I'd spend some time reading about data types, int vs string, etc. This is a reasonable question about something that is not obvious to those just getting started.
Keep at it. We all started somewhere, and this is as good a place as any.
strings cannot be treated as number, it will only compare if they are equal. if numbers are the input. convert it to int first, both the guess and answer. if the guess will always be a number this would suffice.
if (Convert.ToInt32(guess) <= Convert.ToInt32(answer))
{
}
if not try to do a try catch or Int32.TryParse
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
As a user I have to input the size of an array and then fill it.
For example if I input n=2,then first element =3,second =2 I need to calculate (X-3)(X-2).
For this example output has to be 1,-5,6 ( cause (X-3)(X-2) = x^2 - 5*x + 6).
I have no idea how to actually extract those coefficients.Do I have to work as if it was a string line? And how do I actually get to this expression "x^2 - 5*x + 6"?
This is a piece of code that I have, but it just filling of the array
Console.WriteLine( "Enter size of an array" );
int size;
Int32.TryParse(Console.ReadLine(), out size);
var firstVector = new string[size];
Console.WriteLine("Input first vector:");
for (var i = 0; i <size; i++)
{
firstVector[i] = Console.ReadLine();
}
int[] firstVecInt = Array.ConvertAll(firstVector, int.Parse);
Console.WriteLine("======================");
foreach (var item in firstVecInt)
{
Console.Write(item.ToString() + " ");
}
Console.WriteLine(" first vector");
for( var i =0; i< size;i++)
{
Console.Write("(x-" + firstVecInt[i] +")*");
}
Console.WriteLine("polynomial");
It is a bit vague, but I might be able to give you some hints:
Input
You should be parsing those values as you get them. Do not keep them as strings. But you also have to deal with users entering soemthing invalid, wich happens often.
For consoles I like to use the do...while loop. Do (ask the user for input) while (he has not entered anything valid). Combine it with TryParse() and possibly a temporary bool variable and you can do it with very little code.
Math
In order to get the power of something, you need to use the Math.Pow method. Unfortunately it only deals with float/doubles. So you have to potentially consider Float Inprecision. There is no variant that takes Integers, unless you make the loop yourself or go for BigInteger. (How do you do *integer* exponentiation in C#?).
For the other math, be warned that the order of Operators might not be the same in C# as it is in math. Do not hesistate to limit it to one math operation per line by using a lot of temporary variables.
I have a question. I am testing a lib from me, which is generation some text in xml-style. Up to now, I am testing with the function
Assert.AreEqual(string1, string2);
But the strings, which are in xml-style, are more than 300 characters long. And when I make a little mistake in one character, the test is failing and the output is, that the strings are not equal. But the test does not say, at which position they are not equal.
So my question is: Is there already an implemented function, which compares two strings and tell me also, at which position they differ + output of the strings ... ?
try this way
var indexBroke = 0;
var maxLength = Math.Min(string1.Length, string2.Length);
while (indexBroke < maxLength && string1[indexBroke] == string2[indexBroke]) {
indexBroke++;
}
return ++indexBroke;
the logic is that you compare each character step by step and when you get the first difference the function exit returninng the last index with equal characters
For that reason (and many others more), I can recommend using FluentAssertions.
With FluentAssertions you would formulate your assertion like this:
string1.Should().Be(string2);
In the case the strings do not match, you get a nice informative message helping you to tackle down the problem:
Expected string to be
"<p>Line one<br/>Line two</p>" with a length of 28, but
"<p>Line one<br>Line two</p>" has a length of 27.
Additionally, you can give a reason to make the error message even more clear:
string1.Should().Be(string2, "a multiline-input should have been successfully parsed");
That would give you the following message:
Expected string to be
"<p>Line one<br/>Line two</p>" with a length of 28 because a multiline-input should have been successfully parsed, but
"<p>Line one<br>Line two</p>" has a length of 27.
These reason arguments are especially valuable when comparing values that provide no meaning by themselves, such as booleans and numbers.
BTW, FluentAssertions also helps greatly in comparing object graphs.
I'm trying to parse a large text string. I need to split the original string in blocks of 15 characters(and the next block might contain white spaces, so the trim function is used). I'm using two strings, the original and a temporary one. This temp string is used to store each 15 length block.
I wonder if I could fall into a performance issue because strings are immutable. This is the code:
string original = "THIS IS SUPPOSE TO BE A LONG STRING AN I NEED TO SPLIT IT IN BLOCKS OF 15 CHARACTERS.SO";
string temp = string.Empty;
while (original.Length != 0)
{
temp = original.Substring(0, 14).Trim();
original = original.Substring(14, (original.Length -14)).Trim();
}
I appreciate your feedback in order to find a best way to achieve this functionality.
You'll get slightly better performance like this (but whether the performance gain will be significant is another matter entirely):
for (var startIndex = 0; startIndex < original.Length; startIndex += 15)
{
temp = original.Substring(startIndex, Math.Min(original.Length - startIndex, 15)).Trim();
}
This performs better because you're not copying the last all-but-15-characters of the original string with each loop iteration.
EDIT
To advance the index to the next non-whitespace character, you can do something like this:
for (var startIndex = 0; startIndex < original.Length; )
{
if (char.IsWhiteSpace(string, startIndex)
{
startIndex++;
continue;
}
temp = original.Substring(startIndex, Math.Min(original.Length - startIndex, 15)).Trim();
startIndex += 15;
}
I think you are right about the immutable issue - recreating 'original' each time is probably not the fastest way.
How about passing 'original' into a StringReader class?
If your original string is longer than few thousand chars, you'll have noticable (>0.1s) processing time and a lot of GC pressure. First Substring call is fine and I don't think you can avoid it unless you go deep inside System.String and mess around with m_FirstChar. Second Substring can be avoided completely when going char-by-char and iterating over int.
In general, if you would run this on bigger data such code might be problematic, it of course depends on your needs.
In general, it might be a good idea to use StringBuilder class, which will allow you to operator on strings in "more mutable" way without performance hit, like remove from it's beggining without reallocating whole string.
In your example however I would consider throwing out lime that takes substring from original and substitute it with some code that would update some indexes pointing where you should get new substring from. Then while condition would be just checking if your index as at the end of the string and your temp method would take substring not from 0 to 14 but from i, where i would be this index.
However - don't optimize code if you don't have to, I'm assuming here that you need more performance and you want to sacrifice some time and/or write a bit less understandable code for more efficiency.