Range of a string program [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This is a program to get all the letters in a string in a specified range (in this case characters 3 through 7 of the word 'kangaroo').
Why am i getting an error at line arr[i] = x[start+i];?
I am not using Substring because my instructor wants us to figure out how to do it without it as an exercise.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MethodsPractice2
{
class Program
{
static char[] GetRangeOfCharacters(string word, int start, int end)
{
string x = word;
char[] arr = new char[end - start];
for (int i = 0; i < end; i++)
{
arr[i] = x[start + i];
}
return arr;
}
private static void Main(string[] args)
{
char[] endResult;
string word = "kangaroo";
int start = 3;
int end = 7;
endResult = GetRangeOfCharacters(word, start, end);
Console.WriteLine(endResult);
}
}
}

I'll explain the error you are getting,
You have said that you wish to start at character 3, and fill arr which is has 4 entries, with the characters that start at (3) + i
i can be any number less than 7.. 3 + 6 = 9; and Kangaroo has 8 letters in it... therefore you for loop at the minimum needs to go to
i < (end - start)
The other error could could get is i >= 4 in which case it would be trying to access arr[4] which is also out of range
0123456789
kangaroo
garo## /// what arr would be - # = error
garoo# // where i would get you - # = error

If you're looking for the easiest way to print part of the string, the easiest way, as mentioned in the comments, is with the String.Substring method.. To get characters #3-7 of the word kangaroo, you could use:
String.Substring(2,5);
The 2 is the starting index (it's 0-based, so 2 is the third character), and 5 is the length.
If you need the array of characters (as your return type indicates), you could try using the String.ToCharArray method, which functions the same way:
x.ToCharArray(2,5)

Because you take too many characters in the loop:
static char[] GetRangeOfCharacters(string word, int start, int end)
{
string x = word;
char[] arr = new char[end - start];
for (int i = 0; i < end; i++) // <--- here!!!
{
arr[i] = x[start + i];
}
return arr;
}
Correct would be
for (int i = 0; i < end - start; i++)
I would use this instead (skipped invalid argument check):
static char[] GetRangeOfCharacters(string word, int start, int end)
{
return word.Skip(start).Take(end - start).ToArray();
// or more efficient: word.Substring(start, end - start).ToCharArray();
}

end is 7 so you are looping from 0 to 7 and so going at subscripts 3 to 10
so
for (int i = 0; i < end; i++)
should be
for (int i = 0; i < (end - start); i++)
or perhaps even clearer
for (int i = 0; i < arr.Length; i++)

You're overflowing your array, arr[] by 1. Quanity (end-start) gives you one less than the size of your range.
You need to use quantity (end-start+1) to size your target array.

arr is an array with 4 slots (7 - 3).
But the code:
for (int i = 0; i < end; i++)
will loop 7 times (because end == 7), trying to write to a new position of arr on every iteration.
Q: How can you store 7 distinct values to an array with only 4 slots?
A: You can't!
(Your for-loop needs different constraints).

Well end is 7, start is 3. 3 + 6 is 9. Kangaroo is only of length 8 so you're gonna get an index out of range exception (looping while i < end, and adding i to start to get the index). As others have suggested you should use substring instead of your current method.
string subString;
if (end - start < 0)
subString = null; // error!
else
subString = myWord.SubString(start, end - start);
Might also want to check that start and end are both less than myWord.Length

Related

Skipping a range of values in for loop C#

I'm trying to cycle through chars in a string.
string cycleMe = "Hi StackOverflow! Here is my string."
However, I want to skip over certain ranges of indexes. The ranges I want to skip over are stored in a List of objects, delims.
List<Delim> delims = delimCreator();
To retrieve each starting index and ending index for a range, I have to write a loop that accesses each "delim":
delims[0].getFirstIndex() //results in, say, index 2
delims[0].getLastIndex() //results in, say, index 4
delims[1].getFirstIndex() //results in, say, index 5
delims[1].getLastIndex() //results in, say, index 7
(there can be infinitely many "delim" objects in play)
If the above were my list, I'd want to print the string cycleMe, but skip all the chars between 2 and 4 (inclusive) and 5 and 7 (inclusive).
Expected output using the numbers above:
HiOverflow! Here is my string.
Here is the code I have written so far. It loops far more often than I'd expect (it loops ~x2 the number of characters in the string). Thanks in advance! =)
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
Debug.Log("test");
}
}
I assume that by skipping you meant you want to omit those characters from the original string. If that is the case, you can try Aggregate extension method like below.
string result = delims.Aggregate<Delim, string>(cycleMe, (str, d) => cycleMe = cycleMe.Remove(d.FirstIndex, (d.LastIndex - d.FirstIndex) + 1));
Make sure that the delim list is in the proper order.
Solution might be converting the string to char array, replacing the desired parts to spaces, and converting the output back to string.
Here is the modified version of your code:
string cycleMe = "Hi StackOverflow! Here is my string."
var charArray = cycleMe.ToCharArray(); // Converting to char array
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
// ORIGINAL: if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
if (x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex()){
Debug.Log("test");
charArray[x] = ' '; // Replacing the item with space
}
}
string output = new string(charArray); // Converting back to string
P.S. This is probably not the most optimal solution but at least it should work.
You should use LINQ for that
struct Delim
{
public int First { get; set; }
public int Last { get; set; }
}
static void Main(string[] args)
{
string cycleMe = "Hi StackOverflow! Here is my string.";
var delimns = new List<Delim> { new Delim { First=2, Last=4}, new Delim { First = 5, Last = 7 } };
var cut = cycleMe.Where((c, i) =>
!delimns.Any(d => i >= d.First && i <= d.Last));
Console.WriteLine(new string(cut.ToArray());
}
That means I am basically only selecting letters, at positions which are not part of any cutting range.
Also: Fix your naming. A delimiter is a character, not a position (numeric)

Longest Ascending Sequence C#

So I am quite new to C# and having face a problem which requires me to:
Search the longest ascending sequence of integers in an array of integers. As sequence of elements xi (1 ≤ i ≤ n) is ascending if xi < xi+1 for all i (1 ≤ i ≤ n - 1). The size of the array is to be chosen by the user. Values of the array are random numbers are between 0 and 1000 generated by the computer. The program shall print the start index and the length of the longest ascending sequence.
Here are my code so far (I can only sort array in ascending order):
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace AscendingSequences
{
class AscendingSequences
{
public static void Main(string[] args)
{
Console.WriteLine("Ascending Sequence!");
GenerateNumber();
}
public static void GenerateNumber()
{
int i, j, n, number;
int[] array = new int[100];
int[] array1 = new int[100];
Random random = new Random();
Console.Write("\nInput the number of element to be store in the array: ");
n = Convert.ToInt32(Console.ReadLine());
Console.Write("\nThe {0} array is generating-----\n", n);
for (i = 0; i < n; i++)
{
array[i] = random.Next(1, 20);
Console.Write("\nThe array|{0}| is {1} ", i, array[i]);
}
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
if(array[j] < array[i])
{
number = array[i];
array[i] = array[j];
array[j] = number;
}
}
}
Console.Write("\nElements of array in sorted ascending order is: ");
for(i=0; i<n;i++)
{
Console.Write("{0} ", array[i]);
}
}
}
}
This is the assignment given to me:
your approach to first order the array was wrong and that caused some people to be confused unfortunately.
if you start by ordering your array you lose the information of the original location of these elements which are important. Instead you should loop through your array and do a check if the current element is bigger than the previous one(ascending).
//start and length are the "current" values and max are the max found
int start = 0, length = 0, maxstart = 0, maxlength = 0;
//loop through array (starting from index 1 to avoid out of bounds)
for (int i = 1; i < array.Length; i++)
{
//check if current sequence is longer than previously recorded
if (length > maxlength)
{
maxstart = start;
maxlength = length;
}
//if previous element <= to current element
if (array[i - 1] <= array[i])
{
//if the current element isn't part of the current sequence, then start a new sequence
if (start + length < i)
{
start = i - 1;
length = 2;
}
else
{
//count the length
length++;
}
}
}
Here is a .net fiddle with working code:
https://dotnetfiddle.net/1GLmEB
EDIT:
to reply to your question in the comments on how this works start + length < i
This condition checks if the current value is part of the sequence.
The variable start is the start of the last/current found sequence and length is the length.
When this condition returns true it means it falls outside the last found sequence and it resets the values of start and length(true = outside, false = inside)
So lets go through some cases and see why this works:
1 2 3 1 1 2 3 1 1
* > > > e ^
start = 3 (*)
length = 4 (>)
i = 8 (^)
3+4 = e
3+4<8 //true : new sequence
so the last found sequence started at 3 and was 4 long.
this means that this sequence will end at index 7.
since we are currently checking for index 8 in our loop we can see that it isn't part of the same sequence.
1 2 3 1 1 2 3 4 1
* > > > > ê
start = 3 (*)
length = 5 (>)
i = 8 (^)
3+4 = e
3+5<8 //false : current sequence
so the last found sequence started at 3 and was 5 long.
this means that this sequence will end at index 8.
since we are currently checking for index 8 in our loop we can see that it is part of the same sequence.
in hindsight it might have been less confusing if this if statement was turned around (true = inside, false = outside). However I won't change the code now to avoid further confusion.

