BUY THIS BOOK

Safari Books Online

What is this?

Looking to Reprint this content?


C# Cookbook
C# Cookbook

By Stephen Teilhet, Jay Hilyard

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Numbers
Simple types are value types that are a subset of the built-in types in Visual C# .NET, although, in fact, the types are defined as part of the .NET Framework Class Library (.NET FCL). Simple types are made up of several numeric types and a bool type. These numeric types consist of a decimal type (decimal), nine integral types (byte, char, int, long, sbyte, short, uint, ulong, ushort), and two floating-point types (float, double). Table 1-1 lists the simple types and their fully qualified names in the .NET Framework.
Table 1-1: The simple data types
Fully qualified name
Reserved C# keyword
Value range
System.Boolean
bool
true or false
System.Byte
byte
0 to 255
System.SByte
sbyte
-128 to 127
System.Char
char
0 to 65535
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Determining Approximate Equality Between a Fraction and Floating-Point Value
You need to compare a fraction with a value of type double or float to determine whether they are within a close approximation to each other. Take, for example, the result of comparing the expression 1/6 and the value 0.16666667. These seem to be equivalent, except that 0.16666666 is precise to only 8 places to the right of the decimal point, and 1/6 is precise to the maximum number of digits to the right of the decimal point that the data type will hold.
Verify that the difference between the two values is within an acceptable tolerance:
using System;

