Pick out every word beginning with a capital letter - c#

I would like to pick out every word in a string which beggings with a capital letter, but an Array out of bounds error appears on line 3;
foreach (string strWord in words)
{
if (Char.IsUpper(strWord[0]) && strWord.Length > 0)
{
Console.Write(strWord + " :: ");
}
}
Thank you for your help

Swap the arguments, otherwise it crashes before checking:
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))

Just do the strWord.Length > 0 first
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
{
Console.Write(strWord + " :: ");
}
So you can make sure strWord has at least one letter before trying to get first letter.

What is happening here is that you are checking the value of strWord[0] first without first making sure that there is any letter in the word or not, so in-case the value of strWord is NULL the program throws an exception that the index 0 is being called though it has not been given value, so to rectify this problem you should check the length of the word first and then check if the character strWord[0] is Upper case or not this way if the string is NULL then if condition will be discarded before it gets to the second part corrected code 1:-
if (strWord.Length > 0)
{
if(Char.IsUpper(strWord[0]))
{
Console.Write(strWord + " :: ");
}
}
corrected code 2:-
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
{
Console.Write(strWord + " :: ");
}

Make sure the length check is first when you use the && operator because the arguments are evaluated in order. If the first argument fails the second will not execute, and the IsUpper is causing out-of-bounds errors when Length is 0:
http://msdn.microsoft.com/en-us/library/2a723cdk.aspx
So you just need to swap the evaluations around:
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
{
//etc
}

The &&-operator is a short-circuiting operator which mans that it only evaluates the first condition if that returns already false. So it's the right choice if you want to prevent an exception. But you have to use the correct order, first the check then the method that can fail.
So like this:
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
...
However, you could also use this neat LINQ query:
var allWordsThatStartWithUpperCaseLetters = words
.Where(w => w.Length > 0 && Char.IsUpper(w[0]));
string result = string.Join(" :: ", allWordsThatStartWithUpperCaseLetters);

Related

Short circuit condition fail

I've a bit problem with a short circuit condition, what I need to do is check if an array have almost 2 indexes or a string is equal to a certain value, to recreate the problem here, suppose this:
string[] favItem = new string[] { "hello", "world", "test", "foo" };
string temp = "hello";
var itemToRemove = temp.Split(',');
foreach(var fav in favItem)
{
if(fav == "foo" || (itemToRemove.Length > 1 & fav == itemToRemove[0] || fav == itemToRemove[1]))
{
//do something
}
}
so essentially I need to compare fav with a default value, if this fail, I need to check if the itemToRemove array have almost 2 indexes, if yes I need to compare the fav value in iteration, with the two indexes of itemToRemove.
Now suppose that in itemToRemove there is only one index, I'm not able to exit from this:
(itemToRemove.Length > 1 & fav == itemToRemove[0] || fav == itemToRemove[1])
in particular with & I'm trying to exit from the condition if the indexes aren't two.
In the debug mode I can see the false value with the breakpoint, but I don't understand why the code fall to:
OutOfRangeException
with itemToRemove[1] when should be leave the condition.
What am I doing wrong?
Your code has two problems.
First, the short-circuiting boolean "and" operator is &&. & is the bitwise and operator, and does not short circuit.
Secondly, && has a higher precedence than ||, so you need to group the second || together like this (itemToRemove.Length > 1 && (fav == itemToRemove[0] || fav == itemToRemove[1])). The rule of thumb to remember precedence is that and is like multiplication 0 && 1 = 0, while or is like addition 0 || 1 = 1.
Short circuit is && not &.

While loop not properly checking all conditions?

