Infinite Loop? Can't see why - c#

I have a function that takes in a roleID(as an int), and compares it to a multidimensional array to see if that array contains that roleID. if it does, it sets a bool to true and breaks. if it doesn't, the loop never exits. I'm hoping this is something stupid that I'm overlooking, but I've had a few different people look it over now.
The size of the userRoles array that I am testing with right now is 3. I can print userRoles.GetLength(0) and it says 3, and that matches whats in the database.
here's the code:
public bool IsInRole(int roleID)
{
bool inRole = false;
int i = userRoles.GetLength(0);
for (int j = 0; j < i; j++)
{
if (Convert.ToInt32(userRoles[j, 0]) == roleID)
{
inRole = true;
break;
}
}
return inRole;
}
TIA,
Chris

Are you sure that you're not misdiagnosing the symptom, and that it really is getting stuck in the loop? The code you have there doesn't look like wrong, my first thought would be that the place that you're calling IsInRole() isn't handling a 'false' return correctly.

Is j actually incrementing? or is it somehow being reset it back to 0?
Try this
public bool IsInRole(int roleID)
{
bool inRole = false;
int i = userRoles.GetLength(0);
for (int j = 0; j < i; j++)
{
int k = j;
if (Convert.ToInt32(userRoles[k, 0]) == roleID)
{
inRole = true;
break;
}
}
return inRole;
}

Looking at MSDN's GetLength property, to quote 'An example of GetLength is GetLength(0), which returns the number of elements in the first dimension of the Array.'
public bool IsInRole(int roleID)
{
bool inRole = false;
try{
int i = userRoles.GetLength(0);
for (int j = 0; j < i; j++)
{
if (Convert.ToInt32(userRoles[j, 0]) == roleID)
{
inRole = true;
break;
}
}
}catch(Exception up){
throw up;
}
return inRole;
}
I would be inclined to wrap the logic into a try/catch to see if the Convert.ToInt32 or GetLength(0) is throwing an exception...
Hope this helps,
Best regards,
Tom.

Your loop looks solid so it must be not exiting for a different reason. Could your array contain a value that would cause Convert.ToInt32 to hang or throw?

Related

Can I have an if statement change what variable is accessed in a loop

Hey I'm in a situation where I have a for loop that does some stuff and I want to make a line of code either call a function passing in an array indexed by the for loops index, or run a single (not array) variable for every call of that function, I know I could do that by putting an if statement inside the for loop but i'd be repeating the same if statement over and over getting the same result. So is there a way good way I can run the if statement before the for loop and the result of that if statement run the same for loop but that one call passes in the array or the variable?
Code Example
for (int i = 0; i < CurrentVerticalList.Count; i++)
{
GuiGeneral CGroup = CurrentVerticalList[i];
CGroup.ResizeUsingStandard(ForcedResize[i]); //I want the condition before the for
//loop to have ForcedResize[i] here if
//true and another variable here of the
//same type but not an array if false.
for (int j = 0; j < 2; j++)
{
GlobalListIndex[j]++;
}
CGroup.MoveElementTo(CCoord, false);
CCoord.y += CGroup.ElementRect.WidthHeight.y;
}
Here you go, moving your condition check out of your for loop:
Func<int, double> GetResizeFromForcedResize = (index => ForcedResize[index]);
Func<int, double> GetResizeFromVariable = (index => fixVariable);
var GetResizeValue = condition? GetResizeFromForcedResize : GetResizeFromVariable;
for (int i = 0; i < CurrentVerticalList.Count; i++)
{
GuiGeneral CGroup = CurrentVerticalList[i];
CGroup.ResizeUsingStandard(GetResizeValue(i));
for (int j = 0; j < 2; j++)
{
GlobalListIndex[j]++;
}
CGroup.MoveElementTo(CCoord, false);
CCoord.y += CGroup.ElementRect.WidthHeight.y;
}
Edit: Wanted to let you know that the other answers here are still doing a check at every iteration, but not this one.
Eh, hard to understand the question to me but i recon what you want is something along these lines, could've helped with more types supplied, but you could make the intend achievable using a local function:
ForcedResizeArrayType other = new object(); //TODO: Define return type
bool condition = ResolveCondition(); //TODO: Define condition to be true or false
ForcedResizeArrayType GetOneOr(int i, bool condition,
ForcedResizeArrayType[] forcedResizeArray)
{
return condition ? forcedResizeArray[i] : other;
}
for (int i = 0; i < CurrentVerticalList.Count; i++)
{
CGroup.ResizeUsingStandard(GetOneOr(i, condition, ForcedResize));
}
It varies from week to week if i love or hate those local functions, but they have uses

