lunes, 9 de junio de 2008

Todo con arreglos, tablas,matrices,array como usted lo entienda pero nutrase

Jagged Arrays

In the preceding examples, when you created a two-dimensional array, you were creating what C# calls a rectangular array. Thinking of two-dimensional arrays as tables, a rectangular array is a two-dimensional array in which the length of each row is the same for the entire array. However, C# also allows you to create a special type of two-dimensional array called a jagged array. A jagged array is an array of arrays in which the length of each array can differ. Thus, a jagged array can be used to create a table in which the lengths of the rows are not the same.

Jagged arrays are declared by using sets of square brackets to indicate each dimension. For example, to declare a two-dimensional jagged array, you will use this general form:

type[ ] [ ] array-name = new type[size][ ];

Here, size indicates the number of rows in the array. The rows, themselves, have not been allocated. Instead, the rows are allocated individually. This allows for the length of each row to vary. For example, the following code allocates memory for the first dimension of jagged when it is declared. It then allocates the second dimensions manually.

int[][] jagged = new int[3][];
jagged[0] = new int[4];
jagged[1] = new int[3];
jagged[2] = new int[5];

After this sequence executes, jagged looks like this:

Image from book

It is easy to see how jagged arrays got their name!

Once a jagged array has been created, an element is accessed by specifying each index within its own set of brackets. For example, to assign the value 10 to element 2, 1 of jagged, you would use this statement:

jagged[2][1] = 10;

Note that this differs from the syntax that is used to access an element of a rectangular array.

The following program demonstrates the creation of a jagged two-dimensional array:

// Demonstrate jagged arrays.
 
using System;
 
