2

I have created a small app to generate a random number on a button click and at the moment I am saving that number in a .txt file.

private void button1_Click(object sender, EventArgs e)
{
    Random rnd = new Random();
    int random = rnd.Next(1, 10000);
    // saving to a file is not an option!
    //File.AppendAllText(@"C:\Users\Public\no.txt", random + Environment.NewLine);
}

The problem to solve is that this random generated number must be unique (range from 1 to 9999) so every time when the number is generated I would check if that number was generated previously. But to do that I must keep a record of every generated number to be able to check, compare and if exists generate a new one until all numbers are used.

So the question is: Is it possible somehow to keep a record inside app so that I don't have to create any additional files?

update

After closing the app, previously numbers must be saved to be able to create unique new numbers!

Community
  • 1
  • 1
lewis4u
  • 14,256
  • 18
  • 107
  • 148
  • so, you want to remove **File.AppendAllText** ? – Aryan Firouzian Oct 28 '17 at 10:47
  • yes...this is temporary solution! The best case scenario would be that app itself saves an array inside somehow...not creating any additional files – lewis4u Oct 28 '17 at 10:48
  • Do you want this information to be available the next time the application is run? Also, How many times is the button likely to be pressed? – Rob Anthony Oct 28 '17 at 10:50
  • One simple solution would be to use application variable. **Application["Randoms"]** to save concatenated values of the list, and read it again by spliting values when you launch the app. – Aryan Firouzian Oct 28 '17 at 10:51
  • When the app is closed that array must be saved so next time when app is started I must have those previously generated numbers. That is the trickiest part I think...(app closing) – lewis4u Oct 28 '17 at 10:52
  • @RobAnthony the button would be pressed 9999 times until all numbers are generated... but through a time span of a few months! So the app would be closed and opened...you know what I mean :) – lewis4u Oct 28 '17 at 11:01
  • Do you realize that (almost) every piece of information in the computer ultimately resides in some file? – Alejandro Oct 28 '17 at 11:20
  • Yes but could that file be the app it self? – lewis4u Oct 28 '17 at 11:20
  • AppData sounds like the right thing to do for you. It is exactly for data required for the app for which the user doesn’t care. https://learn.microsoft.com/en-us/windows/uwp/app-settings/store-and-retrieve-app-data – flq Oct 28 '17 at 11:24
  • So that is also a new file created but somewhere inside AppData folder right? – lewis4u Oct 28 '17 at 11:27

4 Answers4

4

There is no "inside storage" for an .NET assembly. What wrong with saving a file?

  1. use Special Folder instead of a hardcoded String

  2. Consider using ProgramData or AppData

Also if you want to manage an Runtime object easly, you could make use of Serialization.

You could also use the registry, or a database to save your data.

Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • I can't create any additional files, it's not an option... What is ProgramData or AppData? is it permanent? Saving into registry would be an option! – lewis4u Oct 28 '17 at 11:22
  • ProgrammData/AppData are just special folders to store settings. You can't save data to your exe, you need some storage. I added a link to a tutorial for the regsitry. – Christian Gollhardt Oct 28 '17 at 11:25
  • Yes, so now I have a problem checking the previously generated numbers. Can I simply save a new registry key for each generated number and then for new number simply check if a key with such and such value exist? – lewis4u Oct 28 '17 at 11:38
  • 1
    I would just simple create one key to store an array of integers using Strings Join and Split methods. Not sure if there are better methods, I usualy don't work with the registry. – Christian Gollhardt Oct 28 '17 at 11:43
  • What do you all think about answer from Aryan Firouzyan? – lewis4u Oct 28 '17 at 11:51
  • I think you should make your own opinion. Semanticly, AppSettings is more about configuration, than storage. Its just another file. For an int array `randoms.Select(p => p.ToString()).ToList()` is very well. For everything more complex, use serialization. – Christian Gollhardt Oct 28 '17 at 11:57
  • How do you mean just another file? where would this file be saved on hdd? which path – lewis4u Oct 28 '17 at 11:59
  • Next to your Programm. AssemblyName.config or something like this. – Christian Gollhardt Oct 28 '17 at 12:00
  • Well this is not an option then – lewis4u Oct 28 '17 at 12:01
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157705/discussion-between-lewis4u-and-christian-gollhardt). – lewis4u Oct 28 '17 at 12:19
1
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
randoms = string.IsNullOrEmpty(ConfigurationManager.AppSettings["randoms"]) ? new List<int>() : ConfigurationManager.AppSettings["randoms"].Split(',').Select(int.Parse).ToList();
Random rnd = new Random();
int random = rnd.Next(1, 10000);
if (!randoms.Contains(random))
{
    randoms.Add(random);
    config.AppSettings.Settings.Add("randoms", string.Join(",", randoms.Select(p => p.ToString()).ToList()));
    config.Save(ConfigurationSaveMode.Minimal);
}