How can I remove duplicates from ScoreBoard array?

public void CheckForHighScore(){
finall = PlayerPrefs.GetInt("score");// taking score variable from another script to pass in ScoreBoard
for (int x = 0; x < highScores.Length; x++){
if (finall > highScoreValues[x]){
for (int y = highScores.Length - 1; y > x; y--) { //sorting
highScoreValues[y] = highScoreValues[y - 1];
}
highScoreValues[x] = finall;
DrawScores();
SaveScore();
PlayerPrefs.DeleteKey("score");
break;
}
}
}
void DrawScores() {
for (int x = 0; x < highScores.Length; x++) { // just adding score to string
highScores[x].text = highScoreValues[x].ToString();
}
}
Hey guys. How can I remove duplicates from ScoreBoard array? Tried myself to put this code below the sorting loop but actually nothing happens. I've also tried other methods but they don't work properly. Any help is appreciated.
/*for (int j = 1; j < x; j++)
{
if (highScoreValues[j] == highScoreValues[x])
break;
else
highScoreValues[x] = finall;
}*/
You can use linq.
If highscore is an object, you must override Equals and GetHashCode
public override bool Equals(object obj)
{
// Insert the Code to override
}
public override int GetHashCode()
{
// insert the Code to override
}
Be sure, that GetHashCode returns a unique integer for each object. For this way you can see more here: Correct way to override Equals() and GetHashCode()
If highScore is a primitives, you don't need to override the methods.
After you have unify highScore, you can use this:
var sorted = highScores.OrderByDescending(h => h).Distinct().ToArray();
List<*Insert type of score here*> cache = new List<*Insert type of score here*>();
for(int index = 0; index < highScores.Length; ++index)
{
if(cache.Contains(highScores[index]))
{
highScores.RemoveAt(index);
--index; // Every time you have to remove an item, it will slot the next item
// into that index and subtract 1 from highScores length. Thus you
// will have to decriment the index in order to check the item that
// gets pushed into that index of your highScore Array. You many
// need to check the syntax if highScores is not a List. But
// hopefully this helps :)
}
else
{
cache.Add(highScores[index]);
}
}
}
}

c# comparing two lists of integers in c#

I have two lists that is
List<int> comments ;
List<int> no_checks;
Now i would like to see if all no_checks have comments. So during my processing of data whenever a comment is added am adding its id to comment list and when a no radio is selected am adding its id to no_checks
So a sample output to console has
1.
below should return false;
comment=[12, 13,15]
no_checks = [12,13,15,17 ] //one no has no comment
2
below should return true
comment=[12, 13,15]
no_checks = [12,13 ] //all have comments
So am stuck here
public bool allnoHaveComments(){
var allhave=true;
for(var i=0; i<no_checks.count; i++){
//if one no_checks is not contained in comments allhave=false
}
return allhave;
}
How can i proceed to compare and check to see that id's in no_checks are all contained in comments else if they are not return false
How can i go about this
bool isallnoHaveComments= !no_checks.Except(comment).Any();
This gives you the values in no_checks that aren't in comments
no_checks.Except(comments)
Your problem is basically Check whether an array is a subset of another.
I have used here two for loops, one for comments list and the other for no_checks which is nested inside loop for comments
private bool check_Commentexist(List<int> comments, List<int> no_checks)
{
var j = 0;
var k = 0;
Boolean commentexist = false;
for (var i = 0; i < no_checks.Count; i++)
{
j = no_checks[i];
commentexist = false;
for (var x = 0; x < comments.Count; x++)
{
k = comments[x];
if (j == k) { commentexist = true; break; }
}
//if no match found for atleast on element break the loop
if (commentexist == false) break;
//else if match found the looping continues to check the
//next element in 'no_checks' for a mathcing comment
}
return commentexist;
}

C# Sorting Strings only on first letter

