Trying to understand why my choice in an array doesn't work - c#-2.0

Sorry for the ambiguous title. I'm kind of new to programming and this issue is a bit weird so I didn't know how to word it.
I'm simply practicing on creating an array populated with colors and the user just have to pick a color by picking 1-9. The issue is that I get an error message:
Use of unassigned local variable 'UserPickNum'
I already assigned it to an int and the only solution that will fix this if I created another construct, runs Console.WriteLine(colors[UserPickNum]); picks the color, then the program runs fine.
I guess my question is, why won't it work like this without having to create and call for another construct.
using System;
using System.Collections.Generic;
using System.Text;
class Program
{
static void Main()
{
string[] colors;
string Pick;
int PickNum;
int UserPickNum;
Console.WriteLine("Which color do you want? Pick 1-9");
Pick = Console.ReadLine();
if (int.TryParse(Pick, out PickNum))
{
UserPickNum = Convert.ToInt32(Pick);
}
else
{
Console.WriteLine("This isn't a valid number");
Console.ReadKey();
Main();
}
colors = new string[10] { "black", "white", "green", "purple", "red", "brown", "blue", "gray", "yellow", "indigo" };
Console.WriteLine(colors[UserPickNum]);
Main();
}

If Pick turns out not to be a number and thus int.TryParse returns false, then UserPickNum will not be assigned to a value. Probably the easiest way to resolve this is to assign a value to UserPickNum where you declare it, i.e.:
int UserPickNum = Int32.MinValue;

Your code only has one route through the if statement where you set UserPickNum - hence the warning. However, you don't need to call Convert.ToInt32 on Pick as you already have the number as an integer - in PickNum - assuming that the user entered a valid integer. This means you don't need UserPickNum at all. So you could change your code to be:
if (!int.TryParse(Pick, out PickNum))
{
Console.WriteLine("This isn't a valid number");
Console.ReadKey();
Main();
}
colors = new string[10] { "black", "white", "green", "purple", "red", "brown", "blue", "gray", "yellow", "indigo" };
Console.WriteLine(colors[PickNum]);
Main();
You should also check that it's in range before trying to use it as an array index:
if (PickNum < 0 || PickNum > 9)
{
Console.WriteLine("Input out of range");
// Try again
}

That error means that you are trying to use a variable that hasn't had a value given to it yet. You say "I already assigned it to an int", but that's not really an assignment. The assignment is when you give it a value (e.g. int UserPickNum = 0).
In your code it looks you're attempting to make sure the value is assigned with your if/else statement, but the else clause doesn't actually stop the rest of the code after it from executing. You would need to return after you recursively call Main().

The error message you are getting is because your variable UserPickNum isn't initialized (It isn't set in your else block, and thus there is potentially a path through your code where it isn't set to a value).
You can set it to a default value when you declare it to fix this problem:
int UserPickNum = 0;
Other Feedback
Something else I noticed is that you don't even need the UserPickNum variable. In this part of your code:
Pick = Console.ReadLine();
if (int.TryParse(Pick, out PickNum))
{
UserPickNum = Convert.ToInt32(Pick);
}
the Variable PickNum contains the value that the user typed in as an integer. You can streamline this part of the code like this:
Pick = Console.ReadLine();
if (!int.TryParse(Pick, out PickNum))
{
// code you are currently doing in your else block
Console.WriteLine("This isn't a valid number");
Console.ReadKey();
Main();
}
// code you are currently doing after your if else block
colors = new string[10] { "black", "white", "green", "purple", "red", "brown", "blue", "gray", "yellow", "indigo" };
Console.WriteLine(colors[PickNum]);
Main();

Related

Dart: Reference a variable name from the variable itself

I’m trying to get the variable name instead of the value to pass it to another method
eg.
String myString = "xyz";
String getVariableName(String s){
// What i want is if the above string is passed [getVariableName(myString)]
//i want it to return ['myString']
}
This is generally not possible. At best, if there are a finite number of String variables you care about, you could manually make a collection of them, and then search it:
final stringVariables = <String, String Function()>{
'myString': () => myString,
'myOtherString': () => myOtherString,
};
var myString = 'xyz';
var myOtherString = 'abc';
String getVariableName(String s) {
for (var entry in stringVariables.entries) {
if (entry.value() == s) {
return entry.key;
}
}
return '';
}
void main() {
print(getVariableName('xyz')); // Prints: myString
myString = 'foo';
print(getVariableName('foo')); // Prints: myString
}
Note that stringVariables's above must use a Function as a thunk to delay evaluation of the variable; otherwise the variable name would be associated with whatever value it happened to have when stringVariables is first accessed and wouldn't work if your variables are reassigned.
All that said, I don't really recommend doing any of this. This sounds like an XY problem. You should be asking about whatever it is you ultimately want to do, and there probably is a better way to accomplish that task.

Dart Object instantiating

I'm very new to programming and Dart. I was wondering why you put Response in front of the variable response. Also why do we use Datetime object in front of the variable 'now?' I believe when you want to instantiate, you write Datetime now = Datetime(); But it was written something else for the variable. What does it mean? Thank you very much in advance!
void getTime() async{
Response response = await get(Uri.parse('https://worldtimeapi.org/api/timezone/Europe/London'));
Map data = jsonDecode(response.body);
// get properties from data
String datetime = data['datetime'];
String offset = data['utc_offset'].substring(1,3);
//create DateTime object
DateTime now = DateTime.parse(datetime);
now = now.add(Duration(hours: int.parse(offset)));
print(now);
}
Ok, let's break this down:
Response response = await
get(Uri.parse('https://worldtimeapi.org/api/timezone/Europe/London'));
A variable declaration in Dart looks like this:
<Type> <name> [= <value>];
So in your case Response is the type of the variable, response is the name of the variable and get(Uri.parse('https://worldtimeapi.org/api/timezone/Europe/London')) is the value of the variable (actually get(...) is a future, and the future's response is the value, that's why the await keyword is there, but that's not important.)
Sidenote, you can actually use the var keyword to skip the <Type> part of the declaration:
int myFunction(a, b) => a+b;
int x = myFunction(1,2);
Above, we know myFunction returns an int, and the variable x is equal to the result of myFunction, so it must also be an int, we can use the var keyword to skip writing int then:
int myFunction(a, b) => a+b;
var x = myFunction(1,2);
Of course, here there isn't that big a difference between writing int and var, but when your type is something like List<Map<String, List<int>>> it is quite nice to be able to skip writing that over and over
Now for this line:
DateTime now = DateTime.parse(datetime);
We already know that the first DateTime tells us what type the variable is, and we know that now is the name of the variable, we also know that the variable's value is DateTime.parse(datetime) because it is what goes after the = sign, but we still don't know what DateTime.parse(datetime) means.
Classes can have static and non-static methods, a static method is a method that gets called on a class, while a non-static method gets called on an object. Most method calls ever are non-static, look at this example:
class Car {
void accelerate() {
// some method to increase the speed of the car
}
void decelerate() {
// some method to decrease the speed of the car
}
Car buyCar(int maxCost) {
// some method to buy a new car
}
}
void main() {
Car car = Car();
car.accelerate();
car.decelerate();
Car otherCar = car.buyCar(100000000);
}
Above, the method accelerate and decelerate are instance methods and that makes sense because they probably affect some statistics of the car (like current speed), buyCar is also an instance method, but if you think about it, it shouldn't be, it doesn't affect your current car if you buy a new one and also you shouldn't need to have a car object to buy another one in the first place. So let's make that last method static:
class Car {
void accelerate() {
// some method to increase the speed of the car
}
void decelerate() {
// some method to decrease the speed of the car
}
static Car buyCar(int maxCost) {
// some method to buy a new car
}
}
It is as simple as adding the static keyword, now instead of having to do this:
Car myOldCar = Car();
Car myNewCar = myOldCar.buyCar(100000000);
we can just do this:
Car myNewCar = Car.buyCar(100000000);
looks familiar?
That's right parse is a static method on DateTime class, it takes a string that looks like this: 2012-02-27 13:27:00.123456789z and returns a DateTime object.
So to recap:
Response response = await
get(Uri.parse('https://worldtimeapi.org/api/timezone/Europe/London'));
Response is the type of the variable, response is its name and get(Uri.parse('https://worldtimeapi.org/api/timezone/Europe/London')) is a method that returns a Response object.
DateTime now = DateTime.parse(datetime);
Similarly DateTime is the type, now is the name and DateTime.parse is a static method that parses a string and makes a DateTime object, in this case the string is datetime, which was declared as being equal to data['datetime'].
If you want to understand better how the parse method works, here is the DateTime parse documentation

Truthy and falsy values in Dart programming language

I just stand in front of a very weird part in dart, I didn't find an answer on the internet, No truthy and falsy values in dart?!
for example,
const x = "foo";
void main(){
if(x){
print("x is set")
}
}
In JavaScript we do this things very easily, how can I do that in Dart?!
Dart is a statically typed language, so x is a String, and you can't check if a string is true or false.
if you want to check if x has a value or not, you can do the following
String x = 'hi';
if (x?.isNotEmpty ?? false) {
print("x is set");
}
After some researches, I've found that in order to check for a dynamiclly assigned variable, where in case you're not sure if the variable will be set to a number or a string for example, you need to check if the variable is not equal to null.
For example:
void main(){
var a;
if(true){
a = "The variable is set to string";
}
else if(false){
a = 12; //the variable is set to a number
}
//Now, to check:
if(a != null){
print("A is set, WOW Dart is working! I thought it's garbage!");
}
}
In case the both statements are false, the variable will still be a null.

Invalid rank specifier

I am trying to create a dungeon crawler with a tile-based map. However, I get an error when creating the array of tiles. (Right now, Tile is a class with nothing but an empty constructor.)
class Map
{
Tile[][] Tiles;
static const int DefaultWidth = 640, DefaultHeight = 480;
Random rnd;
public Map(int? Width, int? Height, int? seed)
{
Tiles = new Tile[((Width == null) ? DefaultWidth : (int)Width)]
//This line gives the error "invalid rank specifier: expected ',' or ']'" after the first bracket
[((Height == null) ? DefaultHeight : (int)Height)];
Generate();
}
void Generate()
{
}
}
Why am I getting this error?
In C#, the right way to instantiate a 2D array is to use a comma instead:
int[,] array = new [3,2];
You can still make arrays such as int[][], but you'll need to use a for loop to create every individual array inside it (which can be of different lengths), and this is known as a jagged array. I would recommend, however, to use the comma syntax as it is idiomatic in C# and is the expected way to do things.

Dart: How to bind to variables annotated with int via Web UI?

What is the best practice in Dart when dealing with classes as data records?
To Elaborate: When writing an app, it is likely that a class for a table row will be created. As in
class Item { int itemid, String itemName, double score }
Item item = new Item();
This allows compile time catching of any typos etc. in Dart. (Unlike using a class that relies on NoSuchMethod.)
It will also need a corresponding string structure to bind to the HTML such as
<input id="itemname" type="text" bind-value="itemEdit.itemName">
So the Dart would be:
class ItemEdit { String itemId, String itemName, String score }
ItemEdit itemEdit = new ItemEdit();
Next we need a way to get from one to the other, so we add a method to Item
fromStrings(ItemEdit ie) {
itemid = ie.itemId == null ? null : int.parse(ie.itemId);
itemName = ie.ItemName;
score = ie.score == null ? null : double.parse(ie.score);
}
And the other way around:
toStrings(ItemEdit ie) {
ie.itemid = itemId == null ? '' : ie.itemId.toString();
ie. itemName = itemName == null ? '' : itemname; // Web_ui objects to nulls
ie.score = score == null ? null : score.toStringAsFixed(2);
}
Also, we get jason data from a database, so we need to add another method to Item:
fromJson(final String j) {
Map v = JSON.parse(j);
itemid = v['itemid'];
itemname = v['itemname'];
score = v['score'];
}
And we need to be able to revert to default values:
setDefaults() { itemId = 0; itemName = "New item"; score = 0; }
This verbosity gets me feeling like I am writing COBOL again!
There is something fundamental missing here - either in my understanding, or in the Dart/WebUI libraries.
What I would like to write is something like
class Item extends DataRecord {
int itemid = 0,
String itemName = 'New item',
double score = 0.0;
}
Then, without further coding, to be able to write code such as
item.toStrings();
...
item.fromStrings();
...
item.fromJson(json);
...
item.setDefaults(); // results in {0,'New item',0.0}
And to be able to write in the HTML:
value="{{item.strings.score}}"
If this was possible, it would be quicker, simpler, clearer, and less error prone than the code I am writing at the moment.
(Full disclosure, this answer is written with the assumption that at least one bug will be fixed. See below)
Three suggestions that might help.
Use named constructors to parse and create objects.
Take advantage of toJson() when encoding to JSON.
Use bind-value-as-number from Web UI
1) Named constructors
import 'dart:json' as json;
class Item {
int itemid;
String itemName;
double score;
Item.fromJson(String json) {
Map data = json.parse(json);
itemid = data['itemid'];
itemName = data['itemName'];
score = data['score'];
}
}
2) Encoding to JSON
The dart:json library has a stringify function to turn an object into a JSON string. If the algorithm encounters an object that is not a string, null, number, boolean, or collection of those, it will call toJson() on that object and expect something that is JSON-encodable.
class Item {
int itemid;
String itemName;
double score;
Map toJson() {
return {'itemid':itemid, 'itemName':itemName, 'score':score};
}
}
3) Now, having said that, sounds like you want to easily bind to HTML fields and get primitive values back, not just strings. Try this:
<input type="number" min="1" bind-value-as-number="myInt" />
(Note, there seems to be a bug with this functionality. See https://github.com/dart-lang/web-ui/issues/317)
(from https://groups.google.com/a/dartlang.org/forum/#!topic/web-ui/8JEAA5OxJOc)
Just found a way to perhaps help a little in the this situation:
class obj {
int gapX;
String get gapXStr => gapX.toString();
set gapXStr(String s) => gapX = int.Parse(s);
...
Now, from the HTML you can use, for example
bind-value="gapXStr"
and in code you can use
x += ob.gapX;

Resources