public static bool IsApproximatelyEqualTo(double numerator, 
                                          double denominator, 
                                          double dblValue,
                                          double epsilon)
{
    double difference = (numerator/denominator) - dblValue;

    if (Math.Abs(difference) < epsilon)
    {
        // This is a good approximation
        return (true);
    }
    else
    {
        // This is NOT a good approximation
        return (false);
    }
}
Replacing the type double with float allows you to determine whether a fraction and a float value are approximately equal.
Fractions can be expressed as a numerator over a denominator; however, storing them as a floating-point value might be necessary. Storing fractions as floating-point values introduces rounding errors that make it difficult to perform comparisons. Expressing the value as a fraction (e.g., 1/6) allows the maximum precision. Expressing the value as a floating-point value (e.g., 0.16667) can limit the precision of the value. In this case, the precision depends on the number of digits that the developer decides to use to the right of the decimal point.
You might need a way to determine whether two values are approximately equal to each other. This comparison is achieved by defining a value (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Degrees to Radians
When using the trigonometric functions of the Math class, all units are in radians. You have one or more angles measured in degrees and want to convert these to radians in order to use them with the members of the Math class.
To convert a value in degrees to radians, multiply it by π/180:
using System;

public static double ConvertDegreesToRadians (double degrees)
{
    double radians = (Math.PI / 180) * degrees;
    return (radians);
}
All of the static trigonometric methods in the Math class use radians as their unit of measure for angles. It is very handy to have conversion routines to convert between radians and degrees, especially when a user is required to enter data in degrees rather than radians.
The equation for converting degrees to radians is shown here:
radians = (Math.PI / 180) * degrees
The static field Math.PI contains the constant π.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Radians to Degrees
When using the trigonometric functions of the Math class, all units are in radians; instead, you require a result in degrees.
To convert a value in radians to degrees, multiply it by 180/π:
using System;

public static double ConvertRadiansToDegrees(double radians)
{
    double degrees = (180 / Math.PI) * radians;
    return (degrees);
}
All of the static trigonometric methods in the Math class use radians as their unit of measure for angles. It is very handy to have conversion routines to convert between radians and degrees, especially when displaying degrees to a user is more informative than displaying radians.
The equation for converting radians to degrees is shown here:
degrees = (180 / Math.PI) * radians
The static field Math.PI contains the constant π.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using the Bitwise Complement Operator with Various Data Types
The bitwise complement operator (~) is overloaded to work directly with int, uint, long, ulong, and enumeration data types consisting of the underlying types int, uint, long, and ulong. However, you need to perform a different bitwise complement operation on a data type.
You must cast the resultant value of the bitwise operation to the type you wish to work. The following code demonstrates this technique with the byte data type:
byte y = 1;
byte result = (byte)~y;
The value assigned to result is 254.
The following code shows incorrect use of the bitwise complement operator on the byte data type:
byte y = 1;
Console.WriteLine("~y = " + ~y);
This code outputs the following surprising value:
-2
Clearly, the result from performing the bitwise complement of the byte variable is incorrect; it should be 254. In fact, byte is an unsigned data type, so it cannot be equal to a negative number. If we rewrite the code as follows:
byte y = 1;
byte result = ~y;
we get a compile-time error: "Cannot implicitly convert type `int' to `byte.'" This error message gives some insight into why this operation does not work as expected. To fix this problem, we must explicitly cast this value to a byte before we assign it to the result variable, as shown here:
byte y = 1;
byte result = (byte)~y;
This cast is required because the bitwise operators are only overloaded to operate on six specific data types: int, uint, long, ulong, bool, and enumeration data types. When one of the bitwise operators is used on another data type, that data type is converted to the next closest data type of the six supported data types. Therefore, a byte data type is converted to an int before the bitwise complement operator is evaluated:
      0x01    // byte y = 1;
0xFFFFFFFE    // The value 01h is converted to an int and its 
              //   bitwise complement is taken
      0xFE    // The resultant int value is cast to its original byte data type
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Test for an Even or Odd Value
You need a simple method to test a numeric value to determine whether it is even or odd.
The solution is actually implemented as two methods. To test for an even integer value, use the following method:
public static bool IsEven(int intValue)
{
    return ((intValue & 1) == 0);
}
To test for an odd integer value, use the following method:
public static bool IsOdd(int intValue)
{
    return ((intValue & 1) == 1);
}
Every odd number always has its least-significant bit set to 1. Therefore, by checking whether this bit is equal to 1, we can tell whether it is an odd number. Conversely, testing the least-significant bit to see whether it is 0 can tell you whether it is an even number.
To test whether a value is even we AND the value in question with 1 and then determine whether the result is equal to zero. If the result is zero, we know that the value is an even number; otherwise, the value is odd. This operation is part of the IsEven method.
On the other hand, we can determine whether a value is odd by ANDing the value with 1, similar to how the even test operates, and then determine whether the result is 1. If the result is set to 1, we know that the value is an odd number; otherwise, the value is even. This operation is part of the IsOdd method.
Note that you do not have to implement both the IsEven and IsOdd methods in your application, although implementing both methods might improve the readability of your code.
The methods presented here accept only 32-bit integer values. To allow this method to accept other numeric data types, you can simply overload it to accept any other data types that you require. For example, if you need to also determine whether a 64-bit integer is even, you could modify the IsEven method as follows:
public static bool IsEven(long longValue)
{
    return ((longValue & 1) == 0);
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Obtaining the Most- or Least-Significant Bits of a Number
You have a 32-bit integer value that contains information in both its lower and upper 16 bits. You need a method to get the 16 most-significant bits and/or the 16 least-significant bits of this value.
To get the most-significant bits (MSB) of an integer value, perform a bitwise and between it and the value shown in the following method:
public static int GetMSB(int intValue)
{
    return (intValue & 0xFFFF0000);
}
To get the least-significant bits (LSB) of a value, use the following method:
public static int GetLSB(int intValue)
{
    return (intValue & 0x0000FFFF);
}
This technique can easily be modified to work with other sizes of integers (e.g., 8-bit, 16-bit, or 64-bit); this trick is shown in the Discussion section.
In order to determine the values of the MSB of a number, use the following bitwise AND operation:
uint intValue = Int32.MaxValue;
uint MSB = intValue & 0xFFFF0000;

// MSB == 0xFFFF0000
This method simply ANDs the number to another number with all of the MSB set to 1. This method will zero out all of the LSB, leaving the MSB intact.
In order to determine the values of the LSB of a number, use the following bitwise AND operation:
uint intValue = Int32.MaxValue;
uint LSB = intValue & 0x0000FFFF;

// LSB == 0x0000FFFF
This method simply ANDs the number to another number with all of the LSB set to 1, which zeroes out all of the MSB, leaving the LSB intact.
The methods presented here accept only 32-bit integer values. To allow this method to accept other numeric data types, you can simply overload this method to accept any other data types that you require. For example, if you need to also acquire the least-significant byte or most-significant byte of a 16-bit integer, you could modify the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting a Number in Another Base to Base10
You have a string containing a number in base2 (binary), base8 (octal), base10 (decimal), or base16 (hexadecimal). You need to convert this string to its equivalent integer value and display it in base10.
Use the overloaded static Convert.ToInt32 method on the Convert class:
string base2 = "11";
string base8 = "17";
string base10 = "110";
string base16 = "11FF";

Console.WriteLine("Convert.ToInt32(base2, 2) = " + 
                   Convert.ToInt32(base2, 2));

Console.WriteLine("Convert.ToInt32(base8, 8) = " + 
                   Convert.ToInt32(base8, 8));

Console.WriteLine("Convert.ToInt32(base10, 10) = " + 
                   Convert.ToInt32(base10, 10));

Console.WriteLine("Convert.ToInt32(base16, 16) = " + 
                   Convert.ToInt32(base16, 16));
This code produces the following output:
Convert.ToInt32(base2, 2) = 3
Convert.ToInt32(base8, 8) = 15
Convert.ToInt32(base10, 10) = 110
Convert.ToInt32(base16, 16) = 4607
The static Convert.ToInt32 method has an overload that takes a string containing a number and an integer defining the base of this number. This method then converts the numeric string into an integer and returns this number displayed as base10.
The other static methods of the Convert class, such as ToByte, ToInt64, and ToInt16, also have this same overload, which accepts a number as a string and a base type for this number. Unfortunately, these methods convert from base2, base8, base10, and base16 only to a value of base10. They do not convert a value to any other base types.
See the "Convert Class" and "Converting with System.Convert" topics in the MSDN documentation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Determining Whether a String Is a Valid Number
You have a string that possibly contains a numeric value. You need to know whether this string contains a valid number.
Use the static Parse method of any of the numeric types. For example, to determine whether a string contains an integer, use the following method:
public static bool IsNumeric(string str)
{
    try
    {
        str = str.Trim( );
        int foo = int.Parse(str);
        return (true);
    }
    catch (FormatException)
    {
        // Not a numeric value
        return (false);
    }
}
If you instead needed to test whether a string is a floating-point value, change the second line in the try block to the following:
int foo = float.Parse(str);
A more compact way of testing a string for a numeric value—and one that does not have the overhead of throwing an exception—is to use the double.TryParse method:
public static bool IsNumericFromTryParse(string str)
{
    double result = 0;
    return (double.TryParse(str, System.Globalization.NumberStyles.Float, 
            System.Globalization.NumberFormatInfo.CurrentInfo, out result));
}
The following IsNumericRegEx method does not incur the overhead of throwing an exception and it allows more flexibility in determining what type of number to test for. The IsNumericRegEx method tests for a number that can be signed/unsigned, contain a decimal point, and be displayed in scientific notation. This method accepts a string, possibly containing only a number, and returns true or false, depending on whether this string conforms to a numeric value:
private static Regex r = new Regex(@"^[\+\-]?\d*\.?[Ee]?[\+\-]?\d*$", 
                                   RegexOptions.Compiled);

public static bool IsNumericRegEx(string str)
{
    str = str.Trim( );
    Match m = r.Match(str);
    return (m.Value);
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Rounding a Floating-Point Value
You need to round a number to a whole number or to a specific number of decimal places.
To round any number to its nearest whole number, use the overloaded static Math.Round method, which takes only a single arguments:
int x = (int)Math.Round(2.5555);      // x == 3
If you need to round a floating-point value to a specific number of decimal places, use the overloaded static Math.Round method, which takes two arguments:
decimal x = Math.Round(2.5555, 2);      // x == 2.56
The Round method is easy to use; however, you need to be aware of how the rounding operation works. The Round method follows the IEEE Standard 754, section 4 standard. This means that if the number being rounded is halfway between two numbers, the Round operation will always round to the even number. An example will show what this means to you:
decimal x = Math.Round(1.5);      // x == 2
decimal y = Math.Round(2.5);      // y == 2
Notice that 1.5 is rounded up to the nearest even whole number and 2.5 is rounded down to the nearest even whole number. Keep this in mind when using the Round method.
See Recipe 1.1; see the "Math Class" topic in the MSDN documentation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Different Rounding Algorithms
The Math.Round method will round the value 1.5 to 2; however, the value 2.5 will also be rounded to 2 using this method. Always round to the greater number in this type of situation (e.g., round 2.5 to 3). Conversely, you might want to always round to the lesser number (e.g., round 1.5 to 1).
Use the static Math.Floor method to always round up when a value is halfway between two whole numbers:
public static double RoundUp(double valueToRound)
{
    return (Math.Floor(valueToRound + 0.5));
}
Use the following technique to always round down when a value is halfway between two whole numbers:
public static double RoundDown(double valueToRound)
{
    double floorValue = Math.Floor(valueToRound);
    if ((valueToRound - floorValue) > .5)
    {
        return (floorValue + 1);
    }
    else
    {
        return (floorValue);
    }
}
The static Math.Round method rounds to the nearest even number (see Recipe 1.9 for more information). However, there are some times that you do not want to round a number in this manner. The static Math.Floor method can be used to allow for different manners of rounding.
Note that the methods used to round numbers in this recipe do not round to a specific number of decimal points; rather, they round to the nearest whole number.
See Recipe 1.9; see the "Math Class" topic in the MSDN documentation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Celsius to Fahrenheit
You have a temperature reading measured in Celsius and need to convert it to Fahrenheit.
public static double CtoF(double celsius)
{
    return (((0.9/0.5) * celsius) + 32);
}
This recipe makes use of the following Celsius-to-Fahrenheit temperature conversion equation:
TempFahrenheit = ((9 / 5) * TempCelsius) + 32
The Fahrenheit temperature scale is widely used in the United States. However, much of the rest of the world uses the Celsius temperature scale.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Fahrenheit to Celsius
You have a temperature reading measured in Fahrenheit and need to convert it to Celsius.
public static double FtoC(double fahrenheit)
{
    return ((0.5/0.9) * (fahrenheit - 32));
}
This recipe makes use of the following Fahrenheit-to-Celsius temperature conversion equation:
TempCelsius = (5 / 9) * (TempFahrenheit - 32)
The Fahrenheit temperature scale is widely used in the United States. However, much of the rest of the world uses the Celsius temperature scale.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Safely Performing a Narrowing Numeric Cast
You need to cast a value from a larger value to a smaller one, while gracefully handling conditions that result in a loss of information. For example, casting a long to an int results only in a loss of information if the long data type is greater than int.MaxSize.
The simplest way to do this check is to use the checked keyword. The following method accepts two long data types and attempts to add them together. The result is stuffed into an int data type. If an overflow condition exists, the OverflowException is thrown:
using System;

public void UseChecked(long lhs, long rhs)
{
    int result = 0;

    try 
    {
        result =  checked((int)(lhs + rhs));
    }
    catch (OverflowException e) 
    {
        // Handle overflow exception here.
    }
}
This is the simplest method. However, if you do not want the overhead of throwing an exception and having to wrap a lot of code in try/catch blocks to handle the overflow condition, you could use the MaxValue and MinValue fields of each type. A check using these fields can be done prior to the conversion to insure that no loss of information occurs. If this does occur, the code can inform the application that this cast will cause a loss of information. You can use the following conditional statement to determine whether sourceValue can be cast to a short without losing any information:
// Our two variables are declared and initialized
int sourceValue = 34000;
short destinationValue = 0;

// Determine if sourceValue will lose information in a cast to a short
if (sourceValue <= short.MaxValue && sourceValue >= short.MinValue)
{
    destinationValue = (short)sourceValue;
}
else
{
    // Inform the application that a loss of information will occur
}
Instead of placing this conditional throughout your code, you can use the following overloaded methods to determine whether an integral type will lose data in a cast:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Finding the Length of Any Three Sidesof a Right Triangle
You need to calculate the length of one side of a triangle when either the lengths of two sides are known or one angle and the length of a side are known.
Use the Math.Sin, Math.Cos, and Math.Tan methods of the Math class to find the length of one side. The equations for these methods are as follows:
double theta = 40;
double hypotenuse = 5;
double oppositeSide;
double adjacentSide;

oppositeSide = Math.Sin(theta) * hypotenuse;
oppositeSide = Math.Tan(theta) * adjacentSide;
adjacentSide = Math.Cos(theta) * hypotenuse;
adjacentSide = oppositeSide / Math.Tan(theta);
hypotenuse   = oppositeSide / Math.Sin(theta);
hypotenuse   = adjacentSide / Math.Cos(theta);
where theta (Θ) is the known angle, and the oppositeSide variable is equal to the length of the side opposite to the angle theta, and the adjacentSide variable is equal to the length of the side adjacent to the angle theta. The hypotenuse variable is equal to the length of the hypotenuse of the triangle. See Figure 1-1.
Figure 1-1: A right triangle
In addition to these three static methods, the length of the hypotenuse of a right triangle can be calculated using the Pythagorean theorem. This theorem states that the hypotenuse of a right triangle is equal to the square root of the sum of the squares of the other two sides. This equation can be realized through the use of the Math.Pow and Math.Sqrt static methods of the Math class, as follows:
double hypotenuse = Math.Sqrt(Math.Pow(xSide, 2) + Math.Pow(ySide, 2))
where xSide and ySide are the lengths of the two sides that are not the hypotenuse of the triangle.
Finding the length of a side of a right triangle is easy when an angle and the length of one of the sides are known. Using the trigonometric functions sine, cosine, and tangent, we can derive the lengths of either of the two unknown sides. The equations for sine, cosine, and tangent are defined here:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Finding the Angles of a Right Triangle
You need to calculate an angle of a triangle when the lengths of two sides are known.
Use the Math.Atan, Math.Acos, or Math.Asin static methods of the Math class. The following code calculates the angle theta and returns the value in radian measure:
double theta = Math.Atan(OppositeSide / AdjacentSide);
theta = Math.Acos(AdjacentSide / Hypotenuse);
theta = Math.Asin(OppositeSide / Hypotenuse);
To get the angle in degrees, use the following code:
double theta = Math.Atan(oppositeSide / adjacentSide) * (180 / Math.PI);
theta = Math.Acos(adjacentSide / hypotenuse) * (180 / Math.PI);
theta = Math.Asin(oppositeSide / hypotenuse) * (180 / Math.PI);
where theta is the known angle value, the oppositeSide is equal to the length of the side opposite to the angle, and adjacentSide is equal to the length of the side adjacent to the angle. The hypotenuse is the length of the hypotenuse of the triangle. See Figure 1-1 in Recipe 1.14 for a graphical representation of these sides of a right triangle.
In some cases, we need to determine an angle of a right triangle when only the lengths of two sides are known. The three trigonometric functions arcsine, arccosine, and arctangent allow us to find any angle of a right triangle, given this information. The static methods Math.Atan, Math.Acos, and Math.Asin on the Math class provide the functionality to implement these trigonometric operations.
See Recipe 1.14; see the "Math Class" topic in the MSDN documentation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Strings and Characters
String usage abounds in just about all types of applications. The System.String type does not derive from System.ValueType and is therefore considered a reference type. The string alias is built into C# and can be used instead of the full name.
The FCL does not stop with just the string class; there is also a System.Text.StringBuilder class for performing string manipulations and the System.Text.RegularExpressions namespace for searching strings. This chapter will cover the string class and the System.Text.StringBuilder class.
The System.Text.StringBuilder class provides an easy, performance friendly, method of manipulating string objects. This class duplicates much of the functionality of a string class. However, this duplicated functionality provides a more efficient manipulation of strings than is obtainable by using the string class.
You have a variable of type char and wish to determine the kind of character it contains—a letter, digit, number, punctuation character, control character, separator character, symbol, whitespace, or surrogate character. Similarly, you have a string variable and want to determine the kind of character in one or more positions within this string.
Use the built-in static methods on the System.Char structure shown here:
Char.IsControl
Char.IsDigit
Char.IsLetter
Char.IsNumber
Char.IsPunctuation
Char.IsSeparator
Char.IsSurrogate
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Determining the Kind of Character
You have a variable of type char and wish to determine the kind of character it contains—a letter, digit, number, punctuation character, control character, separator character, symbol, whitespace, or surrogate character. Similarly, you have a string variable and want to determine the kind of character in one or more positions within this string.
Use the built-in static methods on the System.Char structure shown here:
Char.IsControl
Char.IsDigit
Char.IsLetter
Char.IsNumber
Char.IsPunctuation
Char.IsSeparator
Char.IsSurrogate
Char.IsSymbol
Char.IsWhitespace
The following examples demonstrate how to use the methods shown in the Solution section in a function to return the kind of a character. First, create an enumeration to define the various types of characters:
public enum CharKind
{
    Control,
    Digit,
    Letter,
    Number,
    Punctuation,        
    Separator,
    Surrogate,
    Symbol,
    Whitespace,
    Unknown
}
Next, create a method that contains the logic to determine the type of a character and to return a CharKind enumeration value indicating that type:
public static CharKind GetCharKind(char theChar)
{
    if (Char.IsControl(theChar))
    {
        return CharKind.Control;
    }
    else if (Char.IsDigit(theChar))
    {
        return CharKind.Digit;
    }
    else if (Char.IsLetter(theChar))
    {
        return CharKind.Letter;
    }
    else if (Char.IsNumber(theChar))
    {
        return CharKind.Number;
    }
    else if (Char.IsPunctuation(theChar))
    {
        return CharKind.Punctuation;
    }
    else if (Char.IsSeparator(theChar))
    {
        return CharKind.Separator;
    }
    else if (Char.IsSurrogate(theChar))
    {
        return CharKind.Surrogate;
    }
    else if (Char.IsSymbol(theChar))
    {
        return CharKind.Symbol;
    }
    else if (Char.IsWhiteSpace(theChar))
    {
        return CharKind.Whitespace;
    }
    else
    {
        return CharKind.Unknown;
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Determining Whether a Character Is Within a Specified Range
You need to determine whether a character in a char data type is within a range, such as between 1 and 5 or between A and M.
Use the built-in comparison support for the char data type. The following code shows how to use the built-in comparison support:
public static bool IsInRange(char testChar, char startOfRange, char endOfRange)
{
    if (testChar >= startOfRange && testChar <= endOfRange)
    {
        // testChar is within the range
        return (true);
    }
    else
    {
        // testChar is NOT within the range 
        return (false);
    }
}
There is only one problem with that code. If the startOfRange and endOfRange characters have different cases, the result may not be what you expect. By adding the following code, which makes all characters uppercase, to the beginning of the method in Recipe 2.7, we can solve this problem:
testChar = char.ToUpper(testChar);
startOfRange = char.ToUpper(startOfRange);
endOfRange = char.ToUpper(endOfRange);
The IsInRange method accepts three parameters. The first is the testChar character that you need to check on, to test if it falls between the last two parameters on this method. The last two parameters are the starting and ending characters, respectively, of a range of characters. The testChar parameter must be between startOfRange and endOfRange or equal to one of theses parameters for this method to return true; otherwise, false is returned.
The IsInRange method can be called in the following manner:
bool inRange = IsInRange('c', 'a', 'g');
bool inRange = IsInRange('c', 'a', 'b');
bool inRange = IsInRange((char)32, 'a', 'g');
The first call to this method returns true, since c is between a and g. The second method returns false, since c is not between a and b. The third method indicates how an integer value representative of a character would be passed to this method.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Controlling Case Sensitivity when Comparing Two Characters
You need to compare two characters for equality, but you need the flexibility of performing a case-sensitive or case-insensitive comparison.
Use the Equals instance method on the char structure to compare the two characters:
public static bool IsCharEqual(char firstChar, char secondChar)
{
    return (IsCharEqual(firstChar, secondChar, false));
}

public static bool IsCharEqual(char firstChar, char secondChar, 
                               bool caseSensitiveCompare)
{
    if (caseSensitiveCompare)
    {
        return (firstChar.Equals(secondChar));
    }
    else
    {
        return (char.ToUpper(firstChar).Equals(char.ToUpper(secondChar)));
    }
}
The first overloaded IsCharEqual method takes only two parameters: the characters to be compared. This method then calls the second IsCharEqual method with three parameters. The third parameter on this method call defaults to false so that when this method is called, you do not have to pass in a value for the caseSensitiveCompare parameter—it will automatically default to false.
Using the ToUpper method in conjunction with the Equals method on the string class allows us to choose whether to take into account the case of the strings when comparing them. To perform a case-sensitive comparison of two char variables, simply use the Equals method, which, by default, performs a case-sensitive comparison. Performing a case-insensitive comparison requires that both characters be converted to their uppercase values (they could just as easily be converted to their lowercase equivalents, but for this recipe we convert them to uppercase) before the Equals method is invoked. Setting both characters to their uppercase equivalents removes any case-sensitivity between the character values, and they can be compared using the case-sensitive Equals comparison method as though it were a case-insensitive comparison.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Finding All Occurrences of a Character Within a String
You need a way of searching a string for multiple occurrences of a specific character.
Use IndexOf in a loop to determine how many occurrences of a character exist, as well as identify their location within the string:
using System;
using System.Collections;

public static int[] FindAllOccurrences(char matchChar, string source)
{
    return (FindAllOccurrences(matchChar, source, -1, false));
}

public static int[] FindAllOccurrences(char matchChar, string source, 
                                           int maxMatches)
{
    return (FindAllOccurrences(matchChar, source, maxMatches, false));
}

public static int[] FindAllOccurrences(char matchChar, string source, 
                                           bool caseSensitivity)
{
    return (FindAllOccurrences(matchChar, source, -1, caseSensitivity));
}
        
public static int[] FindAllOccurrences(char matchChar, string source, 
                                           int maxMatches, bool caseSensitivity)
{
    ArrayList occurrences = new ArrayList( );
    int foundPos = -1;   // -1 represents not found
    int numberFound = 0;
    int startPos = 0;
    char tempMatchChar = matchChar;
    string tempSource = source;

    if (!caseSensitivity)
    {
        tempMatchChar = char.ToUpper(matchChar);
        tempSource = source.ToUpper( );
    }

    do
    {
        foundPos = tempSource.IndexOf(matchChar, startPos);        
        if (foundPos > -1)
        {
            startPos = foundPos + 1;
            numberFound++;

            if (maxMatches > -1 && numberFound > maxMatches)
            {
                break;
            }
            else
            {
                occurrences.Add(foundPos);
            }
        }
    }while (foundPos > -1);

    return ((int[])occurrences.ToArray(typeof(int)));
}
The FindAllOccurrences method is overloaded to allow the last two parameters (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Finding the Location of All Occurrencesof a String Within Another String
You need to search a string for every occurrence of a specific string. In addition, the case-sensitivity, or insensitivity, of the search needs to be controlled.
Using IndexOf or IndexOfAny in a loop, we can determine how many occurrences of a character or string exist as well as their locations within the string. To find each occurrence of a case-sensitive string in another string, use the following code:
using System;
using System.Collections;

public static int[] FindAll(string matchStr, string searchedStr, int startPos)
{
    int foundPos = -1;   // -1 represents not found
    int count = 0;
    ArrayList foundItems = new ArrayList( );

    do
    {
       foundPos = searchedStr.IndexOf(matchStr, startPos);
       if (foundPos > -1)
       {
          startPos = foundPos + 1;
          count++;
          foundItems.Add(foundPos);

          Console.WriteLine("Found item at position: " + foundPos.ToString( ));
       }
    }while (foundPos > -1 && startPos < searchedStr.Length);

    return ((int[])foundItems.ToArray(typeof(int)));
}
If the FindAll method is called with the following parameters:
int[] allOccurrences = FindAll("Red", "BlueTealRedredGreenRedYellow", 0);
the string "Red" is found at locations 8 and 19 in the string searchedStr. This code uses the IndexOf method inside a loop to iterate through each found matchStr string in the searchStr string.
To find a case-sensitive character in a string, use the following code:
public static int[] FindAll(char MatchChar, string searchedStr, int startPos)
{
    int foundPos = -1;   // -1 represents not found
    int count = 0;
    ArrayList foundItems = new ArrayList( );

    do
    {
       foundPos = searchedStr.IndexOf(MatchChar, startPos);
       if (foundPos > -1)
       {
          startPos = foundPos + 1;
          count++;
          foundItems.Add(foundPos);

          Console.WriteLine("Found item at position: " + foundPos.ToString( ));
       }
    }while (foundPos > -1 && startPos < searchedStr.Length);

    return ((int[])foundItems.ToArray(typeof(int)));
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Poor Man's Tokenizer
You need a quick method of breaking up a string into a series of discrete tokens or words.
Use the Split instance method of the string class. For example:
string equation = "1 + 2 - 4 * 5";
string[] equationTokens = equation.Split(new char[1]{' '});

foreach (string Tok in equationTokens)
   Console.WriteLine(Tok);
This code produces the following output:
1
+
2
-
4
*
5
The Split method may also be used to separate people's first, middle, and last names. For example:
string fullName1 = "John Doe";
string fullName2 = "Doe,John";
string fullName3 = "John Q. Doe";

string[] nameTokens1 = fullName1.Split(new char[3]{' ', ',', '.'});
string[] nameTokens2 = fullName2.Split(new char[3]{' ', ',', '.'});
string[] nameTokens3 = fullName3.Split(new char[3]{' ', ',', '.'});

foreach (string tok in nameTokens1)
{
   Console.WriteLine(tok);
}
Console.WriteLine("");

foreach (string tok in nameTokens2)
{
   Console.WriteLine(tok);
}
Console.WriteLine("");

foreach (string tok in nameTokens3)
{
   Console.WriteLine(tok);
}
This code produces the following output:
John
Doe

Doe
John

John
Q

Doe
Notice that a blank is inserted between the '.' and the space delimiters of the fullName3 name; this is correct behavior. If you did not want to process this space in your code, you can choose to ignore it.
If you have a consistent string whose parts, or tokens, are separated by well-defined characters, the Split function can tokenize the string. Tokenizing a string consists of breaking the string down into well-defined, discrete parts, each of which is considered a token. In the two previous examples, the tokens were either parts of a mathematical equation (numbers and operators) or parts of a name (first, middle, and last).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Controlling Case Sensitivity when Comparing Two Strings
You need to compare the contents of two strings for equality. In addition, the case sensitivity of the comparison needs to be controlled.
Use the Compare static method on the string class to compare the two strings. Whether the comparison is case-insensitive is determined by the third parameter of one of its overloads. For example:
string lowerCase = "abc";
string upperCase = "AbC";

int caseSensitiveResult = string.Compare(lowerCase, upperCase, false);
int caseInsensitiveResult = string.Compare(lowerCase, upperCase, true);
The caseSensitiveResult value is -1 (indicating that lowerCase is "less than" upperCase) and the caseInsensitiveResult is zero (indicating that lowerCase "equals" upperCase).
Using the static string.Compare method allows us the freedom to choose whether to take into account the case of the strings when comparing them. This method returns an integer indicating the lexical relationship between the two strings. A zero means that the two strings are equal, a negative number means that the first string is less than the second string, and a positive number indicates that the first string is greater than the second string.
By setting the last parameter of this method (the IgnoreCase parameter) to true or false, we can determine whether the Compare method takes into account the case of both strings when comparing. Setting this parameter to true forces a case-insensitive comparison and setting this parameter to false forces a case-sensitive comparison. In the case of the overloaded version of the method with no IgnoreCase parameter, comparisons are always case-sensitive.
See the "String.Compare Method" topic in the MSDN documentation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Comparing a String to the Beginning or End of a Second String
You need to determine whether a string is at the head or tail of a second string. In addition, the case sensitivity of the search needs to be controlled.
Use the EndsWith or StartsWith instance methods on a string object. Comparisons with EndsWith and StartsWith are always case-sensitive. The following code compares the value in the string variable head to the beginning of the string Test:
string head = "str";
string test = "strVarName";
bool isFound = test.StartsWith(head);
The following example compares the value in the string variable Tail to the end of the string test:
string tail = "Name";
string test = "strVarName";
bool isFound = test.EndsWith(tail);
In both examples, the isFound Boolean variable is set to true, since each string is found in test.
To do a case-insensitive comparison, employ the static string.Compare method. The following two examples modify the previous two examples by performing a case-insensitive comparison. The first is equivalent to a case-insensitive StartsWith string search:
string head = "str";
string test = "strVarName";
int isFound = string.Compare(head, 0, test, 0, head.Length, true);
The second is equivalent to a case-insensitive EndsWith string search:
string tail = "Name";
string test = "strVarName";
int isFound = string.Compare(tail, 0, test, (test.Length - tail.Length), 
                             tail.Length, true);
Use the BeginsWith or EndsWith instance methods to do a case-sensitive search for a particular string at the beginning or end of a string. The equivalent case-insensitive comparison requires the use of the static Compare method in the string class. If the return value of the Compare method is zero, a match was found. Any other number means that a match was not found.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Inserting Text into a String
You have some text (either a char or a string value) that needs to be inserted at a specific location inside of a second string.
Using the Insert instance method of the string class, a string or char can easily be inserted into a string. For example, in the code fragment:
string sourceString = "The Inserted Text is here -><-";

sourceString  = sourceString.Insert(28, "Insert-This");
Console.WriteLine(sourceString);
the string sourceString is inserted between the > and < characters in a second string. The result is:
The Inserted Text is here ->Insert-This<-
Inserting the character in sourceString into a second literal string between the > and < characters is shown here:
string sourceString = "The Inserted Text is here -><-";
char insertChar = '1';

sourceString  = sourceString.Insert(28, Convert.ToString(insertChar));
Console.WriteLine(sourceString);
There is no overloaded method for Insert that takes a char value, so using a string of length one is the next best solution.
There are two ways of inserting strings into other strings, unless, of course, you are using the regular expression classes. The first involves using the Insert instance method on the string class. This method is also slower than the others since strings are immutable, and, therefore, a new string object must be created to hold the modified value. In this recipe, the reference to the old string object is then changed to point to the new string object. Note that the Insert method leaves the original string untouched and creates a new string object with the inserted characters.
To add flexibility and speed to your string insertions, use the Insert instance method on the StringBuilder class. This method is overloaded to accept all of the built-in types. In addition, the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Removing or Replacing Characters Within a String
You have some text within a string that needs to be either removed or replaced with a different character or string. Since the replacing operation is somewhat simple, you do not require the overhead of using a regular expression to aid in the replacing operation.
To remove a substring from a string, use the Remove instance method on the string class. For example:
string name = "Doe, John";
name = name.Remove(3, 1);
Console.WriteLine(name);
This code creates a new string and then sets the name variable to refer to it. The string contained in name now looks like this:
Doe John
If performance is critical, and particularly if the string removal operation occurs in a loop so that the operation is performed multiple times, you can instead use the Remove method of the StringBuilder object. The following code modifies the str variable so that its value becomes 12345678:
StringBuilder str = new StringBuilder("1234abc5678", 12);
str.Remove(4, 3);
Console.WriteLine(str);
To replace a delimiting character within a string, use the following code:
string commaDelimitedString = "100,200,300,400,500";
commaDelimitedString = commaDelimitedString.Replace(',', ':'); 
Console.WriteLine(commaDelimitedString);
This code creates a new string and then makes the commaDelimitedString variable refer to it. The string in comm