I'm trying to sort a list of strings in alphabetical order in C#. My code looks like this:
public static List<Result> sort(List<Result> listToSort)
{
int listSize = listToSort.Count;
for (int i = 0; i < listSize; i++)
{
for (int j = 0; j < listSize; j++)
{
if (listToSort[i].SN[0] < listToSort[j].SN[0])
{
Result tempValue = listToSort[j];
listToSort[j] = listToSort[i];
listToSort[i] = tempValue;
}
}
}
return listToSort;
}
But it's only sorting it based on the first letter of a string. In other words, if I have a list like this:
donald, abby, dave, bob, sam, pete
It will sort it like so:
abby, bob, donald, dave, pete, sam
One would expect 'dave' to come before 'donald'..
Any ideas?
Currently you are only sorting by the first letter that is why you are seeing this result. You can use Enumerable.OrderBy - LINQ
List<Result> sortedList = listToSort.OrderBy(r=> r.SN).ToList();
Or for your current code you can modify your check to:
if (string.Compare(listToSort[i].SN,listToSort[j].SN) < 0)
How about using LINQ for this:
return listToSort.OrderBy(report => report.SN)
I'm assuming your Report class has a string property you want the list to be sorted by?
EDIT
Didn't notice that you'd already specified the SN property, have amended my answer.
public static List<Result> sort(List<Result> listToSort)
{
return listToSort.OrderBy(x=>x.SN[0]).ToList();
}
You're only ever evaluating the first letter. Try using the traditional sorting method:
public static void Sort(List<Result> listToSort)
{
listToSort.Sort(new ResultComparator());
}
public class ResultComparator : IComparer<Result>
{
public int Compare(Result x, Result y)
{
if (x == null && y == null) return 0;
if (x == null) return 1;
if (y == null) return 0;
// compare based in SN
return string.Compare(x.SN, y.SN);
}
}
Take a look at this part:
for (int i = 0; i < listSize; i++)
{
for (int j = 0; j < listSize; j++)
{
if (listToSort[i].SN[0] < listToSort[j].SN[0])
{
You are
only comparing on SN[0]. If SN is a string then that explains your main result.
always using the same compare, whether i < j or i > j
Best thing to do is to use a built-in sort. Linq's OrderBy(lambda) is the easiest but it creates a new list. For an in-place sort, use List<T>.Sort(Comparer).
If you do have to do it yourself, look up a good sorting algorithm (wikipedia).
It was happened because of comparing character of the first string (listToSort[i].SN[0] => which produces the first character of your input). If you want to compare the string values, you should use string.Compare() method.
--SJ

comparing strings, one from an array other from an entered value

Basically comparing a string that is entered, and trying to get that position from the array.
If I initialize position to 0 then it returns the position zero of the array, if I initialize to 1 then it gives me the item in slot 1, so it's skipping the compare statement.
I also tried using (custStatus == cardStatus[i])
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
int position= 0;
int discount;
for(int i = 0; i < 2; i++)
{
if (string.Equals(custStatus, cardStatus[i]))
position = i;
}
discount = pDiscount[position];
return discount;
}
With your code, there's no way to tell if position = 0 means custStatus was found in your cardStatus array or if no match was made at all and the default value is being used. I'd recommend either using a boolean matchFound variable or setting position = -1 and adding an extra if statement at the end either way. Either:
boolean matchFound = false;
...
if(matchFound)
{
discount = pDiscount[position];
}
or else
int position = -1;
...
if(position >= 0)
{
discount = pDiscount[position];
}
Give this a try:
public static int discount(string[] cardStatus, int[] pDiscount, string custStatus) {
var position = Array.IndexOf(cardStatus, custStatus);
return (position == -1) ? -1 : pDiscount[position];
}
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
for(int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length); i++)
{
if (string.Equals(custStatus, cardStatus[i]))
{
return pDiscount[i];
}
}
return -1;
}
Don't be afraid to return directly from FOR-loop, it is old-school that teaches to have only one return point from method. You can have as many returns as it helps you to keep your code clean and easy to read.
And perhaps it would be better to use the following expression in for-loop as it will guard you from possible different lengths of arrays:
for (int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length; i++)
This looks ok, even though this is somewhat more straightforward:
for(int i = 0; i < cardStatus.Length; i++)
{
if (custStatus == cardStatus[i])
{
position = i;
break;
}
}
Given your question it appears to be the case that all cardStatus[i] match custStatus - did you check the input?
Also given your code what happens if there is no match? Currently you would return pDiscount[0] - that doesn't seem to be correct.

Categories

Resources