problem with converting numbers in textBox - c#

The code below belongs to a binary search algorithm. The user enters numbers in textbox1 and enters the number that he want to find with binarysearch in textbox2. When I enter for example 16 in textBox2 and put breakpoint on the line I commented, I see that the value of searchnum is 10.
I think it converts to hexadecimal. I don't know why. Can you help me?
private void button1_Click(object sender, EventArgs e)
{
string[] source = textBox1.Text.Split(',');
int[] nums = new int[source.Length];
for (int i = 0; i < source.Length; i++)
{
nums[i] = Convert.ToInt32(source[i]);
}
string str_searchnum = textBox2.Text;
int searchnum = Convert.ToInt32(str_searchnum); // str_searchnum shows the value 16 but searchnum shows 10
int first = 0;
int last = nums.Length - 1;
while (1 < nums.Length - 1)
{
int mid = (int)Math.Floor(first + last / 2.0);
////if (first < last)
////{
//// break;
////}
if (searchnum < nums[mid])
{
last = mid - 1;
}
if (searchnum > nums[mid])
{
first = mid + 1;
}
else
{
MessageBox.Show(nums[mid].ToString());
}
}
}

Check to see if the debugger is set to display values using hexadecimal notation? You can find this option by right clicking in the watch window.
If that's not it, step through the entire method. What is the value of str_searchnum?
Although I personally prefer int.TryParse(), Convert.ToInt32() should be well-tested and not be doing any base conversions.

Why not use Array.BinarySearch? Also, your loop condition is (probably) wrong.

Related

Increasing sequence in one dimensional array

