I have a simple program that is used to pass inputs to an array given the inputted size and inputted elements by the user as follows:
Full code
All the code works fine except this snippet :
for(int i=0; i<size; i++) {
flagger = false;
while(flagger == false) {
System.Console.WriteLine("Please enter number " + i + " : ");
nextInput = System.Console.ReadLine();
flagger = errorCheck(nextInput);
}
int varPass = System.Convert.ToInt32(nextInput);
System.Console.WriteLine(flagger);
arr[i] = varPass;
}
No matter what size I input the loop exits early and sorts an array with some empty elements, can anyone see the problem?
In errorCheck you're setting the value of size as you're passing it in the out parameter.
So the next time the user inputs a number smaller than i the loop exits early.
Create a dummy int or handle your error checking differently.
Example:
static bool errorCheck(string input) {
int temp=0;
if (int.TryParse(input, out temp))
return true;
return false;
}
This "bug" happens because size is static.
You can simplify your code further by just returning the result of TryParse.
static bool checkErr(string input) {
int temp=0;
return int.TryParse(input, out temp);
}
You haven't included errorCheck method which seems crucial to me.
If errorCheck returns true the Loop WILL end prematurely.
EDIT: Oops, you did include a link to full code.
As my predecessor said, errorCheck(...) modifies "size". Maybe that's why I still prefix member variables with underscore. It's so easy to miss.
Related
I am trying to write a program that lets me enter a list of names with their respective film rating into an array (Would do a list but the course material wants me to use array). Before I add the names to the array I want to make sure that a valid rating has been entered.
I am currently using a for statement that cycles through he array length and lets the user enter each movie to the list that way. This happens in a while loop to make them re-enter the name if the rating is invalid before the name is committed to Array. I check the names by calling a method with a temporary string assigned with the current entered name and rating which will do some conditional checks and return either false or true depending on the outcome. But the way I am doing it is not working at all..
Problem is that I have no idea how to make practical use of the bool statement my method returns:
string[] filmNames = new string[ArrayLength];
for (int i = 0; i < filmNames.Length; i = i + 1)
{
bool ratingFail = true;
int displayNumber = i + 1;
while (ratingFail)
{
Console.Write($"> Enter the Name and Rating of film number {displayNumber} of {ArrayLength}: ");
string checkRating = Console.ReadLine();
CheckRating(checkRating); // currently just does "return false;" for testing purposes
if (true) // this statement is clearly not effected by whatever the return value is from above method. Why? What to do?
{
ratingFail = true;
}
else
{
filmNames[i] = checkRating; // this bit is marked as unreachable, which is is.
ratingFail = false;
}
}
}
my test method:
public static bool CheckRating(string checkRating)
{
return false;
}
I am VERY (a week) new to programming and C# so please keep in mind when answering that I may not understand particular lingo referring to programming terms outside of the scope of what you can see here within, but I will Google and research to the best of my abilities if there is no way to simplify what you want to say. Thank you for your time and effort.
if (true) // this statement is clearly not effected by whatever the return value is from above method. Why? What to do?
{
ratingFail = true;
}
This will always be true, because you're creating a variable that is always true. You want this:
ratingFail = CheckRating(checkRating)
if (!ratingFail) {
The rating is valid, do stuff here.
}
If ratingFail is true, the loop will continue.
This assumes that CheckRating returns true if the input is invalid, and false if it is valid. The variable naming here is pretty confusing, and I recommend you refactor.
I would do it this way, assuming CheckRating returns true if valid:
for (int i = 0; i < filmNames.Length; i = i + 1)
{
bool ratingValid; // Defaults to false
int displayNumber = i + 1;
while (!ratingValid)
{
Console.Write($"> Blablabla: ");
string input = Console.ReadLine();
ratingValid = CheckRating(input);
}
// Do stuff if rating is valid here. If you got here, rating is valid.
}
// edit by iluvpancakes //
I decided to add a comment made by #Sinatr since that was the (version of the) solution I personally ended up using:
if(CheckRating(checkRating))
{
[do stuff and things]
}
bool ret = CheckRating(checkRating); // currently just does "return false;" for testing purposes
if (ret)
{
[...]
}
Or, like Sinatr's comment:
if(CheckRating(checkRating))
{
[...]
}
I'm now done with the basics of my code, and it works like it should. But now i want to add a try-catch exception so that if the user put is anything else than integers, it will throw an exception and say something like: Wrong input try again. Here is where i need it:
for (int i = 0; i < nummer.Length; i++)
{
Console.Write("Nummer " + talnr + ": ");
talnr++;
string str = Console.ReadLine();
int element = Convert.ToInt32(str);
nummer[i] = element;
}
The loop will loop 10 times and store the inputs in an array. When i try it either makes an exception but contiues the loop or breaks the loop and goes on to the next block of code..
I would favour the use of...
bool parsed = Int.TryParse(str, out myInt);
If (parsed)
{
// do something
}
IMHO, a try/catch block should only really be used when there is a possibility on an unhandled exception (e.g. something volatile such as filesystem interaction) that cannot be "predicted" so as to handle accordingly (e.g. log errors etc.) and then continue without crashing your program.
Always try and handle a "known" with the methods and functions available in the framework to do so.
What you're trying to do doesn't require a try-catch. You can use the TryParse method to check whether the desired input is a properly formed integer, and prompt the user to enter a different input.
for (int i = 0; i < nummer.Length; i++)
{
bool isAnInteger = false;
int element = 0;
Console.Write("Nummer " + talnr + ": ");
talnr++;
string str = Console.ReadLine();
// evaluates to true if str can be parsed as an int, false otherwise
// and outputs the parsed int to element
isAnInteger = int.TryParse(str, out element);
while (!isAnInteger)
{
Console.Write("Wrong input, try again. ");
str = Console.ReadLine();
isAnInteger = int.TryParse(str, out element);
}
nummer[i] = element;
}
Use the int.TryParse method.
This code reads the trimmed input string from the user and tries to convert it to an integer. If the conversion is successful, it creates an integer variable called "result" which you can then use in the IF block. If the conversion fails, you can write the code for what you want to happen in the ELSE block. If you need a total of 10 integers in the list, I would drop the FOR loop in favor of a DO WHILE loop that checks for how many integers were successfully converted and added to the list. It will keep requesting input until the list is filled with 10 integers.
List<int> elements = new List<int>();
do
{
Console.WriteLine("Please enter an integer.");
if (int.TryParse(Console.ReadLine().Trim(), out int result))
{
Console.WriteLine($"You entered the integer {result}");
elements.Add(result);
}
else
{
Console.WriteLine("You must enter an integer. Please try again.");
}
} while (elements.Count < 10);
If you want to keep your code with the try catch loop here it is:
for (int i = 0; i < nummer.Length; i++)
{
try {
Console.Write("Nummer " + talnr + ": ");
talnr++;
string str = Console.ReadLine();
int element = Convert.ToInt32(str);
nummer[i] = element;
}
catch
{
MessageBox.Show("Error, numbers only");
goto breakloop;
}
}
breakloop:;
The goto statement ends the loop if an error occured
It's a good idea to not throw exceptions at all if you can help it. In this case, you can use int.TryParse() instead. This block of code can replace your one int element... line:
int element;
if (!int.TryParse(str, out element)) {
Console.WriteLine("Bad!!");
i--;
continue;
}
The i-- is to make sure that i has the same value on the next interaction of the loop. Doing that will make sure you still get 10 valid inputs before you finish the loop. (Many will say this is a really bad thing to do, but the reason for that is readability - if you have a large for loop and decrement the value somewhere in the middle, it makes it difficult for the next guy looking at your code to understand exactly what's going on. But this is a short loop, so it's pretty obvious. Just be aware of this.)
The continue keyword skips the rest of that iteration of the loop and moves on to the next (so you don't add the bad value to your array).
With some help I have managed to get the right answer to these questions but I want to get my head around the concepts (i.e. understanding why these codes are correct), as understanding is very important and not just memory of syntax.
The first question is You're given the result of 3 competitions (true = win) , the prize for the first is 1, second is 2, third is 3. Return the total prize amount (you can win any combination of prizes)
The answer is:
public static int GetTotalPrize(bool first, bool second, bool third)
{
var result = 0;
if (first)
{ result += 1; }
if (second)
{ result += 2; }
if (third)
{ result += 3; }
return result;
}
How does the program know that if you were to win, let's say, the first, second and third prizes, that the total is 6? Or if you were to win the first and third, the total is 4? In other words, how does the code above account for all possible combinations?
The second question is You're given the result of 3 competitions in one of which you've won (true = win). The prize for the first is 1, second is 2, third is 3. Return the prize amount.
My answer is:
public static int GetPrize(bool first, bool second, bool third)
{
if (first)
return 1;
if (second)
return 2;
if (third)
return 3;
return 0;
}
Without the "return 0;" part at the end, my code was shown as incorrect. Why? As the question states that I have won one of the prizes, so in other words, I am not leaving the competition empty-handed.
Thanks in advance
Well, lets take it step by step.
First answer:
public static int GetTotalPrize(bool first, bool second, bool third)
{
var result = 0;
if (first)
{ result += 1; }
if (second)
{ result += 2; }
if (third)
{ result += 3; }
return result;
}
What happens here is the following:
The variable result is initialized with a value of 0.
What follows is a series of if statements. Notice how they are only if and not if-else, meaning they are not mutually exclusive.
When an if statement is true, then result += [some number] happens. This means that result is assigned the value (result + [some number]).
Finally, result is returned.
Second answer:
public static int GetPrize(bool first, bool second, bool third)
{
if (first)
return 1;
if (second)
return 2;
if (third)
return 3;
return 0;
}
Over here you are told that you have won one of them for sure. If you have not won the first, then you could have won the second or the third. If you have also not won the second, then you must have won the third. So the correct code would be:
if (first)
return 1;
else if (second)
return 2;
else
return 3;
In this case, the if statements are mutually exclusive, since you are told you have won one of them. Unlike the first answer, this syntax guarantees that one of the values (1, 2, or 3) will be returned.
The return guarantee is important because you have defined your function as having return type int. This means that, no matter what happens in the code, it will always return an int. In your code, if it weren't for the return 0, then there would be no return statement if all ifs were false. Of course, you are told that at least one will be true. The compiler however doesn't know that, and so it won't let you compile a function that doesn't fulfill the requirement of always returning a value.
The first piece of code works as follows (reading as pseudocode)
define a numer named result
set its value to 0
if the parameter (first) equals true, add 1 to result
[do this again for (second), and (third), but with their respective numeric values]
return result
it just counts the score, then returns it.
The second part of your question :
you defined your method as guaranteeing to return an int. thus, you cannot write the method without following up on that guarantee. you cannot return NOTHING (void), or the compiler will complain.
you also cannot return null , since an int is not nullable.
If we took the logic of your second question, and were told to make it capable of accepting any number of rounds, the reason for that last return statement might become more obvious:
public static int GetPrize(params bool[] scores)
{
for (int i = 0; i < scores.Length; i++)
{
if (scores[i]) // there is no guarantee any of the bools passed along equals true, so we might never hit this return statement.
return i + 1;
}
//if we never hit the first return statment,
//we will end up here, and will not have won anything.
//we still need to return an int, though.
return 0;
}
I need to compare 2 strings using a For without using String.compare. (It's a homework ... I started programming C# 2 weeks ago)
I just can't figure out how to use the for loop to answer the question. I don't know what to put in for(). I tried for( string text1 = "something",) but I can't figure out what toput after the, in the for loop.
Since this is a homework question, I would recommend stop reading the answer as soon as you think you have enough information to solve it on your own before getting to the solution at the end.
Let's assume a simple method signature, first:
public static bool AreStringEqual(string str1, string str2)
{
}
And our goal is to implement (write the code for) this method. We'll assume our goal is Return true if the strings are equal, and return false if they are not. We won't do anything fancy like make it case insensitive.
We can do some basic checks on our strings, first. If they are of different length, then we can immediately assume the strings are different, and return false:
if (str1.Length != str2.Length)
{
return false;
}
This block checks the length, and if they differ, then false is immediately returned and the rest of the method doesn't get executed.
At this point we can guarantee the strings are the same length, so we can loop over the strings and compare them character by character using a for loop.
for(int counter = 0; counter < str1.Length; counter++)
{
}
This is a pretty standard for-loop that just counts a number from zero to one less than the length of the string. It doesn't matter if we use str1 or str2 for the upper bound of the loop since we already know they are the same length.
To get the character in a string, we can use the Indexer Syntax to get the character at a give position. The numbers start at zero in C# and .NET.
str1[0] gets the first character, str1[1] gets the second, etc.
We can then plug the variable in the for loop into the indexer for str1 and str2, then compare the characters. If they are not equal, then return false.
for(int counter = 0; counter < str1.Length; counter++)
{
if (str1[counter] != str2[counter])
{
return false;
}
}
And finally, if the code gets through the for loop without returning false, then return true at the end. Putting it all together, it looks like this:
public static bool AreStringEqual(string str1, string str2)
{
if (str1.Length != str2.Length)
{
return false;
}
for(int counter = 0; counter < str1.Length; counter++)
{
if (str1[counter] != str2[counter])
{
return false;
}
}
return true;
}
I just want to know, whether a String variable contains a parsable positive integer value. I do NOT want to parse the value right now.
Currently I am doing:
int parsedId;
if (
(String.IsNullOrEmpty(myStringVariable) ||
(!uint.TryParse(myStringVariable, out parsedId))
)
{//..show error message}
This is ugly - How to be more concise?
Note: I know about extension methods, but I wonder if there is something built-in.
You could use char.IsDigit:
bool isIntString = "your string".All(char.IsDigit)
Will return true if the string is a number
bool containsInt = "your string".Any(char.IsDigit)
Will return true if the string contains a digit
Assuming you want to check that all characters in the string are digits, you could use the Enumerable.All Extension Method with the Char.IsDigit Method as follows:
bool allCharactersInStringAreDigits = myStringVariable.All(char.IsDigit);
Maybe this can help
string input = "hello123world";
bool isDigitPresent = input.Any(c => char.IsDigit(c));
answer from msdn.
You can check if string contains numbers only:
Regex.IsMatch(myStringVariable, #"^-?\d+$")
But number can be bigger than Int32.MaxValue or less than Int32.MinValue - you should keep that in mind.
Another option - create extension method and move ugly code there:
public static bool IsInteger(this string s)
{
if (String.IsNullOrEmpty(s))
return false;
int i;
return Int32.TryParse(s, out i);
}
That will make your code more clean:
if (myStringVariable.IsInteger())
// ...
This work for me.
("your string goes here").All(char.IsDigit)
Sorry, didn't quite get your question. So something like this?
str.ToCharArray().Any(char.IsDigit);
Or does the value have to be an integer completely, without any additional strings?
if(str.ToCharArray().All(char.IsDigit(c));
string text = Console.ReadLine();
bool isNumber = false;
for (int i = 0; i < text.Length; i++)
{
if (char.IsDigit(text[i]))
{
isNumber = true;
break;
}
}
if (isNumber)
{
Console.WriteLine("Text contains number.");
}
else
{
Console.WriteLine("Text doesn't contain number.");
}
Console.ReadKey();
Or Linq:
string text = Console.ReadLine();
bool isNumberOccurance =text.Any(letter => char.IsDigit(letter));
Console.WriteLine("{0}",isDigitPresent ? "Text contains number." : "Text doesn't contain number.");
Console.ReadKey();
The answer seems to be just no.
Although there are many good other answers, they either just hide the uglyness (which I did not ask for) or introduce new problems (edge cases).