class Jagged {
  public static void Main() {
    int[][] jagged = new int[3][];
    jagged[0] = new int[4];
    jagged[1] = new int[3];
    jagged[2] = new int[5];
 
    int i;
 
    // store values in first array
    for(i=0; i <>
      jagged[0][i] = i;
 
    // store values in second array
    for(i=0; i <>
      jagged[1][i] = i;
 
    // store values in third array
    for(i=0; i <>
      jagged[2][i] = i;
 
    // display values in first array
    for(i=0; i <>
      Console.Write(jagged[0][i] + " ");
 
    Console.WriteLine();
 
    // display values in second array
    for(i=0; i <>
      Console.Write(jagged[1][i] + " ");
 
    Console.WriteLine();
    
    // display values in third array
    for(i=0; i <>
      Console.Write(jagged[2][i] + " ");
 
    Console.WriteLine();
 
  }
}

The output is shown here:

0 1 2 3
0 1 2
0 1 2 3 4

Jagged arrays are not used by all applications, but they can be effective in some situations. For example, if you need a very large two-dimensional array that is sparsely populated (that is, one in which not all of the elements will be used), then an irregular array might be a perfect solution.

One last point: since jagged arrays are arrays of arrays, there is no restriction that requires that the arrays be single-dimensional. For example, the following creates an array of two-dimensional arrays:

int[][,] jagged = new int[3][,];

The next statement assigns jagged[0] a reference to a 4×2 array:

jagged[0] = new int[4, 2];

The following statement assigns a value to jagged[0][1,0]:

jagged[0][1,0] = i;

Previous Page

Next Page

Assigning Array References

As with other objects, when you assign one array reference variable to another, you are simply changing the object to which the variable refers. You are not causing a copy of the array to be made, nor are you causing the contents of one array to be copied to the other. For example, consider this program:

// Assigning array reference variables.
 
using System;
 
class AssignARef {
  public static void Main() {
    int i;
 
    int[] nums1 = new int[10];
    int[] nums2 = new int[10];
 
    for(i=0; i <>
 
    for(i=0; i <>
 
    Console.Write("Here is nums1: ");
    for(i=0; i <>
      Console.Write(nums1[i] + " ");
    Console.WriteLine();
 
    Console.Write("Here is nums2: ");
    for(i=0; i <>
      Console.Write(nums2[i] + " ");
    Console.WriteLine();
 
    nums2 = nums1; // now nums2 refers to nums1
    Console.Write("Here is nums2 after assignment: ");
    for(i=0; i <>
      Console.Write(nums2[i] + " ");
    Console.WriteLine();
 
   // now operate on nums1 array through nums2
   nums2[3] = 99;
 
    Console.Write("Here is nums1 after change through nums2: ");
    for(i=0; i <>
      Console.Write(nums1[i] + " ");
    Console.WriteLine();
  }
}

The output from the program is shown here:

Here is nums1: 0 1 2 3 4 5 6 7 8 9
Here is nums2: 0 -1 -2 -3 -4 -5 -6 -7 -8 -9
Here is nums2 after assignment: 0 1 2 3 4 5 6 7 8 9
Here is nums1 after change through nums2: 0 1 2 99 4 5 6 7 8 9

As the output shows, after the assignment of nums1 to nums2, both array reference variables refer to the same object.

Previous Page

Next Page

Using the Length Property

A number of benefits result because C# implements arrays as objects. One comes from the fact that each array has associated with it a Length property that contains the number of elements that an array can hold. Thus, each array carries with it a field that contains the array’s length. Here is a program that demonstrates this property:

// Use the Length array property.
 
using System;
 
class LengthDemo {
  public static void Main() {
    int[] nums = new int[10];
 
    Console.WriteLine("Length of nums is " + nums.Length);
 
    // use Length to initialize nums
    for(int i=0; i <>
      nums[i] = i * i;
 
    // now use Length to display nums
    Console.Write("Here is nums: ");
    for(int i=0; i <>
      Console.Write(nums[i] + " ");
 
    Console.WriteLine();
  }
}

This program displays the following output:

Length of nums is 10
Here is nums: 0 1 4 9 16 25 36 49 64 81

In LengthDemo notice the way that nums.Length is used by the for loops to govern the number of iterations that take place. Since each array carries with it its own length, you can use this information rather than manually keeping track of an array’s size. Keep in mind that the value of Length has nothing to do with the number of elements that are actually in use. It contains the number of elements that the array is capable of holding.

When the length of a multidimensional array is obtained, the total number of elements that can be held by the array is returned. For example:

// Use the Length array property on a 3-D array.
 
using System;
 
class LengthDemo3D {
  public static void Main() {
    int[,,] nums = new int[10, 5, 6];
 
    Console.WriteLine("Length of nums is " + nums.Length);
  }
}

The output is shown here:

Length of nums is 300

As the output verifies, Length obtains the number of elements that nums can hold, which is 300 (10×5×6) in this case. It is not possible to use Length to obtain the length of a specific dimension.

The inclusion of the Length property simplifies many algorithms by making certain types of array operations easier—and safer—to perform. For example, the following program uses Length to reverse the contents of an array by copying it back-to-front into another array:

// Reverse an array.
 
using System;
 
class RevCopy {
  public static void Main() {
    int i,j;
    int[] nums1 = new int[10];
    int[] nums2 = new int[10];
 
    for(i=0; i <>
 
    Console.Write("Original contents: ");
    for(i=0; i <>
      Console.Write(nums1[i] + " ");
    Console.WriteLine();
 
    // reverse copy nums1 to nums2
    if(nums2.Length >= nums1.Length) // make sure nums2 is long enough
      for(i=0, j=nums1.Length-1; i <>
        nums2[j] = nums1[i];
 
    Console.Write("Reversed contents: ");
    for(i=0; i <>
      Console.Write(nums2[i] + " ");
 
    Console.WriteLine();
  }
}

Here is the output:

Original contents: 0 1 2 3 4 5 6 7 8 9
Reversed contents: 9 8 7 6 5 4 3 2 1 0

Here, Length helps perform two important functions. First, it is used to confirm that the target array is large enough to hold the contents of the source array. Second, it provides the termination condition of the for loop that performs the reverse copy. Of course, in this simple example, the size of the arrays is easily known, but this same approach can be applied to a wide range of more challenging situations.

Using Length with Jagged Arrays

A special case occurs when Length is used with jagged arrays. In this situation, it is possible to obtain the length of each individual array. For example, consider the following program, which simulates the CPU activity on a network with four nodes:

// Demonstrate Length with jagged arrays.
 
using System;
 
class Jagged {
  public static void Main() {
    int[][] network_nodes = new int[4][];
    network_nodes[0] = new int[3];
    network_nodes[1] = new int[7];
    network_nodes[2] = new int[2];
    network_nodes[3] = new int[5];
 
 
    int i, j;
 
    // fabricate some fake CPU usage data
    for(i=0; i <>
      for(j=0; j <>
        network_nodes[i][j] = i * j + 70;
    Console.WriteLine("Total number of network nodes: " +
                      network_nodes.Length + "\n");
 
    for(i=0; i <>
      for(j=0; j <>
        Console.Write("CPU usage at node " + i +
                      " CPU " + j + ": ");
        Console.Write(network_nodes[i][j] + "% ");
        Console.WriteLine();
      }
      Console.WriteLine();
    }
  }
}

The output is shown here:

Total number of network nodes: 4
 
CPU usage at node 0 CPU 0: 70%
CPU usage at node 0 CPU 1: 70%
CPU usage at node 0 CPU 2: 70%
 
CPU usage at node 1 CPU 0: 70%
CPU usage at node 1 CPU 1: 71%
CPU usage at node 1 CPU 2: 72%
CPU usage at node 1 CPU 3: 73%
CPU usage at node 1 CPU 4: 74%
CPU usage at node 1 CPU 5: 75%
CPU usage at node 1 CPU 6: 76%
 
CPU usage at node 2 CPU 0: 70%
CPU usage at node 2 CPU 1: 72%
 
CPU usage at node 3 CPU 0: 70%
CPU usage at node 3 CPU 1: 73%
CPU usage at node 3 CPU 2: 76%
CPU usage at node 3 CPU 3: 79%
CPU usage at node 3 CPU 4: 82%

Pay special attention to the way Length is used on the jagged array network_nodes. Recall, a two-dimensional jagged array is an array of arrays. Thus, when the expression

network_nodes.Length

is used, it obtains the number of arrays stored in network_nodes, which is 4 in this case. To obtain the length of any individual array in the jagged array, you will use an expression such as this:

network_nodes[0].Length

which, in this case, obtains the length of the first array.

Previous Page

Next Page

The foreach Loop

In Chapter 5 it was mentioned that C# defines a loop called foreach, but a discussion of that statement was deferred until later. The time for that discussion has now come.

The foreach loop is used to cycle through the elements of a collection. A collection is a group of objects. C# defines several types of collections, of which one is an array. The general form of foreach is shown here:

foreach(type var-name in collection) statement;

Here, type var-name specifies the type and name of an iteration variable that will receive the values of the elements from the collection as the foreach iterates. The collection being cycled through is specified by collection, which, for this discussion, is an array. Thus, type must be the same as (or compatible with) the base type of the array. One important point to remember is that the iteration variable is read-only as far as the array is concerned. Thus, you can’t change the contents of the array by assigning the iteration variable a new value.

Here is a simple example that uses foreach. It creates an array of integers and gives it some initial values. It then displays those values, computing the summation in the process.

// Use the foreach loop.
 
using System;
 
class ForeachDemo {
  public static void Main() {
    int sum = 0;
    int[] nums = new int[10];
 
    // give nums some values
    for(int i = 0; i <>
      nums[i] = i;
 
    // use foreach to display and sum the values
    foreach(int x in nums) {
      Console.WriteLine("Value is: " + x);
      sum += x;
    }
    Console.WriteLine("Summation: " + sum);
  }
}

The output from the program is shown here:

Value is: 0
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 6
Value is: 7
Value is: 8
Value is: 9
Summation: 45

As this output shows, the foreach cycles through an array in sequence from the lowest index to the highest.

Although the foreach loop iterates until all elements in an array have been examined, it is possible to terminate a foreach loop early by using a break statement. For example, this program sums only the first five elements of nums:

// Use break with a foreach.
 
using System;
 
class ForeachDemo {
  public static void Main() {
    int sum = 0;
    int[] nums = new int[10];
 
    // give nums some values
    for(int i = 0; i <>
      nums[i] = i;
 
    // use foreach to display and sum the values
    foreach(int x in nums) {
      Console.WriteLine("Value is: " + x);
      sum += x;
      if(x == 4) break; // stop the loop when 4 is obtained
    }
    Console.WriteLine("Summation of first 5 elements: " + sum);
  }
}

This is the output produced:

Value is: 0
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Summation of first 5 elements: 10

As is evident, the foreach loop stops after the fifth element has been obtained.

The foreach also works on multidimensional arrays. It returns those elements in row order, from first to last.

// Use foreach on a two-dimensional array.
 
using System;
 
class ForeachDemo2 {
  public static void Main() {
    int sum = 0;
    int[,] nums = new int[3,5];
 
    // give nums some values
    for(int i = 0; i <>
      for(int j=0; j <>
        nums[i,j] = (i+1)*(j+1);
    
    // use foreach to display and sum the values
    foreach(int x in nums) {
      Console.WriteLine("Value is: " + x);
      sum += x;
    }
    Console.WriteLine("Summation: " + sum);
  }
}

The output from this program is shown here:

Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 2
Value is: 4
Value is: 6
Value is: 8
Value is: 10
Value is: 3
Value is: 6
Value is: 9
Value is: 12
Value is: 15
Summation: 90

Since the foreach can only cycle through an array sequentially, from start to finish, you might think that its use is limited. However, this is not true. A large number of algorithms require exactly this mechanism, of which one of the most common is searching. For example, the following program uses a foreach loop to search an array for a value. It stops if the value is found.

// Search an array using foreach.
 
using System;
 
class Search {
  public static void Main() {
    int[] nums = new int[10];
    int val;
    bool found = false;
 
    // give nums some values
    for(int i = 0; i <>
      nums[i] = i;
 
    val = 5;
 
    // use foreach to search nums for key
    foreach(int x in nums) {
      if(x == val) {
        found = true;
        break;
      }
    }
 
    if(found)
      Console.WriteLine("Value found!");
  }
}

The output is shown here:

Value found!

The foreach is an excellent choice in this application because searching an array involves examining each element. Other types of foreach applications include such things as computing an average, finding the minimum or maximum of a set, looking for duplicates, and so on. As you will see later in this book, the foreach is especially useful when operating on other types of collections.

Previous Page

Next Page

Strings

From a day-to-day programming standpoint, one of the most important of C#’s data types is string. string defines and supports character strings. In many other programming languages a string is an array of characters. This is not the case with C#. In C#, strings are objects. Thus, string is a reference type. Although string is a built-in data type in C#, a discussion of string needed to wait until classes and objects had been introduced.

Actually, you have been using the string class since Chapter 2. When you create a string literal, you are actually creating a string object. For example, in the statement

Console.WriteLine("In C#, strings are objects.");

the string “In C#, strings are objects.” is automatically made into a string object by C#. Thus, the use of the string class has been “below the surface” in the preceding programs. In this section you will learn to handle strings explicitly.

Constructing Strings

The easiest way to construct a string is to use a string literal. For example, here str is a string reference variable that is assigned a reference to a string literal:

string str = "C# strings are powerful.";

In this case, str is initialized to the character sequence “C# strings are powerful.”

You can also create a string from a char array. For example:

char[] charray = {'t', 'e', 's', 't'};
string str = new string(charray);

Once you have created a string object, you can use it anywhere that a quoted string is allowed. For example, you can use a string object as an argument to WriteLine( ), as shown in this example:

// Introduce string.
 
using System;
 
class StringDemo {
  public static void Main() {
 
    char[] charray = {'A', ' ', 's', 't', 'r', 'i', 'n', 'g', '.' };
    string str1 = new string(charray);
    string str2 = "Another string.";
 
    Console.WriteLine(str1);
    Console.WriteLine(str2);
  }
}

The output from the program is shown here:

A string.
Another string.

Operating on Strings

The string class contains several methods that operate on strings. Table 7-1 shows a few. The string type also includes the Length property, which contains the length of the string.

Table 7-1: Some Common String Handling Methods

Method

Description

static string Copy(string str)

Returns a copy of str.

int CompareTo(string str)

Returns less than zero if the invoking string is less than str, greater than zero if the invoking string is greater than str, and zero if the strings are equal.

int IndexOf(string str)

Searches the invoking string for the substring specified by str.

Returns the index of the first match, or 1 on failure.

int LastIndexOf(string str)

Searches the invoking string for the substring specified by str.

Returns the index of the last match, or 1 on failure.

string ToLower( )

Returns a lowercase version of the invoking string.

string ToUpper( )

Returns an uppercase version of the invoking string.

To obtain the value of an individual character of a string, you simply use an index. For example:

string str = "test";
Console.WriteLine(str[0]);

This displays “t”, the first character of “test”. Like arrays, string indexes begin at zero. One important point, however, is that you cannot assign a new value to a character within a string using an index. An index can only be used to obtain a character.

To test two strings for equality, you can use the = = operator. Normally, when the = = operator is applied to object references, it determines if both references refer to the same object. This differs for objects of type string. When the = = is applied to two string references, the contents of the strings, themselves, are compared for equality. The same is true for the != operator: when comparing string objects, the contents of the strings are compared.

Here is a program that demonstrates several string operations:

// Some string operations.
 
using System;
 
class StrOps {
  public static void Main() {
    string str1 =
      "When it comes to .NET programming, C# is #1.";
    string str2 = string.Copy(str1);
    string str3 = "C# strings are powerful.";
    string strUp, strLow;
    int result, idx;
 
    Console.WriteLine("str1: " + str1);
 
    Console.WriteLine("Length of str1: " +
                       str1.Length);
 
    // create upper- and lowercase versions of str1
    strLow = str1.ToLower();
    strUp =  str1.ToUpper();
    Console.WriteLine("Lowercase version of str1:\n    " +
                      strLow);
    Console.WriteLine("Uppercase version of str1:\n    " +
                      strUp);
 
    Console.WriteLine();
 
    // display str1, one char at a time.
    Console.WriteLine("Display str1, one char at a time.");
    for(int i=0; i <>
      Console.Write(str1[i]);
    Console.WriteLine("\n");
 
    // compare strings
    if(str1 == str2)
      Console.WriteLine("str1 == str2");
    else
      Console.WriteLine("str1 != str2");
 
    if(str1 == str3)
      Console.WriteLine("str1 == str3");
    else
      Console.WriteLine("str1 != str3");
 
    result = str1.CompareTo(str3);
    if(result == 0)
      Console.WriteLine("str1 and str3 are equal");
    else if(result <>
      Console.WriteLine("str1 is less than str3");
    else
      Console.WriteLine("str1 is greater than str3");
 
    Console.WriteLine();
 
    // assign a new string to str2
    str2 = "One Two Three One";
 
    // search string
    idx = str2.IndexOf("One");
    Console.WriteLine("Index of first occurrence of One: " + idx);
    idx = str2.LastIndexOf("One");
    Console.WriteLine("Index of last occurrence of One: " + idx);
 
  }
}

This program generates the following output:

str1: When it comes to .NET programming, C# is #1.
Length of str1: 44
Lowercase version of str1:
    when it comes to .net programming, c# is #1.
Uppercase version of str1:
    WHEN IT COMES TO .NET PROGRAMMING, C# IS #1.
 
Display str1, one char at a time.
When it comes to .NET programming, C# is #1.
 
str1 == str2
str1 != str3
str1 is greater than str3
 
Index of first occurrence of One: 0
Index of last occurrence of One: 14

You can concatenate (join together) two strings using the + operator. For example, this statement:

string str1 = "One";
string str2 = "Two";
string str3 = "Three";
string str4 = str1 + str2 + str3;

initializes str4 with the string “OneTwoThree”.

One other point: The string keyword is an alias for (that is, maps directly to) the System.String class defined by the .NET Framework class library. Thus, the fields and methods defined by string are those of the System.String class, which includes more than the sampling described here. System.String is examined in detail in Part II.

Arrays of Strings

Like any other data type, strings can be assembled into arrays. For example:

// Demonstrate string arrays.
 
using System;
 
class StringArrays {
  public static void Main() {
    string[] str = { "This", "is", "a", "test." };
 
    Console.WriteLine("Original array: ");
    for(int i=0; i <>
      Console.Write(str[i] + " ");
    Console.WriteLine("\n");
 
    // change a string
    str[1] = "was";
    str[3] = "test, too!";
 
    Console.WriteLine("Modified array: ");
    for(int i=0; i <>
      Console.Write(str[i] + " ");
  }
}

Here is the output from this program:

Original array:
This is a test.
 
Modified array:
This was a test, too!

Here is a more interesting example. The following program displays an integer value using words. For example, the value 19 would display as one nine.

// Display the digits of an integer using words.
 
using System;
 
class ConvertDigitsToWords {
  public static void Main() {
    int num;
    int nextdigit;
    int numdigits;
    int[] n = new int[20];
 
    string[] digits = { "zero", "one", "two",
                        "three", "four", "five",
                        "six", "seven", "eight",
                        "nine" };
    num = 1908;
 
    Console.WriteLine("Number: " + num);
 
    Console.Write("Number in words: ");
 
    nextdigit = 0;
    numdigits = 0;
 
    /* Get individual digits and store in n.
       These digits are stored in reverse order. */
    do {
      nextdigit = num % 10;
      n[numdigits] = nextdigit;
      numdigits++;
      num = num / 10;
    } while(num > 0);
    numdigits--;
 
    // display words
    for( ; numdigits >= 0; numdigits--)
      Console.Write(digits[n[numdigits]] + " ");
 
    Console.WriteLine();
  }
}

The output is shown here:

Number: 1908
Number in words: one nine zero eight

In the program, the string array digits holds in order the word equivalents of the digits from zero to nine. The program converts an integer into words by first obtaining each digit of the value and storing those digits, in reverse order, in the int array called n. Then, this array is cycled through from back to front. In the process, each integer value in n is used as an index into digits, with the corresponding string being displayed.

Strings Are Immutable

Here is something that might surprise you: The contents of a string object are immutable. That is, once created, the character sequence comprising that string cannot be altered. This restriction allows C# to implement strings more efficiently. Even though this probably sounds like a serious drawback, it isn’t. When you need a string that is a variation on one that already exists, simply create a new string that contains the desired changes. Since unused string objects are automatically garbage-collected, you don’t even need to worry about what happens to the discarded strings.

It must be made clear, however, that string reference variables may, of course, change the object to which they refer. It is just that the contents of a specific string object cannot be changed after it is created.

To fully understand why immutable strings are not a hindrance, we will use another of string’s methods: Substring( ). The Substring( ) method returns a new string that contains a specified portion of the invoking string. Because a new string object is manufactured that contains the substring, the original string is unaltered, and the rule of immutability is still intact. The form of Substring( ) that we will be using is shown here:

string Substring(int start, int len)

Here, start specifies the beginning index, and len specifies the length of the substring.

Here is a program that demonstrates Substring( ) and the principle of immutable strings:

// Use Substring().
 
using System;
 
class SubStr {
  public static void Main() {
    string orgstr = "C# makes strings easy.";
 
    // construct a substring
    string substr = orgstr.Substring(5, 12);
 
    Console.WriteLine("orgstr: " + orgstr);
    Console.WriteLine("substr: " + substr);
 
  }
}

Here is the output from the program:

orgstr: C# makes strings easy.
substr: kes strings

As you can see, the original string orgstr is unchanged and substr contains the substring.

One more point: Although the immutability of string objects is not usually a restriction or hindrance, there may be times when it would be beneficial to be able to modify a string. To allow this, C# offers a class called StringBuilder, which is in the System.Text namespace. It creates string objects that can be changed. For most purposes, however, you will want to use string, not StringBuilder.

Strings Can Be Used in switch Statements

A string can be used to control a switch statement. It is the only non-integer type that can be used in the switch. The fact that strings can be used in switch statements makes it possible to handle some formerly tedious situations quite easily. For example, the following program displays the digit equivalent of the words “one,” “two,” and “three”:

// A string can control a switch statement.
 
using System;
 
class StringSwitch {
  public static void Main() {
    string[] strs = { "one", "two", "three", "two", "one" };
 
    foreach(string s in strs) {
      switch(s) {
        case "one":
          Console.Write(1);
          break;
        case "two":
          Console.Write(2);
          break;
        case "three":
          Console.Write(3);
          break;
      }
    }
    Console.WriteLine();
 
  }
}

The output is shown here:

12321

Previous Page

Next Page

No hay comentarios:

Que hey funciona

Que hey funciona
Ojea

Aprende C#

Aprende C#
Illustrated 2008

El contador de visitas

Pinki y Cerebro

Pinki y Cerebro
Los Programmer

Libros interesantes

Libros interesantes
para Novatos