How to make only chosen characters uppercase in C# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I want to make every other letter uppercase, how do I do that?
Code:
String a = ("aábdeéðfghiíjklmnoóprstuúvxyýþæö");
for (int i=0; i < a.Length; i++)
{
Console.Write(a.ToUpper()[i]+ ",");
}
Using Linq:
string a = "aábdeéðfghiíjklmnoóprstuúvxyýþæö";
var converted =
new string(a.Select((ch, i) => ((i % 2) == 0) ? ch : Char.ToUpper(ch)).ToArray());
Console.WriteLine(converted);
Increment your loop by 2.
Example:
String a = ("aábdeéðfghiíjklmnoóprstuúvxyýþæö");
for (int i=0; i<a.Length; i+=2)
Console.Write(a.ToUpper()[i]+ ",");
For every even alphabet start loop from 0 and for odd start from 1.
Linq answer is very good and has the advantage to be one liner, but a normal loop here is twice faster than the Linq solution
char[] a = "aábdeéðfghiíjklmnoóprstuúvxyýþæö".ToCharArray();
for (int i = 0; i < a.Length; i++)
{
if (i % 2 != 0)
{
a[i] = Char.ToUpper(a[i]);
}
}
string result = new string(a);
Using LINQ to go through each char in the string. If it is divisible by 2 then that means its every other letter. So make that upper case, if not divisible by 2 then leave it as it is. Rejoin all the chars together in an array then convert that back into a string.
String a = ("aábdeéðfghiíjklmnoóprstuúvxyýþæö");
var convertedString = new string(a
.Select((c, i) => (i + 1) % 2 == 0 ? Char.ToUpper(c) : c)
.ToArray());
String a = ("aábdeéðfghiíjklmnoóprstuúvxyýþæö");
for (int i=0; i<a.Length; i++)
{
if (i % 2 == 0)
{
a = a.Substring(0, i) + a.Substring(i, 1).ToUpper() + a.Substring(i);
}
}
The % symbol is modulo, in this context if the index if divisible by 2 make the symbol upper case.
EDIT: as correctly pointed out, string are immutable, I've edited appropriately. This most likely isn't the most efficient way of doing this, I'd recommend using LINQ for a more efficient algorithm
You can use Linq.
string oldString = "aábdeéðfghiíjklmnoóprstuúvxyýþæö";
string alternatedString = string.Concat(
oldString.ToLower().Select((character, index) => index % 2 == 0 ? character : char.ToUpper(character)));
Output: aÁbDeÉðFgHiÍjKlMnOóPrStUúVxYýÞæÖ
Or
string oldString = "aábdeéðfghiíjklmnoóprstuúvxyýþæö";
StringBuilder alternatedString = new StringBuilder();
for(int index=0; index<oldString.Length; index++)
{
if(index % 2 == 0)
alternatedString.Append(oldString[index].ToString().ToLower());
else
alternatedString.Append(oldString[index].ToString().ToUpper());
}
Output: aÁbDeÉðFgHiÍjKlMnOóPrStUúVxYýÞæÖ

