I'm working around an array, in which i wanna add some of its values. At some points, for this do be done with just one calculation, it will ask for an index outside the array.
Is there a way to say, 'if an index is outside the array, assume the value to be 0' ?
Something a bit like this:
try
{
grid[x,y] = grid[x-1,y] + grid[x-1,y-1];
//This is simplified
x++;
}
catch (IndexOutOfRangeException)
{
grid[x - 1, y - 1] = 0;
}
Assuming for simplicity that you have an integer array, you may consider extension method like the following:
static class ArrayExtension
{
static int SafeGetAt(this int[,] a, int i, int j)
{
if(i < 0 || i >= a.GetLength(0) || j < 0 || j >= a.GetLength(1))
return 0;
return a[i, j];
}
}
and then access array elements as
grid.SafeGetAt(x, y);
An alternative approach could be to make a wrapper class which accesses the array internally and inplements an indexer. In this case you may keep using [,]-syntax to access elements.
I would not suggest using exceptions, which are quite slow and should be avoided in regular application workflow.
Related
I've tried changing my sort into a recursive function where the method calls itself. At least that's my understanding of recursion to forego for loops and the method calls itself to repeat the necessary iterations.
Below is my iterative verion:
for (int i = 0; i < Integers.Count; i++) //loops through all the numbers
{
min = i; //setting the current index number to be the minimum
for (int index = i + 1; index < Integers.Count; index++) //finds and checks pos of min value
{ //and switches it with last element using the swap method
if ((int) Integers[index] > (int) Integers[min]) {
min = index;
}
comparisons++;
}
if (i != min) //if statement for if swop is done
{
Swap(i, min, Integers, ref swops); //swap method called
}
//Swap method called
}
I've tried making it recursive. I read online that it was OK to still have for loops in a recursive funtion which I guess is not true. I just havent been able to develop a working sort. Am I going to need to split the method into 2 where one method traverses a list and the other does the sort?
Here's my selection sort recursive method attempt below:
static void DoSelectionSortRecursive(ArrayList Integers, int i, int swops, int comparisons) {
int min;
min = i;
for (int index = i + 1; index < Integers.Count; index++) //read online that the use of arraylists are deprecated, and i shoudlve rather used List<int> in order to remedy the code. is it necassary
{
if ((int) Integers[index] > (int) Integers[min]) {
min = index;
}
comparisons++;
}
if (i != min) {
Swap(i, min, Integers, ref swops);
}
DoSelectionSortRecursive(Integers, (i + 1), comparisons, swops); //DoSelectionSortRecursive method called
}
This is my imporved attempt including performance measures and everything. The original list of integers in the unsorted lists. 84,24,13,10,37.
and im getting 84,24,13,37,10. clearly not in a sorted descending order.
below is the improved code
static void DoSelectionSortRecursive(ArrayList Integers)
{
Stopwatch timer = new Stopwatch();
timer.Start();
int shifts = 0;
int swops = 0;
int comparisons = 0;
Sort(Integers, 1,ref swops,ref comparisons);
timer.Stop();
Console.WriteLine("Selection Sort Recursive: ");
Console.WriteLine(timer.ElapsedMilliseconds);
Console.WriteLine(swops);
Console.WriteLine(comparisons);
Console.WriteLine(shifts); //not needed in this sort
Console.WriteLine("-------------------------------------");
foreach (int i in Integers)
{
Console.WriteLine(i);
}
}
static void Sort(ArrayList Integers, int i, ref int swops, ref int comparisons)
{
int min = i;
int index = i + 1;
if (index < Integers.Count) //read online that the use of arraylists are deprecated, and i shoudlve rather used List<int> in order to remedy the code. is it necassary
{
if ((int)Integers[index] > (int)Integers[min])
{
min = index;
}
comparisons++;
index++;
}
if (i != min)
{
Swap(i, min, Integers, ref swops);
}
if (i < Integers.Count - 1)
{
Sort(Integers, (i + 1), ref comparisons, ref swops); //DoSelectionSortRecursive method called
}
}
static void Swap(int x, int y, ArrayList Integers, ref int swap) //swap method, swaps the position of 2 elements
{
swap++;
int temporary = (int)Integers[x]; //essentially will swap the min with the current position
Integers[x] = Integers[y];
Integers[y] = temporary;
}
There are no "rules" about recursion that say you cannot use loops in the recursive method body. The only rule in recursion is that the function has to call itself, which your second code snippet does, so DoSelectionSortRecursive is legitimately recursive.
For example, merge sort uses recursion for splitting the array and loops for merging the sorted subarrays. It'd be wrong to call it anything but a recursive function, and it'd be somewhat silly to implement the merging stage (an implementation detail of merge sort) recursively -- it'd be slower and harder to reason about, so loops are the natural choice.
On the other hand, the splitting part of merge sort makes sense to write recursively because it chops the problem space down by a logarithmic factor and has multiple branches. The repeated halving means it won't need to make more than a few or a dozen recursive calls on a typical array. These calls don't incur much overhead and fit well within the call stack.
On the other hand, the call stack can easily blow for linear recursive algorithms in languages without tail-call optimization like C# where each index in the linear structure requires a whole stack frame.
Rules prohibiting loops are concoted by educators who are trying to teach recursion by forcing you to use a specific approach in your solution. It's up to your instructor to determine whether one or both loops need to be converted to recursion for it to "count" as far as the course is concerned. (apologies if my assumptions about your educational arrangement are incorrect)
All that is to say that this requirement to write a nested-loop sort recursively is basically a misapplication of recursion for pedagogical purposes. In the "real world", you'd just write it iteratively and be done with it, as Google does in the V8 JavaScript engine, which uses insertion sort on small arrays. I suspect there are many other cases, but this is the one I'm most readily familiar with.
The point with using simple, nested loop sorts in performance-sensitive production code is that they're not recursive. These sorts' advantage is that they avoid allocating stack frames and incurring function call overhead to sort small arrays of a dozen numbers where the quadratic time complexity isn't a significant factor. When the array is mostly sorted, insertion sort in particular doesn't have to do much work and is mostly a linear walk over the array (sometimes a drawback in certain real-time applications that need predictable performance, in which case selection sort might be preferable -- see Wikipedia).
Regarding ArrayLists, the docs say: "We don't recommend that you use the ArrayList class for new development. Instead, we recommend that you use the generic List<T> class." So you can basically forget about ArrayList unless you're doing legacy code (Note: Java does use ArrayLists which are more akin to the C# List. std::list isn't an array in C++, so it can be confusing to keep all of this straight).
It's commendable that you've written your sort iteratively first, then translated to recursion on the outer loop only. It's good to start with what you know and get something working, then gradually transform it to meet the new requirements.
Zooming out a bit, we can isolate the role this inner loop plays when we pull it out as a function, then write and test it independent of the selection sort we hope to use it in. After the subroutine works on its own, then selection sort can use it as a black box and the overall design is verifiable and modular.
More specifically, the role of this inner loop is to find the minimum value beginning at an index: int IndexOfMin(List<int> lst, int i = 0). The contract is that it'll throw an ArgumentOutOfRangeException error if the precondition 0 <= i < lst.Count is violated.
I skipped the metrics variables for simplicity but added a random test harness that gives a pretty reasonable validation against the built-in sort.
using System;
using System.Collections.Generic;
using System.Linq;
class Sorter
{
private static void Swap(List<int> lst, int i, int j)
{
int temp = lst[i];
lst[i] = lst[j];
lst[j] = temp;
}
private static int IndexOfMin(List<int> lst, int i = 0)
{
if (i < 0 || i >= lst.Count)
{
throw new ArgumentOutOfRangeException();
}
else if (i == lst.Count - 1)
{
return i;
}
int bestIndex = IndexOfMin(lst, i + 1);
return lst[bestIndex] < lst[i] ? bestIndex : i;
}
public static void SelectionSort(List<int> lst, int i = 0)
{
if (i < lst.Count)
{
Swap(lst, i, IndexOfMin(lst, i));
SelectionSort(lst, i + 1);
}
}
public static void Main(string[] args)
{
var rand = new Random();
int tests = 1000;
int lstSize = 100;
int randMax = 1000;
for (int i = 0; i < tests; i++)
{
var lst = new List<int>();
for (int j = 0; j < lstSize; j++)
{
lst.Add(rand.Next(randMax));
}
var actual = new List<int>(lst);
SelectionSort(actual);
lst.Sort();
if (!lst.SequenceEqual(actual))
{
Console.WriteLine("FAIL:");
Console.WriteLine($"Expected => {String.Join(",", lst)}");
Console.WriteLine($"Actual => {String.Join(",", actual)}\n");
}
}
}
}
Here's a more generalized solution that uses generics and CompareTo so that you can sort any list of objects that implement the IComparable interface. This functionality is more akin to the built-in sort.
using System;
using System.Collections.Generic;
using System.Linq;
class Sorter
{
public static void Swap<T>(List<T> lst, int i, int j)
{
T temp = lst[i];
lst[i] = lst[j];
lst[j] = temp;
}
public static int IndexOfMin<T>(List<T> lst, int i = 0)
where T : IComparable<T>
{
if (i < 0 || i >= lst.Count)
{
throw new ArgumentOutOfRangeException();
}
else if (i == lst.Count - 1)
{
return i;
}
int bestIndex = IndexOfMin(lst, i + 1);
return lst[bestIndex].CompareTo(lst[i]) < 0 ? bestIndex : i;
}
public static void SelectionSort<T>(List<T> lst, int i = 0)
where T : IComparable<T>
{
if (i < lst.Count)
{
Swap(lst, i, IndexOfMin(lst, i));
SelectionSort(lst, i + 1);
}
}
public static void Main(string[] args)
{
// same as above
}
}
Since you asked how to smush both of the recursive functions into one, it's possible by keeping track of both i and j indices in the parameter list and adding a branch to figure out whether to deal with the inner or outer loop on a frame. For example:
public static void SelectionSort<T>(
List<T> lst,
int i = 0,
int j = 0,
int minJ = 0
) where T : IComparable<T>
{
if (i >= lst.Count)
{
return;
}
else if (j < lst.Count)
{
minJ = lst[minJ].CompareTo(lst[j]) < 0 ? minJ : j;
SelectionSort(lst, i, j + 1, minJ);
}
else
{
Swap(lst, i, minJ);
SelectionSort(lst, i + 1, i + 1, i + 1);
}
}
All of the code shown in this post is not suitable for production -- the point is to illustrate what not to do.
Following algorithm works pretty fine in C#
public int[] Sortieren(int[] array, int decide)
{
bool sorted;
int temp;
for (int i = 0; i < array.Length; i++)
{
do
{
sorted= true;
for (int j = 0; j < array.Length - 1; j++)
{
if (decide == 1)
{
if (array[j] < array[j + 1])
{
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
sorted= false;
}
}else if (decide == 0)
{
if (array[j] > array[j + 1])
{
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
sorted= false;
}
}
else
{
Console.WriteLine("Incorrect sorting parameter!");
break;
}
}
} while (!sorted);
}
return array;
}
Same thing in C fails. I only get the first two numbers of the array being sorted. The rest of the numbers are same. So, this code also seems to change the array instead of only sorting it. Any ideas, where are the bugs?
#include <stdio.h>
#include<stdbool.h>
#define MAX 10
void main(void)
{
int random_numbers[MAX],temp,Array_length;
bool sorted;
srand(time(NULL));
for(int i=0;i<=MAX;i++){
random_numbers[i]=rand()%1000;
}
Array_length=sizeof(random_numbers) / sizeof(int);
printf("List of (unsorted) numbers:\n");
for(int i=0;i<MAX;i++){
if(i==MAX-1)
printf("%i",random_numbers[i]);
else
printf("%i,",random_numbers[i]);
}
//Searching algorithm
for(int i=0;i<Array_length;i++){
do{
sorted=true;
for(int j=0;j<Array_length-1;j++){
if(random_numbers[j]>random_numbers[j+1]){
temp=random_numbers[j];
random_numbers[j]==random_numbers[j+1];
random_numbers[j+1]=temp;
sorted=false;
}
}
}while(!sorted);
}
printf("\n");
for(int i=0;i<Array_length;i++){
if(i==Array_length-1)
printf("%i",random_numbers[i]);
else
printf("%i,",random_numbers[i]);
}
}
You have an error in your swap algorithm:
if (zufallszahlen[j] > zufallszahlen[j+1]) {
temp = zufallszahlen[j];
zufallszahlen[j] == zufallszahlen[j+1]; // here
zufallszahlen[j+1] = temp;
sortiert = false;
}
In the line after you assign to temp, your double equal sign results in a check for equality rather than an assignment. This is still legal code (== is an operator and and expressions that use them evaluate to something), and the expression will evaluate to either 1 or 0 depending on the truth value of the statement. Note that this is legal even though you're not using the expression, where normally a boolean value would presumably be used for control flow.
Note that this is true for other operators as well. For example, the = operator assigns the value on the right to the variable on the left, so hypothetically a mistake like if (x = 0) will mean this branch will never be called, since the x = 0 will evaluate to false every time, when you may have meant to branch when x == 0.
Also, why are you using a boolean value to check if the array is sorted? Bubble sort is a simple algorithm, so it should be trivial to implement, and by the definition of an algorithm, it's guaranteed to both finish and be correct. If you were trying to optimize for performance purposes, for example choosing between merge sort and insertion sort based on whether the data was already sorted then I would understand, but you're checking whether the data is sorted as you're sorting it, which doesn't really make sense, since the algorithm will tell you when it's sorted because it will finish. Adding the boolean checking only adds overhead and nets you nothing.
Also, note how in your C# implementation, you repeated the sort process. This is a good sign your design is wrong. You take in an integer as well as the actual int[] array in your C# code, and you use that integer to branch. Then, from what I can gather, you sort using either < or >, depending on the value passed in. I'm pretty confused by this, since either would work. You gain nothing from adding this functionality, so I'm confused as to why you added it in.
Also, why do you repeat the printf statements? Even doing if/else if I might understand. But you're doing if/else. This is logically equivalent to P V ~P and will always evaluate to true, so you might as well get rid of the if and the else and just have one printf statement.
Below is implementation of your Bubble Sort program, and I want to point out a few things. First, it's generally frowned upon to declare main as void (What should main() return in C and C++?).
I quickly want to also point out that even though we are declaring the maximum length of the array as a macro, all of the array functions I defined explicitly take a size_t size argument for referrential transparency.
Last but not least, I would recommend not declaring all your variables at the start of your program/functions. This is a more contested topic among developers, especially because it used to be required, since compilers needed to know exactly what variables needed to be allocated. As compilers got better and better, they could accept variable declarations within code (and could even optimize some variables away altogether), so some developers recommend declaring your variables when you need them, so that their declaration makes sense (i.e... you know you need them), and also to reduce code noise.
That being said, some developers do prefer declaring all their variables at the beginning of the program/function. You'll especially see this:
int i, j, k;
or some variation of that, because the developer pre-declared all of their loop counters. Again, I think it's just code noise, and when you work with C++ some of the language syntax itself is code noise in my opinion, but just be aware of this.
So for example, rather than declaring everything like this:
int zufallszahlen[MAX], temp, Array_length;
You would declare the variables like this:
int zufallszahlen[MAX];
int Array_length = sizeof (zufallszahlen) / sizeof (int);
The temp variable is then put off for as long as possible so that it's obvious when and were it's useful. In my implementation, you'll notice I declared it in the swap function.
For pedagogical purposes I would also like to add that you don't have to use a swap variable when sorting integers because you can do the following:
a = a + b;
b = a - b;
a = a - b;
I will say, however, that I believe the temporary swap variable makes the swap much more instantly familiar, so I would say leave it in, but this is my own personal preference.
I do recommend using size_t for Array_length, however, because that's the type that the sizeof operator returns. It makes sense, too, because the size of an array will not be negative.
Here are the include statements and functions. Remember that I do not include <stdbool.h> because the bool checking you were doing was doing nothing for the algorithm.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
void PrintArray(int arr[], size_t n) {
for (int i = 0; i < n; ++i) {
printf("%d ", arr[i]);
}
printf("\n");
}
void PopulateArray(int arr[], size_t n) {
for (int i = 0; i < n; ++i) {
arr[i] = rand() % 1000 + 1;
}
}
void BubbleSortArray(int arr[], size_t n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n - 1; ++j) {
if (arr[j] > arr[j+1]) {
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
}
To implement the bubble sort algorithm, the only thing you have to do now is initialize the random number generator like you did, create your array and populate it, and finally sort the array.
int main()
{
srand(time(NULL));
int arr[MAX];
size_t array_length = sizeof (arr) / sizeof (int);
PopulateArray(arr, array_length);
PrintArray(arr, array_length);
BubbleSortArray(arr, array_length);
PrintArray(arr, array_length);
}
I hope this helps, let me know if you have any questions.
Okay, I've been using this code to do a selection sort on integers:
public void selectSort(int [] arr)
{
//pos_min is short for position of min
int pos_min,temp;
for (int i=0; i < arr.Length-1; i++)
{
pos_min = i; //set pos_min to the current index of array
for (int j=i+1; j < arr.Length; j++)
{
if (arr[j] < arr[pos_min])
{
//pos_min will keep track of the index that min is in, this is needed when a swap happens
pos_min = j;
}
}
//if pos_min no longer equals i than a smaller value must have been found, so a swap must occur
if (pos_min != i)
{
temp = arr[i];
arr[i] = arr[pos_min];
arr[pos_min] = temp;
}
}
}
but now I want to run the same algorithm on a string list instead.
How could that be accomplished? It feels really awkward and like you would need additional loops to compare multiple chars of different strings..?
I tried a lot, but I couldn't come up with anything useful. :/
Note:
I know, selection sort isn't very efficient. This is for learning purposes only. I'm not looking for alternative algorithms or classes that are already part of C#. ;)
IComparable is an interface that gives us a function called CompareTo, which is a comparison operator. This operator works for all types which implement the IComparable interface, which includes both integers and strings.
// Forall types A where A is a subtype of IComparable
public void selectSort<A>(A[] arr)
where A : IComparable
{
//pos_min is short for position of min
int pos_min;
A temp;
for (int i=0; i < arr.Length-1; i++)
{
pos_min = i; //set pos_min to the current index of array
for (int j=i+1; j < arr.Length; j++)
{
// We now use 'CompareTo' instead of '<'
if (arr[j].CompareTo(arr[pos_min]) < 0)
{
//pos_min will keep track of the index that min is in, this is needed when a swap happens
pos_min = j;
}
}
//if pos_min no longer equals i than a smaller value must have been found, so a swap must occur
if (pos_min != i)
{
temp = arr[i];
arr[i] = arr[pos_min];
arr[pos_min] = temp;
}
}
}
The System.String class has a static int Compare(string, string) method that returns a negative number if the first string is smaller than the second, zero if they are equal, and a positive integer if the first is larger.
By "smaller" I mean that it comes before the other in the lexical order and by larger that it comes after the other in lexical order.
Therefore you can compare String.Compare(arr[j], arr[pos_min]) < 0 instead of just arr[j] < arr[pos_min] for integers.
I am writing the code in python 3.6
First import sys module for use of various features in our syntax.
import sys
Consider an array of string data type items.
A = ['Chuck', 'Ana', 'Charlie', 'Josh']
for i in range(0, len(A)):
min_val = i
for j in range(i+1, len(A)):
if A[min_val] > A[j]:
min_val = j
Swapping the indexed and minimum value here.
(A[min_val], A[i]) = (A[i], A[min_val])
print("Sorted Array is :")
for i in range(len(A)):
print("%s" % A[i])
This works perfectly fine for an array of string datatype and sorts out the input data in an alphabetical way out.
As in the input 'Charlie' and 'Chuck' are being compared according to their alphabetical preference till the 3rd place and arranged accordingly.
The output of this program on python console is
Sorted Array is :
Ana
Charlie
Chuck
Josh
In the first part I am creating pairs out of array elements and the array is twice as short. The array is always even.
Here is the first part:
using System;
class Program
{
static void Main()
{
int[] Arr = new int[]{1, 2, 0, 3, 4, -1};
int[] newArr = new int[(Arr.Length / 2)];
int sum = 0;
for (int i = 0; i < Arr.Length; i+=2)
{
if (i + 1 < Arr.Length)
{
newArr[sum] = Arr[i] + Arr[i + 1];
}
else
{
newArr[sum] = Arr[i];
}
sum++;
}
in the second part I would like to check if the array elements are equal. What I want to do is to increment int counter each time the index in the for loop is equal to the next index in the array.
What I have as second part:
int counter = 0;
for (int i = 0; i < newArr.Length -1; i++)
{
if (newArr[i] == newArr[i + 1])
{
counter++;
}
else
{
Console.Write(" ");
}
}
What is wrong in this code. I cannot seem to understand how to write code that will work with int Arr[5] and int Arr[5000]
All you need to change is the termination condition in the for loop to
i < newArr.Length - 1
so that you can compare array[i] with array[i + 1]. This change makes sure you do not get past the upper bound of the array.
try this
for ( i=1;i<arr.Length;i++)
{
if(arr[0]==arr[i])
continue;
else
break;
}
if (i==arr.Length)
Console.WriteLine("All element in array are equal");
If there is no need to write so imperative code, other than to achieve your final goal – you don't have to. Almost always you can do it in a much more readable way.
I suggest using LINQ. For collections implementing IEnumerable<T>:
newArr.Distinct().Take(2).Count() == 1
LINQ is a built-in feature, just make sure you are using System.Linq; at the top of your .cs file.
What goes on here?
Distinct returns an IEnumerable<T>, its enumeration will give all distinct elements from your array, but no enumeration, and hence computation, happened yet.
Take returns new IEnumerable<T>, its enumeration will enumerate previous IEnumerable<T> internally, but it will give only first two distinct elements. Again, no enumeration happened yet.
At last, Count enumerates the last IEnumerable<T> and returns its elements count (in our case 0, 1 or 2).
As we used Take(2), the enumeration initiated by Count method will be stopped right when the second distinct element is found. If we don't use Take(2), our code will enumerate the whole array even if it is not needed.
Why is this approach better?
Much shorter and more readable;
Lazy evaluation – if an element is found out to be distinct from the other ones, the enumeration will be stopped immediately;
Flexible – you can pass a custom equality comparer to Distinct method. You can also call Select method before calling Distinct to choose what specific member your elements will be compared by;
Universal – Works with any collection which impletents IEnumerable<T> interface.
Other ways
The same result can be achieved in slightly other ways, for example:
!newArr.Distinct().Take(2).Skip(1).Any()
Experiment with LINQ and choose the way you and your team consider the most readable.
For collections implementing IList<T> you can also write (as #Alexander suggested):
newArr.All(x => x == newArr[0])
This variant is shorter but not as flexible and universal.
OFF TOPIC. Encapsulating common code
You should encapsulate code that does one simple thing into a separate method, it further improves your code readability and allows reusing your method in several places. I'd write an extension method for this one.
public static class CollectionExtensions {
public static bool AllElementsEqual<T>(this IEnumerable<T> items) {
return items.Distinct().Take(2).Count() == 1;
}
}
Later in your code you need just to call this method:
newArr.AllElementsEqual()
Try this..
for (int i = 0; i < newArr.Length-1; i++)
{
for(int j=0 ;j< newArr.Length-1; i++)
{
if (newArr[i] == newArr[j])
{
/////
}
}
}
else
{
Console.Write(" ");
}
}
main()
{
....
i = index;
while (i < j)
{
if (ip[i] == "/")
{
ip[i - 1] = (double.Parse(ip[i - 1]) / double.Parse(ip[i + 1])).ToString();
for (int k = i; k < (ip.Length - 2); k++)
{
ip[k] = ip[k + 2];
}
Array.Resize(ref ip, ip.Length - 2);
j = j - 2;
i--;
}
i++;
}
}
For the above code I wanted to apply Oop's concepts.
This pattern repeats almost 5 times (for div,mul,add,sub,pow) in main program, with four identical lines .
To decrease the no of lines and there by to increase efficiency of code, I wrote the same like this.
i = index;
while (i < j)
{
if (ip[i] == "/")
{
ip[i - 1] = (double.Parse(ip[i - 1]) / double.Parse(ip[i + 1])).ToString();
ext.Resize(ip, i, j);
}
i++;
}
class ext
{
public static void Resize(string [] ip, int i, int j)
{
for (int k = i; k < (ip.Length - 2); k++) { ip[k] = ip[k + 2]; }
Array.Resize(ref ip, ip.Length - 2);
j=j-2; i--;
return ;
}
}
Code got compiled successfully. But the problem is the changes in array and variables that took place in called function are not reflecting in main program. The array and variables are remaining unchanged in main program.
I am unable to understand where I went wrong.
Plz guide me.
Thank You.
I don't think you understand what ref parameters are for - once you understand those (and the fact that arrays themselves can't change in size), you'll see why Array.Resize takes a ref parameter. Have a look at my parameter passing article for details.
You can fix your code by changing it like this:
public static void Resize(ref string [] ip, ref int i)
{
for (int k = i; k < (ip.Length - 2); k++)
{
ip[k] = ip[k + 2];
}
Array.Resize(ref ip, ip.Length - 2);
j = j - 2;
i--;
}
and calling it like this:
ext.Resize(ref ip, ref i);
However, I suspect that using a more appropriate data structure would make your code clearer. Is there any reason you can't use a List<string> instead?
You're removing items from the middle of a sequence, so shrinking its length. So using arrays is just making it difficult.
If ip was a List<string> instead of string[]:
i = index;
while (i < j)
{
if (ip[i] == "/")
{
ip[i - 1] = (double.Parse(ip[i - 1]) / double.Parse(ip[i + 1])).ToString();
ip.RemoveAt(i);
ip.RemoveAt(i);
j = j - 2;
i--;
}
i++;
}
It looks like you're parsing an arithmetic expression. However, you might want to allow for parentheses to control the order of evaluation, and that's going to be tricky with this structure.
Update: What your code says is: You are going to scan through a sequence of strings. Anywhere in that sequence you may find a division operator symbol: /. If so, you assume that the things on either side of it can be parsed with double.Parse. But:
( 5 + 4 ) / ( 6 - 2 )
The tokens on either side of the / in this example are ) and ( so double.Parse isn't going to work.
So I'm really just checking that you have another layer of logic outside this that deals with parentheses. For example, perhaps you are using recursive descent first, and then only running the piece of code you posted on sequences that contain no parentheses.
If you want the whole thing to be more "objecty", you could treat the problem as one of turning a sequence of tokens into a tree. Each node in the tree can be evaluated. The root node's value is the value of the whole expression. A number is a really simple node that evaluates to the number value itself. An operator has two child nodes. Parenthesis groups would just disappear from the tree - they are used to guide how you build it. If I have some time later I could develop this into a short example.
And another question: how are you splitting the whole string into tokens?