You're given an array of integers,in case if you see subsequence in which each following bigger than the previous on one(2 3 4 5) you have to rewrite this subsequence in the resulting array like this 2 - 5 and then the rest of the array. So in general what is expected when you have 1 2 3 5 8 10 11 12 13 14 15 the output should be something like 1-3 5 8 10-15.
I have my own idea but can't really implement it so all I managed to do is:
static void CompactArray(int[] arr)
{
int[] newArr = new int[arr.length];
int l = 0;
for (int i = 0,k=1; i <arr.length ; i+=k,k=1) {
if(arr[i+1]==arr[i]+1)
{
int j = i;
while (arr[j+1]==arr[j]+1)
{
j++;
k++;
}
if (k>1)
{
}
}
else if(k==1)
{
newArr[i] = arr[i];
}
}
In short here I walk through the array and checking if next element is sum of one and previous array element and if so I'm starting to walk as long as condition is true and after that i just rewriting elements under indices and then move to the next.
I expect that people will help me to develop my own solution by giving me suggestions instead of throwing their own based on the tools which language provides because I had that situation on the russian forum and it didn't help me, and also I hope that my explanation is clear because eng isn't my native language so sorry for possible mistakes.
If I understand the problem correctly, you just need to print the result on the screen, so I'd start with declaring the variable which will hold our result string.
var result = string.Empty
Not using other array to store the state will help us keep the code clean and much more readable.
Let's now focus on the main logic. We'd like to loop over the array.
for (int i = 0; i < array.Length; i++)
{
// Let's store the initial index of current iteration.
var beginningIndex = i;
// Jump to the next element, as long as:
// - it exists (i + 1 < array.Length)
// - and it is greater from current element by 1 (array[i] == array[i+1] - 1)
while (i + 1 < array.Length && array[i] == array[i+1] - 1)
{
i++;
}
// If the current element is the same as the one we started with, add it to the result string.
if (i == beginningIndex)
{
result += $"{array[i]} ";
}
// If it is different element, add the range from beginning element to the one we ended with.
else
{
result += $"{array[beginningIndex]}-{array[i]} ";
}
}
All that's left is printing the result:
Console.WriteLine(result)
Combining it all together would make the whole function look like:
static void CompactArray(int[] array)
{
var result = string.Empty;
for (int i = 0; i < array.Length; i++)
{
var beginningIndex = i;
while (i + 1 < array.Length && array[i] == array[i+1] - 1)
{
i++;
}
if (i == beginningIndex)
{
result += $"{array[i]} ";
}
else
{
result += $"{array[beginningIndex]}-{array[i]} ";
}
}
Console.WriteLine(result);
}

Having the nth char based on a variable not working as expected

So I have pow - a list containing numbers. I have to examine other numbers like this: Get all the digits and sum the numbers from pow having the same index as the certain digit.
So if I check number 4552 I need to get pow[4]+pow[5]+pow[5]+pow[2]. Because I'm a noob I try to convert the number to string, get the characters with loop and then convert back to int to get the index. So the code is as follows for getting the sums between 4550 and 4559:
for (int i = 4550; i < 4560; i++)
{
int sum = 0;
for (int j = 0; j < i.ToString().Length; j++)
{
sum += pows[Convert.ToInt32(i.ToString()[j])]; //here is the error - index was out of range
//do something with sum (like store it in another list)
}
}
So what is wrong with that?
EDIT: To avoid confusion... pow has 10 elements, from indexes 0-9.
SOLUTION: The issue with my code was that I got the character code not the digit itself, thanks Steve Lillis. Though the solution provided by Dmitry Bychenko is far more superior to my attempt. Thank you all.
What you're looking for is similar to a digital root:
Modulus (% in C#) is easier and faster than conversion to string:
public static int DigitalRootIndex(IList<int> list, int value) {
if (value < 0)
value = -value;
int result = 0;
// for value == 4552
// result == list[4] + list[5] + list[5] + list[2]
while (value > 0) {
int index = value % 10;
result += list[index];
value /= 10;
}
return result;
}
...
int test = DigitalRootIndex(pow, 4552);
This bit of code gets a single character such as '4' which is character code 59:
c = i.ToString()[j]
Then this bit of code turns that char into an integer. It doesn't parse it like you're expecting, so the result for '4' is 59, not 4:
Convert.ToInt32(c)
Do this instead:
int.Parse(c.ToString())
Something like this (quick and dirty try)?
int currentDigit;
int sum;
for (int i = 4550; i < 4560; i++)
{
sum = 0;
currentDigit = i;
while (currentDigit > 0)
{
if (pow.Count > (currentDigit % 10))
{
sum += pow[((currentDigit % 10))];
}
}
}
Note that lists have zero based index so when you do pow[1], you are actually accessing second element in the list. Is that what you want?

C# Code Verification Program

Alright so I am making a program to verify a 4 digit code.
The computer generates a 4 digit code
The user types in a 4 digit code. Their guess.
the computer tells them how many digits are
guessed correctly in the correct place and how many digits have
been guessed correctly but in the wrong place.
The user gets 12 guesses to either win – guess the right code. Or
lose – run out of guesses.
So basically, my program doesn't seem to actually verify whether the code is correct but i cant see why not because i have if and for loops for verification, please take a look.
class Program
{
public static Random random = new Random();
static void Main(string[] args)
{
int DigitOne = random.Next(0, 10);
int DigitTwo = random.Next(0, 10);
int DigitThree = random.Next(0, 10);
int DigitFour = random.Next(0, 10);
byte[] code = new byte[4];
code[0] = Convert.ToByte(DigitOne);
code[1] = Convert.ToByte(DigitTwo);
code[2] = Convert.ToByte(DigitThree);
code[3] = Convert.ToByte(DigitFour);
bool CodeCorrect = false;
Console.WriteLine(code[0] +""+ code[1] +""+ code[2]+""+code [3] );
Console.WriteLine("You have 12 guesses before you will be permenantly locked out.\n");
int AmountOfGuesses = 0;
while (AmountOfGuesses < 12 && !CodeCorrect)
{
Console.WriteLine("Enter 4 digit code to unlock the safe: ");
int[] UserCode = new int[4];
for (int i = 0; i < 4; i++)
{
UserCode[i] = Convert.ToInt32(Console.Read()) - 48;
}
if (UserCode.Length != 4)
{
Console.WriteLine("Error. Try Again.\n");
}
else
{
int UserDigitOne = UserCode[0];
int UserDigitTwo = UserCode[1];
int UserDigitThree = UserCode[2];
int UserDigitFour = UserCode[3];
for (int i = 0; i < 4; i++)
{
if (UserCode[i] == code[i])
{
Console.WriteLine("The digit at position " + (i + 1) + " is correct.");
}
}
if (UserCode[0] == code[0] && UserCode[1] == code[1] && UserCode[2] == code[2] && UserCode[3] == code[3])
{
CodeCorrect = true;
Console.WriteLine("Code Correct. Safe unlocked.");
}
}
AmountOfGuesses++;
}
if (AmountOfGuesses > 12)
{
Console.WriteLine("Code Incorrect. Safe Locked permenantly.");
}
Console.ReadLine();
}
If you step through the code after it generated the number 1246, and then input the same number from the command line, convert it to a char array, then convert each char to a byte, you'll get the following four bytes:
49 50 52 54
These correspond to the ASCII representations of each char, NOT the actual numbers.
Try something like this:
int[] input = new int[4];
for(int i = 0; i < 4; i++ )
{
input[i] = Convert.ToInt32(Console.Read()) - 48;
}
The -48 should turn your ASCII code into the actual numerical representation that was provided. Console.Read() reads individual characters rather than the full line.
Also, you don't have to say:
CodeCorrect == false
This is more simply represented as:
!CodeCorrect
Similarly, if it was set to true, it would just be:
CodeCorrect
I also suggest using a for loop to set multiple elements in an array rather than manually writing out each line of code. It's not a big deal for small arrays, but it's good practice.
UPDATE: Here's a revised version of the full program:
class Program
{
public static Random random = new Random();
static void Main(string[] args)
{
int[] randCombination = new int[4];
for (int i = 0; i < 4; i++)
{
randCombination[i] = random.Next(0, 10);
Console.Write(randCombination[i].ToString());
}
bool CodeCorrect = false;
Console.WriteLine("\nYou have 12 guesses before you will be permenantly locked out.\n");
int AmountOfGuesses = 0;
while(AmountOfGuesses < 12 && !CodeCorrect)
{
Console.WriteLine("Enter 4 digit code to unlock the safe: ");
int[] UserCode = new int[4];
string input = Console.ReadLine();
int n;
bool isNumeric = int.TryParse(input, out n);
int correctCount = 0;
if(input.Length != 4 || !isNumeric)
{
Console.WriteLine("Error. Input code was not a 4 digit number.\n");
}
else
{
for(int i = 0; i < 4; i++)
{
UserCode[i] = Convert.ToInt32(input[i]) - 48;
if(UserCode[i] == randCombination[i])
{
Console.WriteLine("The digit at position " + (i + 1) + " is correct.");
correctCount++;
}
}
if(correctCount == 4)
{
CodeCorrect = true;
Console.WriteLine("Code Correct. Safe unlocked.");
}
}
AmountOfGuesses++;
}
if(AmountOfGuesses >= 12)
{
Console.WriteLine("Code Incorrect. Safe Locked permenantly.");
}
Console.ReadLine();
}
}
A couple of things were changed:
Added a for loop at the top that generates a random number, enters it into an array of ints and then prints it to standard output.
I changed the way user input is read back to the Console.ReadLine(). The reason for this is to check if the user inputted a four digit integer. the int.TryParse statement makes sure the input is an int, and the Length property checks the length.
I also used a counter to count each correct guess. If 4 correct digit guesses were made, the safe is unlocked.
Your final if statement would never have evaluated because Amount of Guesses would equal 12, not be greater than it. Changed it to >= from >. Always be on the lookout for small things like this.
EDIT #2: For more information on int.TryParse, see the following:
http://www.dotnetperls.com/int-tryparse
How the int.TryParse actually works
You are comparing numbers with the character representation of a number. Each value of code[] represents an actual number. You then compare those values with the values in UserCode which is a string, meaning there is a character at each index. It is never the case that ((byte)'4') == ((byte)4) (using 4 as an example, but works for any numerical digit).
One way around this is to parse each user input character into a byte using the byte.Parse method.
For fun learning purposes look at the output from the following code:
for (char i = '0'; i <= '9'; i++)
{
Console.WriteLine("char: " + i + "; value: " + ((byte)i));
}
The output is actually:
char: 0; value: 48
char: 1; value: 49
char: 2; value: 50
char: 3; value: 51
char: 4; value: 52
char: 5; value: 53
char: 6; value: 54
char: 7; value: 55
char: 8; value: 56
char: 9; value: 57
This is due to string encoding.
I would also recommend that one you have your code working that you submit it to the fine folks at the Code Review site to review other aspects of the code which could use work.

How can i check the index length in long[] array?

For example i have a long[] x
And im doing:
for (int i=0; i<x.length;x--)
{
}
I know that in x for example i have 30 indexs cells.
How can i loop over the cells(indexs) in the x array and find on each cell the length of it and also to get/show the numbers in each cell.
If in x[0] there is 232
And in x[1] there is 21
And so on...
I want to display 232,21,....etc
And then i want to check that if x[i].length is above 0 do...
But there is no x[i].length
So how do i do it ?
I did:
public long GetHistogramMaximum(long[] histogram)
{
long result = 0;
long count = 0;
for (int i = 0; i < histogram.Length; i++)
{
if (histogram[i] > 0)
{
MessageBox.Show(histogram[i].ToString());
break;
}
}
return result;
}
And its working but each time its showing me the number twice why the messagebox is working twice each time ?
If in the first array the number is 33454 then i see the messagebox once and then once again. Whats wrong here ? I want it to show me the number only once each time.
Its like repeating each number and show it once and then once again and only then moving to the next one.
EDIT **
Maybe the problem its showing the number twice each time have something to do with the scroll event im using ?
void trackBar1_Scroll(object sender, EventArgs e)
{
myTrackPanelss1.trackBar1.Minimum = 0;
myTrackPanelss1.trackBar1.Maximum = counter - 1;//list_of_histograms.Count-1;
long[] tt = list_of_histograms[myTrackPanelss1.trackBar1.Value];
histogramControl1.DrawHistogram(tt);
long res = GetTopLumAmount(tt, 1000);
long max = GetHistogramMaximum(tt);
if (res > -1)
label24.Text = (res / 1000.0).ToString();
setpicture(myTrackPanelss1.trackBar1.Value);
this.pictureBox1.Refresh();
}
For some reason its getting to the scroll and do everything here again. Twice in a row.
What can be the problem ?
A long[] basically holds a number of long values. Doing x[i].length is invalid, because a long does not have a property length. What is it that you are trying to achieve?
long[] x = {1,2,3} ;
x.length; //this is valid because you are querying the length / count of the array
x[0].length; //this is invalid because 1 does not have a property length
EDIT
Your loop counter will be the index. So,
for (int i =0; i < x.Length; i++)
{
//check for maximum, when you find it
Console.WriteLine("The maximum value is " + x[i]);
Console.WriteLine("The maximum value is present at index " + i);
}
As Michael says, you can find the length of the array via x.Length. In C#, x.Length (where x is an array) will return a 32-bit integer that represents the total number of elements across all dimensions. You only have a 1D array here, so that should be sufficient for what you're trying to achieve.
If you're also after the value stored in the array, the value is called as:
x[i];
So, in an example:
for ( int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
... would display the value in the array in your console.
Is that what you were asking?
Here is how to do something based on the values in the array.:
for (int i=0; i < x.Length; i++)
{
// print the number to the screen.
Console.WriteLine(x[i]);
if (x[i] > 0) {
// do something else.
}
}
I'm not sure what you meant by x--, but that's probably wrong from your description.
You could cast it to a string and get the length property.
x[i].ToString().Length
Although if you want to check if the length is above zero, then surely just the presence of a value proves this?
Your function has a terrible problem:
public long GetHistogramMaximum(long[] histogram)
{
long result = 0;
long count = 0;
for (int i = 0; i < histogram.Length; i++)
{
if (histogram[i] > 0)
{
MessageBox.Show(histogram[i].ToString());
break;
}
}
return result;
}
This way, you check the values in your array.
When i=0, it checks x[i]. So, 33454 (the value you gave in x[0]) is greater than 0, it shows the number and "break;", so it stops the "for" and do what's next: it returns the result variable that is never modified.
So variables result and count are useless in your code.
Rewrite with something that way for getting the maximum in your array:
public long GetHistogramMaximum(long[] histogram)
{
long result = 0;
for (int i = 0; i < histogram.Length; i++)
{
if (histogram[i] > result)
{
MessageBox.Show(string.Format("{0} is greater than {1}", histogram[i], result);
result = histogram[i];
}
}
return result;
}

A logical error with my code

I wrote this code and its always showing the same results why?
The code is a searching method.
using System;
using System.Collections.Generic;
using System.Text;
namespace CArraySe
{
class Program
{
class CArray
{
private int[] arr;
private int upper;
private int numElements;
private int compCount;
public CArray(int size)
{
arr = new int[size];
upper = size - 1;
numElements = 0;
compCount = 0;
}
public void Insert(int item)
{
arr[numElements] = item;
numElements++;
}
public void DisplayElements()
{
for (int i = 0; i <= upper; i++)
{
Console.Write(arr[i]);
if (i == upper)
{
Console.WriteLine();
continue;
}
Console.Write(", ");
}
}
public void Clear()
{
for (int i = 0; i <= upper; i++)
arr[i] = 0;
numElements = 0;
}
public bool SeqSearch(CArray n, int sValue)
{
for (int index = 0; index < n.upper; index++)
{
if (arr[index] == sValue)
return true;
}
compCount++;
return false;
}
public int binSearch(CArray n, int value)
{
int upperBound, lowerBound, mid;
upperBound = n.upper; lowerBound = 0;
while (lowerBound <= upperBound)
{
mid = (upperBound + lowerBound) / 2;
if (arr[mid] == value)
return mid;
else if (value < arr[mid]) upperBound = mid - 1;
else lowerBound = mid + 1;
}
compCount++;
return -1;
}
static void Main(string[] args)
{
CArray nums = new CArray(10);
Random rnd = new Random(100);
for (int i = 0; i < 10; i++)
nums.Insert((int)(rnd.NextDouble() * 100));
Console.WriteLine();
Console.Write("The Binary Search Result is: ");
Console.WriteLine(nums.binSearch(nums, 500));
Console.WriteLine(nums.compCount);
nums.Clear();
for (int i = 0; i < 10; i++)
nums.Insert((int)(rnd.NextDouble() * 100));
Console.Write("The Sequential Search result is: ");
Console.WriteLine(nums.SeqSearch(nums, 500));
Console.WriteLine(nums.compCount);
}
}
}
}
Its always showing the same result even if I changed the number I'm looking for.
The output is:
The Binary Search Result is: -1
1
The Sequential Search result is: False
2
Press any key to continue . . .
I think your value being searched for (500) is not being found. Try outputting the nums array and verifying that what you are looking for is in the array.
Plus, one search returns an int and the other returns a bool. Is there a specific reason for that?
Edit: Also, Binary Search only works with sorted lists.
Your method binSearch returns "-1" when the number isn't found. Since you're populating your array with random values, the odds are very good that the number you search for won't be found. So you're always getting "-1".
To test your binSearch method, you should populate the array with known values, then search for some value that is guaranteed to be in the array.
The first answer is correct. Also, even though you are using a random number, each run of the program will produce the same sequence of random numbers. You should seed it with a different number each time you run the program if you want to test the code well.
As the others have already mentioned, in the general case, there's no guarantee that the number you're searching for is in the list of randomly generated numbers. In the specific case that you posted, the number will never appear in the list because you're generating random numbers in the 0-100 range, then trying to find 500.
Running what you provided does not add a value above 100. If you change your add to this:
for (int i = 0; i < 9; i++)
nums.Insert((int)(rnd.NextDouble() * 100));
nums.Insert(500);
The binSearch returns 9, but the SeqSearch return false because your looping search is index < n.upper and you need to do index <= n.upper to check all values. Additionally, as noted above, the binSearch only works in this case because 500 is larger than all the numbers in the array and has been placed at the last index. The binary search will only work by luck if the list its searching is not sorted. Therefore changing to:
nums.Insert(500);
for (int i = 0; i < 9; i++)
nums.Insert((int)(rnd.NextDouble() * 100));
Will return -1; and true for the SeqSearch.
Although this probably doesn't answer your question directly, here are some observations which makes your code hard to understand and debug:
You need either one of numElements or upper, not both. In Clear(), you are setting only numElements to 0 whereas you are using upper in your loops everywhere?
Binary search works only with sorted arrays
If SeqSearch and BinSearch are receiving an instance of the array, shouldn't they be static methods instead of instance methods?

Categories