Index Out Of Range while comparing two array elements [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 7 years ago.
This is a part of a bigger problem I'm trying to solve, but index out of range exception seems to be an invisible hurdle to me.
This if loop works well in c++ but in c#, idk whats happening. Any help is appreciated. This is very important to me. Please find the root for this exception.
namespace damn
{
class Program
{
static void Main(string[] args)
{
string InputString = Console.ReadLine();
string[] stringArray = InputString.Split(',');
int[] intArray = new int[stringArray.Length];
for (int i = 0; i < stringArray.Length; i++)
{
intArray[i] = int.Parse(stringArray[i]);
}
int length = stringArray.Length;
for(int i=0; i<length; i++)
{
if (intArray[i] > intArray[i + 1])
Console.WriteLine("ok");
else
Console.WriteLine("not ok");
}
}
IndexOutOfRangeException was unhandeled.But how? the logic is right, ain't it?
Call me a noob or what ever, this is not the actual program, but a part of it.
input sample -
1,2,3,4 [/enter/]
You have int Array[i + 1] where i goes one less than length so for last item you will have out of range as array is zero-based index; end loop 2 less then length so that intArray[i + 1] wont go out of range.
for(int i=0; i<length-1; i++)
your second loop is out of range doens't matter if you're using C++ or C#. it's just that iin C++ you have to manage your own memory space and it doesn't throw index out of range error; so you need to know when to stop in C++.
Let's get back to your code:
for(int i=0; i<length; i++)
{
if (intArray[i] > intArray[i + 1])
Console.WriteLine("ok");
else
Console.WriteLine("not ok");
}
When i == length - 1 which is your last true condition, i+1 is out of range of the array because i + 1 = length; and in C# index starts from 0.
to fix just simply change your second loop condition to i < length - 1 instead of i < length

Linear Search Problem [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
My program has no compile errors but the output is incorrect. Example input:
size of array: 5
input numbers: 5 4 3 2 1
//sorted: 1 2 3 4 5
search: 1
output: number 1 found at index 4
the output should be number 1 found at index 0 since the numbers were sorted already. How will I change it to this.
int[] nums = new int[100];
int SizeNum;
bool isNum = false;
private void ExeButton_Click(object sender, EventArgs e)
{
int i, loc, key;
Boolean found = false;
string SizeString = SizeTextBox.Text;
isNum = Int32.TryParse(SizeString, out SizeNum);
string[] numsInString = EntNum.Text.Split(' '); //split values in textbox
for (int j = 0; j < numsInString.Length; j++)
{
nums[j] = int.Parse(numsInString[j]);
}
if (SizeNum == numsInString.Length)
{
Array.Sort(numsInString);
key = int.Parse(SearchTextBox.Text);
ResultText.AppendText("Sorted: ");
for (i = 0; i < SizeNum; i++)
ResultText.AppendText(" " + numsInString[i]);
ResultText.AppendText("\n\n");
{
for (loc = 0; loc < SizeNum; loc++)
{
if (nums[loc] == key)
{
found = true;
break;
}
}
if (found == true)
ResultText.AppendText("Number " + key + " Found At Index [" + loc + "]\n\n");
else
ResultText.AppendText("Number " + key + " Not Found!\n\n");
}
}
}
You're sorting numsInString but then searching nums. nums is being populated before the search, so you're seeing the results of searching the unsorted numbers.
Once you've parsed numsInStrings into nums, you should be working with the latter array only. Make sure that's the one you're sorting and searching through.
In other words, once you replace the current sort call with
Array.Sort(nums);
your code will be fine.
Updated:
You actually need another fix. Right now, you're initializing nums to be an array of size 100. By default, each element will be 0. So even though you put numbers in the first five elements, when you sort the array, you end up with 95 0's, followed by 1 2 3 4 5.
You should delay initializing nums until you've seen how big numsInString is:
string[] numsInString = EntNum.Text.Split(' '); //split values in textbox
nums = new int[numsInString.Length];
for (int j = 0; j < numsInString.Length; j++)
{
nums[j] = int.Parse(numsInString[j]);
}
Now when you sort nums, you'll see only the numbers you entered.
you are sorting the numsInString array, but still searching into the nums array.
for (loc = 0; loc < SizeNum; loc++)
{
if (numsInString[loc] == key)
{
found = true;
break;
}
}
You're parsing numsInString then you're sorting it. (I suspect the sort won't do what you want, either.)
I think you really want to be sorting nums instead:
Array.Sort(nums);
Having said that, there are simpler ways of achieving the end result - such as using IndexOf to find the index of a value in an array.
It's also rather unclear why you've got braces here:
for (i = 0; i < SizeNum; i++)
ResultText.AppendText(" " + numsInString[i]);
ResultText.AppendText("\n\n");
{
...
}
That makes it look like you've got a loop with a body, but it's actually equivalent to:
for (i = 0; i < SizeNum; i++)
{
ResultText.AppendText(" " + numsInString[i]);
}
ResultText.AppendText("\n\n");
{
...
}
... the braces serve no purpose here, and merely harm readability.

Categories