Been trying to solve this for 2 days now and I just can't get it to work! The programs layout has to stay the same (part of the challenge). Really bugging me and hoping somebody could shed some light...
I keep getting the following error:
Use of unassigned local variable 'countOfFizz'
Use of unassigned local variable 'countOfBuzz'
Use of unassigned local variable 'countOfFizzBuzz'
Use of unassigned local variable 'countOfPrime'
On these lines:
fb.IsFizz(input, countOfFizz);
fb.IsFizz(input, countOfBuzz);
fb.IsFizz(input, countOfFizzBuzz);
fb.IsFizz(input, countOfPrime);
and here is the full code. (again apologies if its poor coding, its basics and the layout has been supplied already).
class FizzBuzz
{
public static void Main()
{
int input;
string enter;
int countOfFizz;
int countOfBuzz;
int countOfFizzBuzz;
int countOfPrime;
Console.WriteLine("Please enter a number: ");
enter = Console.ReadLine();
input = int.Parse(enter);
while (input != 0)
{
Console.WriteLine("Please enter a number: ");
enter = Console.ReadLine();
input = int.Parse(enter);
FizzBuzz fb = new FizzBuzz();
fb.IsFizz(input, countOfFizz);
FizzBuzz fb1 = new FizzBuzz();
fb1.IsBuzz(input, countOfBuzz);
FizzBuzz fb2 = new FizzBuzz();
fb2.IsFizzBuzz(input, countOfFizzBuzz);
FizzBuzz fb3 = new FizzBuzz();
fb3.IsPrime(input, countOfPrime);
FizzBuzz fb4 = new FizzBuzz();
fb4.TotalFizz(countOfFizz);
FizzBuzz fb5 = new FizzBuzz();
fb5.TotalBuzz(countOfBuzz);
FizzBuzz fb6 = new FizzBuzz();
fb6.TotalFizzBuzz(countOfFizzBuzz);
FizzBuzz fb7 = new FizzBuzz();
fb7.TotalPrime(countOfPrime);
}
Console.WriteLine("Finished.");
}
public bool IsFizz(int input, int countOfFizz)
{
if (input % 9 == 0)
{
Console.WriteLine("Fizz");
countOfFizz++;
return true;
}
return false;
}
public bool IsBuzz(int input, int countOfBuzz)
{
if (input % 13 == 0)
{
Console.WriteLine("Buzz");
countOfBuzz++;
return true;
}
return false;
}
public bool IsFizzBuzz(int input, int countOfFizzBuzz)
{
if (input % 9 == 0 && input % 13 == 0)
{
Console.WriteLine("FizzBuzz");
countOfFizzBuzz++;
return true;
}
return false;
}
public bool IsPrime(int input, int countOfPrime)
{
for (int i = 2; i < input; i++)
{
if (input % i == 0 && i != input)
{
return false;
}
}
Console.WriteLine("Prime");
countOfPrime++;
return true;
}
public void BeginTesting(int countOfFizz, int countOfBuzz, int countOfFizzBuzz, int countOfPrime)
{
countOfFizz = 0;
countOfBuzz = 0;
countOfFizzBuzz = 0;
countOfPrime = 0;
}
public int TotalFizz(int countOfFizz)
{
Console.WriteLine("Number of Fizz: ");
return countOfFizz;
}
public int TotalBuzz(int countOfBuzz)
{
Console.WriteLine("Number of Buzz: ");
return countOfBuzz;
}
public int TotalFizzBuzz(int countOfFizzBuzz)
{
Console.WriteLine("Number of FizzBuzz: ");
return countOfFizzBuzz;
}
public int TotalPrime(int countOfPrime)
{
Console.WriteLine("Number of Prime: ");
return countOfPrime;
}
}
The problem is that you are passing ints to the methods, when an int (or float, bool, etc.) is passed to a method it is copied, it is not passed as a reference variable. Therefore, the countOfBuzz you change within a method is not the same as the one in the main method.
To solve this, don't pass those parameters to the methods. Instead, change the scope of those variables to be inside the class instead of inside the main method.
Also, it is good practice to initialize the variables to zero (local variables within methods need to be initialized, otherwise you get that message you asked about).
As Simon already explained in his answer, integers are value types and all value types are always passed by value (by default). This means that when you call for example IsFizz with the countOfFizz then all that happens is that the value of that variable is passed to the function which then has its own variable with a copy of the value. So when the function changes the value, then only that local variable’s value changed but that change will never make it to the original variable.
One way to solve this would be to explicitely pass those variables by reference. You can do this by using ref int countOfFizz in the function signature for the parameter (i.e. add the ref keyword). However, I do not recommend you to do this as it will not provide a state the FizzBuzz class was likely to have.
So, in object oriented programming, you create objects which hold a state. In your case, the FizzBuzz is the class, the type of those objects. Now if we think about it, and take into account that you apparently want to keep count of the number of Fizz/Buzz/FizzBuzz cases, it makes sense to have those counts contained within the object.
So first of all, you should make those countOfX variables instance variables that are bound to the object.
Looking at the IsFizz etc. methods, they are all supposed to return a boolean value. So it’s likely that they were originally only meant to check the input and return true or false depending on if the check succeeded or not. Here we can also increment our counters when we find a falue. So in the end, those methods should only take the input, perform the check, increment their counter and return the check result.
The TotalX methods can then simply return the current counter results, while the BeginTesting method can reset them to zero (without taking any parameters).
Finally, in the Main function you want to create only a single instance of FizzBuzz so we can share the state during the whole duration of the program. You should check the return values for the IsX methods and print the appropriate response here (often you don’t want class types to arbitrarily print stuff but handle that in a different layer—in your case the console application that happens in the Main function).
As a final note, I would like you to know that I’m interpreting a lot into the original task here and cannot perfectly say what the original intention behind this code was. From my point of view it looks a bit ridiculous to do it like that. The FizzBuzz problem, even in this changed instance, is a simple problem aimed to show if a person is capable of basic programming-related thinking. It’s not necessarily meant to be a problem to work on in a complex object oriented manner, but just like the typical “Hello World” there seem to be people who like over-generalizing it in a way to make it terribly complex for fun or practice. I’m not really agreeing that this FizzBuzz instance with that predefined base code is either generalized nor fun nor a good practice. But again, this is just my opinion.
And finally a last hint to complete this “correctly”: The output “FizzBuzz” is the combination of both conditionals for “Fizz” and ”Buzz”. Meaning that if a number qualifies for “FizzBuzz” it also does so for the individual ones. So you should make sure that the check for the individual ones either explicitely prevent the “FizzBuzz” combination to match, or you check for the combined one first and abort further checks if it matches.
Initialize the variables might do the trick for you:
int countOfFizz = 0;
int countOfBuzz = 0;
int countOfFizzBuzz = 0;
int countOfPrime = 0;
Remove the parameter (countOfFizz) from IsFizz, and it should work. Do the same for other similar methods.
public bool IsFizz(int input)
{
if (input % 9 == 0)
{
Console.WriteLine("Fizz");
countOfFizz++;
return true;
}
return false;
}
Related
edit; Based on responses, I may have been unclear in my final goal. I've updated the last section.
Situation
I have a number of variables which I need to perform the same operation on. In this case, they are strings, and can at the point we reach this code have the value null, "", "Blank", or they could already have an assigned other value that I want to keep.
if (String.IsNullOrEmpty(MyVar1) || "Blank".Equals(MyVar1))
MyVar1 = null;
if(String.IsNullOrEmpty(MyVar2) || "Blank".Equals(MyVar2))
MyVar2 = null;
...
if(String.IsNullOrEmpty(MyVar10) || "Blank".Equals(MyVar10))
MyVar10 = null;
Being a programmer that wants to keep my code clean and this block drives me mad, I'm looking for a way to create a list of these variables, and perform this same if statement + null assignment on each.
For an example, here's what I'd like to do:
MyVar1 = "Blank";
DreamDataStructure varList = new DreamDataStructure() { MyVar1, MyVar2, ..., MyVar10 };
foreach(ref string MyVar in varList)
{
if(String.IsNullOrEmpty(MyVar) || "Blank".Equals(MyVar))
MyVar = null;
}
Console.WriteLine(MyVar1); //Should now be null
What Doesn't Work
1) Because my variables are strings, I can't do something like this.
var myListOfVariables = new[] { &MyVar1, &MyVar2, ..., &MyVar10 };
If I could, I'd be able to foreach over them as expected. Because string is a managed type though, it cannot be passed by reference like this.
2) Similarly, if I just made a List<string> of the variables, they would be passed by value and wouldn't help my case.
3) These variables can't be wrapped in an outer object type, as they need to be used as strings in a large number of places in a legacy application. Assume that it would be too large an effort to change how they're used in every location.
Question
Is there a way to iterate over string (or other managed type) variables in a pass-by-reference way that will allow me to put the entire operation inside of a loop and reduce the duplication of code that's happening here?
The goal here is that I can use the original variables later on in my code with the updated values. MyVar1, etc, are referenced later on already by legacy code which expects them to be null or have an actual value.
If I understand your question correctly, I don't think what you want to do is possible. Please see this question: Interesting "params of ref" feature, any workarounds?
The only thing I can suggest (which I know doesn't answer your question) is creating a method to avoid duplication of your conditional logic:
void Convert(ref string text)
{
if (string.IsNullOrEmpty(text) || "Blank".Equals(text))
{
text = null;
}
}
You could create a function instead of passing references, which would also be more readable.
string Validate(string inputString)
{
return string.IsNullOrEmpty(inputString) || "Blank".Equals(inputString) ? null : inputString;
}
<...>
MyVar1 = Validate(MyVar1);
Update:
Now I get what you're trying to do. You have a bunch of variables, and you want to perform some sort of bulk operation on them without changing anything else. Putting them in a class isn't an option.
In that case you're really stuck operating on them one at a time. There are ways to shorten it, but you're pretty much stuck with the repetition.
I'd
create a string SanitizeString(string input) function
type x = SanitizeString(x); once for each variable
copy and paste the variable names to replace x.
It's lame, but that's about all there is.
Perhaps this would be a better approach. It ensures that the values are always sanitized. Otherwise you can't easily tell whether the values have been sanitized or not:
public class MyValues
{
private string _value1;
private string _value2;
private string _value3;
public string Value1
{
get { return _value1; }
set { _value1 = Sanitize(value); }
}
// repeat for other values
private string Sanitize(string input) =>
string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
That's one option. Another is to sanitize the inputs earlier. But ideally we want to ensure that a given class is always in a valid state. We wouldn't want to have an instance of a class whether the values may or may not be valid. It's better to ensure that they are always valid.
ref doesn't really factor into it. We don't need to use it often, if ever. With a value type or string we can just return a new value from a function.
If we're passing a reference type and we want to make changes to it (like setting its properties, adding items to a list) then we're already passing a reference and we don't need to specify ref.
I'd try to write methods first without using ref and only use it if you need to. You probably never will because you'll succeed at whatever you're trying to do without using ref.
Your comment mentioned that this is a legacy app and it's preferable not to modify the existing class. That leaves one more option - reflection. Not my favorite, but when you say "legacy app" I feel your pain. In that case you could do this:
public static class StringSanitizer
{
private static Dictionary<Type, IEnumerable<PropertyInfo>> _stringProperties = new Dictionary<Type, IEnumerable<PropertyInfo>>();
public static void SanitizeStringProperties<T>(T input) where T : class
{
if (!_stringProperties.ContainsKey(typeof(T)))
{
_stringProperties.Add(typeof(T), GetStringProperties(typeof(T)));
}
foreach (var property in _stringProperties[typeof(T)])
{
property.SetValue(input, Sanitize((string)property.GetValue(input)));
}
}
private static string Sanitize(string input)
{
return string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
private static IEnumerable<PropertyInfo> GetStringProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(property => property.PropertyType == typeof(string) && property.CanRead && property.CanWrite);
}
}
This will take an object, find its string properties, and sanitize them. It will store the string properties in a dictionary by type so that once it has discovered the string properties for a given type it won't have to do it again.
StringSanitizer.SanitizeStringProperties(someObject);
you can simply use a string[] and get the changes back to the caller method like this.
public Main()
{
var myVar1 = "Blank";
var myVar2 = "";
string myVar3 = null;
var myVar4 = "";
string[] dreamDataStructure = new string[] { myVar1, myVar2, myVar3, myVar4 };
}
private void ProcessStrings(string[] list)
{
for(int i = 0; i < list.Length; i++)
{
if (String.IsNullOrEmpty(list[i]) || "Blank".Equals(list[i]))
list[i] = null;
}
}
For a part of my project, I want to enforce the rule that the user input can only be within a min/max word boundary. With a minimum of 1 word, and a maximum of 50 words. The boolean isn't changing from the default set value of false. Here is my code:
bool WordCount_Bool = false;
//Goto the method that handles the calculation of whether the users input is within the boundary.
WordCount_EH(WordCount_Bool);
//Decide whether to continue with the program depending on the users input.
if (WordCount_Bool == true)
{
/*TEMP*/MessageBox.Show("Valid input");/*TEMP*/
/*Split(split_text);*/
}
else
{
MessageBox.Show("Please keep witin the Min-Max word count margin.", "Error - Outside Word Limit boundary");
}
Method handling the array and the change of the boolean:
private bool WordCount_EH(bool WordCount_Bool)
{
string[] TEMPWordCount_Array = input_box.Text.Split(' ');
int j = 0;
int wordcount = 0;
for (int i = 100; i <=0; i--)
{
if (string.IsNullOrEmpty(TEMPWordCount_Array[j]))
{
//do nothing
}
else
{
wordcount++;
}
j++;
}
if (wordcount >= 1)
{
WordCount_Bool = true;
}
if (wordcount < 1)
{
WordCount_Bool = false;
}
return WordCount_Bool;
}
Thank you all in advance.
Side note: I realize that the for loop will throw an exception or at least is not optimal for its purpose so any advice will be much appreciated.
Extra Side note: Sorry I should have said that the reason i haven't used length is that wherever possible I should do my own code instead of using built-in functions.
The short answer is you should just return a true or false value from your WordCount_EH method like others have said
But just to clear up why it doesn't work. C# by default passes arguments by value. With Value types such as Boolean the actual value of true or false is stored in the variable. So when you pass your Boolean value into your method all you are doing is saying please put this bool value into my new variable (the method parameter). When you make changes to that new variable it only changes that variable. It has no relation to the variable that it was copied from. This is why you don't see a change in original bool variable. You may have named the variables the same but they are infact two different variables.
Jon Skeet explains it fantastically here http://jonskeet.uk/csharp/parameters.html
Here you go this should solve it:
if(input_box.Text.Split(' ').Length>50)
return false;
else
return true;
You need to pass WordCount_Bool by ref if you want to change it in WordCount_EH:
private bool WordCount_EH(ref bool WordCount_Bool) { ... }
bool WordCount_Bool = false;
WordCount_EH(ref WordCount_Bool);
although in this case you might as well use the return value:
bool WordCount_Bool = false;
WordCount_Bool = WordCount_EH(WordCount_Bool);
If you want to pass argument by reference, you need to do as per #Lee suggestion.
For your logic implementation, you can use following code to avoid array indexing.
// It would return true if you word count is greater than 0 and less or equal to 50
private bool WordCount_EH()
{
var splittedWords = input_box.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
return (splittedWords.Count > 0 && splittedWords.Count <= 50);
}
The scenario is that I have say two different types of cases - case 1 and case 2. For case 1 and case 2 each I have a certain startIndex, endIndex and a formula for accessing the elements of a List.
Now for assigning values startIndex and endIndex I am preferring a normal switch case, however I am at loss for the formula for accessing elements. For case 1 it is say something like List[ a+i ] and for case 2 it is say List[a + (i-b)].
One way can be to have a for loop like this
for(int i=0;;i++)
{
if(case is 1)
then f=a+i
else if(case 2)
then f=a+(i-b)
}
I thought of using delegates. however, as per my knowledge they need to be made global. Actions do not return value. Func can be used but one expression/formula takes only one element (int) and the other takes 3. I need something in lines to this like that anonymous function can be assigned any of above mentioned formulae at runtime from the switch case (as the cases might and will increase in future).
Thank you.
I thought of using delegates. however, as per my knowledge they need
to be made global.
This is not true (actually, there are no truly global variables in C#, since each and every variable needs to be encapsulated inside an object). A public delegate type is indeed visible to all code after referencing the assembly containing this type's code, but a variable of such type can be private.
What I recommend in your situation is to have some sort of mapping from case numbers to delegates. A good idea is to use a Dictionary<TKey, TValue> if you have at most one delegate per case. This dictionary can be stored as a private variable inside the class where your method resides.
public class MyClass
{
private Dictionary<int, Delegate> _delegateMapping = new Dictionary<int, Delegate>;
}
There are a couple of ways you can add elements do the dictionary in the constructor: passing the already populated dictionary, passing an array of delegates, creating these delegates in the constructor itself. Either way, you'll end up with a dictionary of Delegate types, so you'll need to use a cast to be able to use them in your code properly.
for (int i = 1; i < _delegateMapping.Count; i++)
{
switch (i)
{
case 1:
var f = (Action<int>)_delegateMapping[1];
f(i);
break;
case 2:
var f = (Action<int, int>)_delegateMapping[2];
f(i, a);
break;
}
}
Of course I'm greatly improvising here.
It is important to note that if the type of delegate changes inside the dictionary, you will have to modify the cast accordingly inside the switch statement. Otherwise, if no implicit cast exists, you'll get a runtime exception.
Hi guys thank you so very much for your feedbacks. I finally found the solution with Func. This is what my code looks like. I had to manipulate the Func usage a little. I made almost all the vars which I have to use in the Func as global/local to the function where I write these Funcs. My apologies, if I was not able to explain my problem properly.
int i = -1;
Func<int,int> formula = null;
switch(f)
{
case 1:
{
formula = new Func<int,int>(index => { return i; });
}
break;
case 2:
{
formula = new Func<int, int>( index => { return s- (i * c); } );//here s and c are global variables.
}
break;
}
i = startIndex;
while(i < endIndex)
{
var Obj= List[formula.Invoke(i)];
//my code goes here
i++;
}
Let me know if my solution is correct w.r.t performance, logic, C# programming, etc.. :)
EDITED::
#usr and #Kapol I tried the way you suggested and tried to improvise the code like this.
private Dictionary<int, Func<int[], int>> indexFormulae;
private void assignDelegates()
{
indexFormulae = new Dictionary<int, Func<int[], int>>();
indexFormulae.Add(0, getFormula_1);
indexFormulae.Add(1, getFormula_2);
}
private void someFunction(int sp)
{
int i = 0;
Func<int[], int> formula = null;
indexFormulae.TryGetValue(formation,out formula);
i = startIndex;
while (i < endIndex)
{
int[] intValues = new int[] {i,sp,globalVar };
var Obj = List[formula.Invoke(intValues)];
//My code here
i++;
}
}
private int getFormula_1(params int[] intValues)
{
return intValues[0];
}
private int getIndex_Vertical(params int[] intValues)
{
return intValues[1] - (intValues[0] * intValues[2]);
}
So, that with this now I can use these two getFormula methods anywhere in this class rather than keeping them anonymous. and also I think I will stick to params because I might have N number of int params in future for other functions.
I have the attached code which trys to find all 1s in an array input by the user.
The program asks the user to select the array size, then input a number of that size with some 1s in it. It then counts the number of 1s found.
I guess that the input the user gives is in the form of a string? So, if they input 12345 it would be a string with one 1 in it.
I am trying to convert the array to int32, though I don't think I fully understand why it has to be int32 either.
If somebody could help me understand this programs' workings and why I'm getting the following error I'd be thankful.
An unhandled exception of type 'System.FormatException' occurred in
mscorlib.dll Additional information: Input string was not in a correct
format.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace count1s
{
class Program
{
static void Main(string[] args)
{
int count = 0;
Console.WriteLine("Enter a number for the array length");
int limit = int.Parse(Console.ReadLine());
int[] array1s = new int[limit];
Console.WriteLine("Enter a number with some 1s in it");
for(int i=0; i<limit; i++)
{
array1s[i] = Convert.ToInt32(Console.ReadLine());
}
foreach (int number in array1s)
{
if (number == 1)
{
count++;
}
}
Console.WriteLine("The number of 1s in the array is: {0}", count);
Console.ReadLine();
}
}
}
You are getting this error because you are entering the array elements in one line.
If you enter one element on one line then program will work fine.
If you want to accept numbers on one line then you can use split function like
String []numbers = Console.ReadLine().Split(' ');
for (int i = 0; i < limit; i++)
{
array1s[i] = Convert.ToInt32(numbers[i]);
}
foreach (int number in array1s)
{
if (number == 1)
{
count++;
}
}
I don't think I fully understand why it has to be int32 either.
It doesn't have to be. That depends on your input. If the user enters a number small enough, it can also fit into a short (which is 16 bits), and you can parse the string into that.
why I'm getting the following error
Because you're trying to parse a string which isn't parse-able to a valid int value. If you're not sure the input is valid, you can use a method such as int.TryParse, which returns a boolean indicating the success or failure of the parsing:
int i = 0;
while (i < limit)
{
string value = Console.ReadLine();
int parsedValue;
if (!int.TryParse(value, out parsedValue))
{
Console.WriteLine("You've entered an invalid number. Please try again");
continue;
}
array[i] = parsedValue;
i++;
}
If you want to count all occurrences of 1, you can simply use Enumerable.Count which takes a predicate:
return array.Count(number => number == 1);
Use this as
for(int i=0; i<limit; i++)
{
int value;
var isNumber = int.TryParse(Console.ReadLine(), out value);
if(isNumber)
{
array1s[i] = value;
}
else
{
Console.WriteLine("Invalid value you have entered");
continue;
}
}
Well, now I feel like a bit of an idiot.
I tried some of your responses, thanks very much for that, and they are good. I went back and tried the code I originally posted as well and found that it does work. I just need to hit carriage return after each entry into the array.
I'll take a look at all of this properly later to find out what is going on.
Thanks again all - gotta say - was really surprised to get so many responses on here so quickly. Awesome!!
I just found a really good article on the Microsoft: DEV204x Programming with C# course I have started online. I think this will be helpful to all who follow with the same questions I had. Hopefully I'm not breaking any copyright laws or stackoverflow rules. It's a free course, so I doubt it.
Data Conversions
C# supports two inherent types of conversion (casting) for data types, implicit and explicit. C# will use implicit conversion where it can, mostly in the case when a conversion will not result in a loss of data or when the conversion is possible with a compatible data type. The following is an example of an implicit data conversion.
Converting from smaller to larger integral types:
int myInt = 2147483647;
long myLong= myInt;
The long type has a 64-bit size in memory while the int type uses 32-bits. Therefore, the long can easily accomodate any value stored in the int type. Going from a long to an int may result in data loss however and you should use explicit casting for that.
Explicit casts are accomplished in one of two ways as demonstrated with the following coe sample.
double myDouble = 1234.6;
int myInt;
// Cast double to int by placing the type modifier ahead of the type to be converted
// in parentheses
myInt = (int)myDouble;
The second option is to use the methods provided in the .NET Framework.
double myDouble = 1234.6;
int myInt;
// Cast double to int by using the Convert class and the ToInt32() method.
// This converts the double value to a 32-bit signed integer
myInt = Convert.ToInt32(myDouble);
You will find many other methods in the Convert class that cast to different integral data types such as ToBoolean(), ToByte(), ToChar(), etc.
The Convert.ToInt32() method can also be used to cast a string literal to a numeric data type. For example, you may have GUI-based application in which uses input data into text boxes. These values are string values when passed to the code in your application. Use of the above method to cast the string to numbers can help prevent exceptions in your code when trying to use the wrong data type in a specific area.
C# also provides another mechanism to deal with casting types. The use of the TryParse() method and Parse() methods can help with casting as well. These methods are attached to the types in C# rather than the Convert class. An example will help demonstrate.
// TryParse() example
bool result = Int32.TryParse(value, out number);
// Parse() example
int number = Int32.Parse(value);
In the TryParse() example, the method returns a Boolean result indicating if the conversion succeeded. In the Parse() example, if the conversion does not succeed, an exception will be thrown.
I am working on a program that would allow the user to build digital circuits from virtual logic gates. Every gate would be an instance of a class that represents particular gate type, for example here's how AND class looks:
public class andgate
{
public andgate()
{
inputs = new bool[7];
for (int i = 0; i < 7; i++) inputs[i] = true;
output = (inputs[0] && inputs[1] && inputs[2] && inputs[3] && inputs[4] && inputs[5] && inputs[6]);
}
public bool[] inputs;
public bool output;
}
Every gate has seven inputs but not all of them have to be used (i.e. for a gate with three imputs the remaining four will just be "1" which is AND's neutral element anyway). Each input is a reference to an output of another gate or to an element of bool array (which stores the input vector) so that signal generated by one gate automatically is sent to the following gate. The problem is I also need the signal to be transmitted dynamically within the gate, i.e. if one of the input signals in AND gate is set to 0 then the output automatically has a 0 value. Therefore when you feed a binary vector to the inputs of the cirtuit, it changes the values of the circuit's outputs. Or maybe there's an easier way to simulate a circuit than building it from individual gates? I need it for test pattern generating.
Make the output property read-only:
public bool output
{
get
{
return inputs.All(i => i);
}
}
Instead of ANDing all the inputs, just check if there is any input that is false.
Of course you have to remove the assignment to output in the constructor. This should make your output property "dynamic".
You may also want to change the inputs to bool?[] instead, so that a null value would signify that there is no signal. You will then have to remove the initialization of the input array to all true and change the output return to:
return inputs.All(i => i.GetValueOrDefault(true));
Edited with Tim S's suggestions in the comments
For this, you should use a properties to set/get the inputs, as you can perform additional computations in a property. The state variables you're holding should be private.
public bool[] Inputs {
set {
inputs = value;
}
}
public bool Output {
get {
return inputs[0] && inputs[1] ...
}
}
I would avoid doing this for the Inputs property, since exposing arrays is really exposing information about how the class stores things, which should be avoided where possible for good OOP. A ReadOnlyCollection might be more suitable, for example.
However, I would rethink the design in general, and avoid having some arbitrary # of inputs, 7. Where have you conjured that value from?
A more simplistic approach would be to assume that a gate takes 2 values - A and B, for which you can set the values in the constructor or individual properties.
You then take advantage of the fact that operations on binary logic gates are associative, so an AND gate taking a, b, c, is equivalent to one taking a, b, feeding it's output to another which also takes c. This is how you'd build a circuit in practice anyway - the issue you need to consider is the latency of the gate though.
It sounds like you should add events into your gates, such that when their state changes they're able to notify dependant objects; something like this:
public class AndGate
{
private bool[] inputs;
private bool output;
public bool[] Inputs
{
get
{
return this.inputs;
}
set
{
this.inputs = value;
UpdateOutput();
}
}
public bool Output
{
get
{
return this.output;
}
}
public AndGate()
{
inputs = new bool[7];
for (int i = 0; i < 7; i++) inputs[i] = true;
UpdateOutput();
}
private void UpdateOutput()
{
bool original = output;
output = true;
for(int i=0; i<inputs.Length; i++)
{
output = output && inputs[i];
}
if (original != output)
{
OnChanged(EventArgs.Empty);
}
}
public event GateStateChangedEventHandler StateChanged;
protected virtual void OnChanged(EventArgs e)
{
if (StateChanged != null)
{
StateChanged(this, e);
}
}
}