You can define the key in app setting:

<configuration>
  <appSettings>
    <add key="randoms" value="" />
  </appSettings>
  <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
 </startup>
</configuration>

I am not sure how config.AppSettings.setting.Add works. I think it adds value to the previous one by concatenating.

Aryan Firouzian
  • 1,940
  • 5
  • 27
  • 41
  • Can I save a new value to that key="randoms" AFTER the app is started and then when the app is closed the last saved value should be there??? – lewis4u Oct 28 '17 at 11:41
  • I tried and it was working when I close, and start application again (can read previous values from the key). but I got confused about how **config.AppSettings.Settings.Add** works. You can fix it by your application logic. – Aryan Firouzian Oct 28 '17 at 11:45
  • 1
    I will check this by the end of the day and post the result! – lewis4u Oct 28 '17 at 11:50
  • Can a registry key have an array for value? I mean instead having `key => value` to be this `key => [value, value2, value3]` – lewis4u Oct 28 '17 at 13:20
  • [Someone asked this question here](https://stackoverflow.com/questions/10419116/store-string-array-in-appsettings), I think it is not possible as they suggest concatenating string or using json string. – Aryan Firouzian Oct 28 '17 at 22:07
  • 1
    Yeah I gave up. I am saving the array in registry – lewis4u Oct 28 '17 at 22:08
0

I think the simple answer is to adjust the way the function works in the context of your application.

I would change the logic as follows:

  • When the program is running, keep the list in an array.
  • When you need to add a new number, resize the array then add it
  • When you exit, save the array content to the file (in format of your choosing, personally I would make it comma delimited)
  • When you start, load the file and populate the array (if you delimited with a comma or other character(s), read it into a string and use the split function.)

The salient code/pieces to resizing the array are:

// should be in an accessible class scope - public or maybe even static
int[] myList = new list[0];             //start at 0 or empty

//function ressize Array by 1, accessible class scope - public or even static
static public int[] incrementIntArrayBy1(int[] oldArray){
        int[] newArray = new int[oldArray.Length + 1];
        Array.Copy(oldArray, newArray, oldArray.Length);
        return newArray;
    } 

//function on button
private void button1_Click(object sender, EventArgs e){
    mylist = incrementIntArrayBy1(myList);
    myList[myList.length-1] =  new Random().Next(1, 1000);
}
  • Saving to a file is not an option for me. – lewis4u Oct 28 '17 at 11:36
  • Why not use `List` instead of writing all this code yourself? – CSharpie Oct 28 '17 at 11:37
  • Seemed unnecessary given it's a simple array of integers. – Robert MacMillan Oct 28 '17 at 11:39
  • lewis4u, your question mentioned "any additional files" - this would be using the same "1" file that you currently have. You could put them into an HKEY_LOCAL_MACHINE or current user registry key (as someone suggested, depending on your need) - would be trivial if you're serializing or saving the generated numbers as a comma-delimited list. – Robert MacMillan Oct 28 '17 at 11:44
0

I would generate the random numbers slightly differently.

  1. Create a pair of integers stored together.
  2. Store all of the numbers 1 to 9999 as the first number in the pair
  3. Generate a random integer as the second number (any size)
  4. Sort the pairs on the second number
  5. Save these pairs in a file
  6. When you want an integer between 1 and 9999, read the next number on the list
  7. When you've read them all, go back to step 3.

This prevents having to check all the numbers to see whether they have been previously generated which may cause delays when you are reaching the last few numbers.

Rob Anthony
  • 1,743
  • 1
  • 13
  • 17