So the assignment is as follows: you can enter all sorts of numbers but when you enter 0 two times in a row it needs to stop. The first time you enter a number your not allowed to enter 0.
This is the code I have setup:
class MainClass
{
public static void Main (string[] args)
{
int givenNumber, prevNumber;
Console.WriteLine ("Enter a number: ");
int.TryParse (Console.ReadLine (), out givenNumber);
// I've set the prevNumber to givenNumber because the variable has to be initialized
// before I can use it in the condition below. I thought setting it to the giveNumber
// wouldn't harm. Note that the first time your not allowed to enter 0
prevNumber = givenNumber;
while (givenNumber != 0 && prevNumber != 0) {
prevNumber = givenNumber; //Here is where they both are 0 at a given moment, but only after the condition.
Console.WriteLine ("Enter a number: ");
int.TryParse (Console.ReadLine (), out givenNumber);
}
Console.WriteLine ("Tada");
}
}
The problem is that it already stops when you've only entered one 0. For example if I'd first enter a 7 to start with, and my next number would be 0. When I debug it it says that my givenNumber is 0 and prevNumber is 7, when it goes back to the while condition it stops and finishes. When the program finishes the debug clearly says prevNumber = 7 and givenNumber = 0. I am using the conditional AND correct am I not?
Any clue? I'm not allowed to use arrays for this matter.
Thanks in advance
Ooh, right, you've got the logic wrong. It should be this:
while ((givenNumber != 0) || (prevNumber != 0)) {
Look up DeMorgan's laws to see why...
Your problem is with your conditional statement.
Right now you're checking whether both the givenNumber and the PrevNumber DO NOT equal 0.
So, if neither of them equals 0 then the statement will evaluate to TRUE. However, if either one of the numbers is 0 then the statement will evaluate to FALSE, since (TRUE) && (FALSE) evaluates to FALSE.
There are two ways to fix this: You can either use || (the "OR" operator) with the two "!=" statements, or you can negate the whole thing and use regular equality rather than "!=" as such: !(givenNumber == 0 && prevNumber == 0)
while (givenNumber != 0 && prevNumber != 0)
For first read value from console - number 7
givenNumer will be 7
prevNumber will be 7 too (because of assignment prevNumber = givenNumber;)
Thus while (7 != 0 && 7 != 0) will pass
Second read from Console - number 0
Thus while (0 != 0 && 7 != 0) will not pass because 0 != 0 is FALSE and while loop ends if condition is result is FALSE

Testing Values For Multiple Conditions in C#

I am having some difficulty finding out what's wrong with my code. I am trying to create a console app in C#. The program is supposed to ask the user to to input 3 numbers. All of the number must be greater than 0. The first number should be even, the second should be whole, and the third should be odd. My syntax seems to be correct, however, when I run the program, it seems to ignore the if (userInput > 0) part. Here is my code:
class Program
{
static void Main(string[] args)
{
try
{
int userInput;
Console.WriteLine("Please enter an even number.");
userInput = Convert.ToInt32(Console.ReadLine());
if (userInput > 0 && !isEven(userInput))
return;
Console.WriteLine("Please enter a whole number.");
userInput = Convert.ToInt32(Console.ReadLine());
if (userInput > 0)
Console.WriteLine("Please enter an odd number.");
userInput = Convert.ToInt32(Console.ReadLine());
if (userInput > 0 && isEven(userInput))
return;
Console.WriteLine("Congratulations!");
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
catch { }
}
static bool isEven(int value)
{
if (value % 2 == 0)
return true;
else
return false;
}
}
If anyone could tell me how to properly test both conditions I would be eternally greatful. Thanks.
Your requirements for the first number entered are essentially:
The number must be both positive and even.
The inverse of that is:
If the number is not positive, OR it is not even, then it is not valid.
Your check says
If the number is positive AND it is odd, then reject it
Meaning any number that is zero, negative, or even is valid.
What we have here is an application of DeMorgan's Law. It states that:
!(A && B)
is equivalent to
!A || !B
So if a valid number is even AND positive, then an invalid number is not even OR not positive (not positive is less than or equal to zero).
Problem : you are checking for one Valid and other invalid scenario with Logical AND.
Solution : you need to use both invalid scenarios with Logical OR.
asper your requirement program should not proceed if any one of the following rule breaks:
a. userinput should be > 0
b. userinput should be odd,whole and even
1. Replace This:
if (userInput > 0 && !isEven(userInput))
With This:
if (userInput <= 0 || !isEven(userInput))
2. Replace This:
if (userInput > 0 && isEven(userInput))
With This:
if (userInput <= 0 || isEven(userInput))
Based on the way you've structured your program, there is likely supposed to be a return statement after the second if, IE:
if (userInput > 0)
return;
However, this still does not address the problem that what you are probably trying to say is:
if (userInput <= 0)
return;
Or somewhat more directly translated from English:
if (!(userInput > 0))
return;
This change of sign applies to your other if statements as well, as others have mentioned.
Check
if (userInput <= 0 || !isEven(userInput))
return;
Since you want to quit when either the number is not positive OR the number is not even.
De Morgan's laws tell you how you can invert a logical expression. You do it by replacing each term by it's negated term and by replacing the AND's by OR's and vice versa.
So you could also write
if (userInput > 0 && isEven(userInput)) {
// The user input is ok, continue
} else {
return;
}
userInput <= 0 is the negation of userInput > 0.
De Morgan's laws
NOT(A AND B) = NOT(A) OR NOT(B)
and
NOT(A OR B) = NOT(A) AND NOT(B)

Neat solution to a counting within a string

I am trying to solve the following problem but cannot find an elegant solution. Any ideas?
Thanks.
Input - a variable length string of numbers, e.g.,
string str = "5557476374202110373551116201";
Task - Check (from left to right) that each number (ignoring the repetitions) does not appear in the following 2 indexes. Using eg. above, First number = 5. Ignoring reps we see that last index of 5 in the group is 2. So we check next 2 indexes, i.e. 3 and 4 should not have 5. If it does we count it as error. Goal is to count such errors in the string.
In the above string errors are at indexes, 3,10 and 16.
in addition to the other excellent solutions you can use a simple regexp:
foreach (Match m in Regexp.Matches(str, #"(\d)(?!\1)(?=\d\1)"))
Console.WriteLine("Error: " + m.Index);
returns 3,10,16. this would match adjacent errors using lookahead with a backreference. handles repetitions. .net should support that. if not, you can use a non-backreference version:
(?<=0[^0])0|(?<=1[^1])1|(?<=2[^2])2|(?<=3[^3])3|(?<=4[^4])4|(?<=5[^5])5|(?<=6[^6])6|(?<=7[^7])7|(?<=8[^8])8|(?<=9[^9])9
A simple indexed for loop with a couple of look ahead if checks would work. You can treat a string as a char[] or as an IEnumerable - either way you can use that to loop over all of the characters and perform a lookahead check to see if the following one or two characters is a duplicate.
Sorry, not a C# man, but here's a simple solution in Ruby:
a="5557476374202110373551116201"
0.upto(a.length) do |i|
puts "error at #{i}" if a[i]!=a[i+1] && a[i]==a[i+2]
end
Output:
error at 3
error at 10
error at 16
Here's something I threw together in C# that worked with the example input from the question. I haven't checked it that thoroughly, though...
public static IEnumerable<int> GetErrorIndices(string text) {
if (string.IsNullOrEmpty(text))
yield break;
int i = 0;
while (i < text.Length) {
char c = text[i];
// get the index of the next character that isn't a repetition
int nextIndex = i + 1;
while (nextIndex < text.Length && text[nextIndex] == c)
nextIndex++;
// if we've reached the end of the string, there's no error
if (nextIndex + 1 >= text.Length)
break;
// we actually only care about text[nextIndex + 1],
// NOT text[nextIndex] ... why? because text[nextIndex]
// CAN'T be a repetition (we already skipped to the first
// non-repetition)
if (text[nextIndex + 1] == c)
yield return i;
i = nextIndex;
}
yield break;
}

Why does "abcd".StartsWith("") return true?

Title is the entire question. Can someone give me a reason why this happens?
Yes - because it does begin with the empty string. Indeed, the empty string logically occurs between every pair of characters.
Put it this way: what definition of "starts with" could you give that would preclude this? Here's a simple definition of "starts with" that doesn't:
"x starts with y if the first y.Length characters of x match those of y."
An alternative (equivalent) definition:
"x starts with y if x.Substring(0, y.Length).Equals(y)"
I will try to elaborate on what Jon Skeet said.
Let's say x, y and z are strings and + operator is in fact concatenation, then:
If we can split z to write z = x + y that means that z starts with x.
Because every string z can be split to z = "" + z it follows that every string starts with "".
So, because ("" + "abcd") == "abcd" it follows that "abcd" starts with ""
I'll start with a related fact that is easier to understand.
The empty set is a subset of every set.
Why? The definition of subset states that A is a subset of B if every element of A is an element of B. Conversely, A is not a subset of B if there is an element of A that is not an element of B.
Now fix a set B. I'll establish that the empty set is a subset of B. I'll do this by showing that it is not the case that the empty set is not a subset of B. If the empty set were not a subset of B then I could find an element of the empty set that is not in B. But the empty set does not have any elements and thus I can not find an element that is not in B. Therefore, it is not the case that the empty set is not a subset of B. Thus, the empty set must be a subset of B.
Any string starts with the empty string.
First, we must agree on our definition of starts with. Let s and t be strings We say that s starts with t if s.Length >= t.Length and the first t.Length characters of t match those of s. That is, s.Length >= t.Length and for every Int32 index such that 0 <= index < t.Length, s[index] == t[index] is true. Conversely, we would say that s does not start with t if the statement
s.Length < t.Length or s.Length >= t.Length and there is an Int32 index such that 0 <= index < t.Length and s[index] != t[index]
is true. In plain English, s is shorter than t, or, if not, there is a character in t not matching the character as the same position in s.
Now fix a string s. I'll establish that s starts with the empty string. I'll do this by showing that it is not the case that s does not start with the empty string. If s does not start with the empty string then s.Length < String.Empty.Length or s.Length >= String.Empty.Length and there is an Int32 index such that 0 <= index < String.Empty.Length. But s.Length >= 0 and String.Empty.Length is equal to zero so it is impossible for s.Length < String.Empty.Length to be true. Similarly, since ``String.Empty.Lengthis equal to zero, there is noInt32 indexsatisfying0 <= index < String.Empty.Length`. Therefore
s.Length < String.Empty.Length or s.Length >= String.Empty.Length and there is an Int32 index such that 0 <= index < String.Empty.Length
is false. Therefore, it is not the case that s does not start with the empty string. Thus, s must start with the empty string.
The following is an implementation of starts with coded as an extension to string.
public static bool DoStartsWith(this string s, string t) {
if (s.Length >= t.Length) {
for (int index = 0; index < t.Length; index++) {
if (s[index] != t[index]) {
return false;
}
}
return true;
}
return false;
}
The above two bolded facts are examples of vacuously true statements. They are true by virtue of the fact that the statements defining them (subset and starts with) are universal quantifications over empty universes. There are no elements in the empty set, so there can not be any elements of the empty set not in some other fixed set. There are no characters in the empty string, so there can not be a character as some position in the empty string not matching the character in the same position in some other fixed string.
This method compares the value parameter to the substring at the beginning of this string that is the same length as value, and returns a value that indicates whether they are equal. To be equal, value must be an empty string (Empty), a reference to this same instance, or match the beginning of this instance.
.NET String.StartsWith
true if the character sequence represented by the argument is a prefix of the character sequence represented by this string; false otherwise. Note also that true will be returned if the argument is an empty string or is equal to this String object as determined by the equals(Object) method.
Java String.startsWith
Let's just say "abcd".StartsWith("") returns false.
if so then what does the following expression eval to, true or false:
("abcd".Substring(0,0) == "")
it turns out that evals to true, so the string does start with the empty string ;-), or put in other words, the substring of "abcd" starting at position 0 and having 0 length equals the empty string "". Pretty logical imo.
In C# this is how the specification tells it to react;
To be equal, value must be an empty string (Empty), a reference to this same instance, or match the beginning of this instance.
The first N characters of the two strings are identical. N being the length of the second string, i.e. zero.
Why does “abcd”.StartsWith(“”) return true?
THE REAL ANSWER:
It has to be that way otherwise you'd have the case where
"".startsWith("") == false
"".equals("") == true
but yet
"a".startsWith("a") == true
"a".equals("a") == true
and then we'd have Y2K all over again because all the bank software that depends on equal strings starting with themselves will get our accounts mixed up and suddenly Bill Gates will have my wealth and I'd have his, and damn it! Fate just isn't that kind to me.
Just for the record, String.StartsWith() internally calls the method System.Globalization.CultureInfo.IsPrefix() which makes the following check explicitly:
if (prefix.Length == 0)
{
return true;
}
Because a string begins well with "nothing".
If you think of it in regular expressions terms, it makes sense.
Every string (not just "abcd", also "" and "sdf\nff") ,
returns true when evaluating the regular expression of 'starts with empty string'.

Categories