Here is the code I use to get the different weather forecasts from the Environment Canada website: public static void Main() {   string url = http://dd.weather.gc.ca/nowcasting/matrices/SCRIBE.NWCSTG. + DateTime.Now.ToString(MM.dd.HH) + Z.n.Z;   string allStations = Decompress.zDecompress(url).ToString();   string temp = allStations.Substring(allStations.IndexOf(STN: CYYC));   string weatherReports = temp.Substring(0, temp.IndexOf(+\n.));   string[] lines = weatherReports.Split(new string[] { \n }, StringSplitOptions.None);   Station s = new Station();   foreach (string line in lines)   {     if (line.IndexOf(-) != 0 && line.IndexOf(STN) != 0 && line.IndexOf(DATE) != 0)        {          Weather w = new Weather();          string[] properties = line.Split('|');          for (int i = 0; i < properties.Length; i++)              {               properties[i] = properties[i].Trim();                if (properties[i] == ){                    properties[i] = 0;                }              }           w.SkyCover = int.Parse(properties[1].Trim());           w.Ceiling = int.Parse(properties[2].Trim());           w.Pcpn1 = properties[3].Trim();           w.Pop1 = int.Parse(properties[4].Trim());           w.Pcpn2 = properties[5].Trim();           w.Pop2 = int.Parse(properties[6].Trim());           w.Pcpn3 = properties[7].Trim();           w.Pop3 = int.Parse(properties[8].Trim());           w.Pop = int.Parse(properties[9].Trim());           w.PcpnQuantity = double.Parse(properties[10].Trim());           w.PcpnType = properties[11].Trim();           w.Temperature = double.Parse(properties[12].Trim());           w.DewPoint = double.Parse(properties[13].Trim());           w.WindDirection = int.Parse(properties[14].Trim());           w.WindSpeed = int.Parse(properties[15].Trim());           w.GustSpeed = int.Parse(properties[16].Trim());           w.Visibility = double.Parse(properties[17].Trim());           w.VisObstacleType = properties[18].Trim();           s.Reports.Add(w);}}}And here is what the string looks like after my substrings:STN: CYYC    |SKY|CIG|        PRECIPITATION        |POP|   ACC  |    TEMP   |    WIND   |  VIS   |\nDATE      HR |/10|   |PCPN1|POP|PCPN2|POP|PCPN3|POP|   | Qp | Tp|  T  |  Td | DD| VV|GST|(SM) |TP|\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 0600|  8|140| -RW |100|     |  0|     |  0| 60| 0.0|   | 13.0| 10.0|  0|  0|   |15.00|  |\n20150805 0700|  8| 92|     |  0|     |  0|     |  0|  0| 0.0|   | 13.0| 11.0|290|  9|   |10.00|  |\n20150805 0800|  9| 82|     |  0|     |  0|     |  0|  0| 0.0|   | 13.0| 11.0|  0|  0|   |15.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 0900|  6| 91|     |  0|     |  0|     |  0|  0| 0.0|   | 13.0| 10.0|  0|  0|   |15.00|  |\n20150805 1000|  8| 84|     |  0|     |  0|     |  0|  0| 0.0|   | 13.0| 11.0|230|  8|   |15.00|  |\n20150805 1100| 10|113| -RW |100|     |  0|     |  0|100| 0.1| RA| 13.0| 11.0|277| 11|   |10.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 1200| 10| 93| -RW |100|     |  0|     |  0|100| 0.1| RA| 13.0| 10.8|225|  9|   | 7.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 1300|  8|999| -RW |100|     |  0|     |  0| 33| 0.1| RA| 13.9| 11.4|163|  6|   |15.00|  |\n20150805 1400|  8|999| -RW |100|     |  0|     |  0| 31| 0.1| RA| 14.4| 11.5|129|  7|   |15.00|  |\n20150805 1500|  8|999| -RW |100|     |  0|     |  0| 26| 0.0|   | 14.9| 11.6|134| 12|   |15.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 1600|  9|999|     |  0|     |  0|     |  0| 12| 0.0|   | 15.5| 11.4|196|  6|   |15.00|  |\n20150805 1700|  5|   |     |  0|     |  0|     |  0| 12| 0.0|   | 16.1| 11.0|289|  8|   |15.00|  |\n20150805 1800| 10|999|     |  0|     |  0|     |  0| 10| 0.0|   | 16.7| 10.7|335| 15|   |15.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 1900| 10|999|     |  0|     |  0|     |  0| 13| 0.0|   | 16.7| 10.2|353| 17|   |15.00|  |\n20150805 2000|  9|999|     |  0|     |  0|     |  0| 17| 0.0|   | 17.1| 10.1|349| 18|   |15.00|  |\n20150805 2100| 10|999|     |  0|     |  0|     |  0| 18| 0.0|   | 17.5| 10.0|346| 20|   |15.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+--+\n20150805 2200|  8|999|     |  0|     |  0|     |  0| 21| 0.0|   | 17.2| 10.4|354| 19|   |15.00|  |\n20150805 2300| 10|999| -RW | 80| -T  | 20|     |  0| 24| 0.3| RA| 16.9| 10.9|  3| 18|   |15.00|  |\n20150806 0000| 10|999| -RW | 60| -T  | 40|     |  0| 24| 1.6| RA| 16.6| 11.4| 13| 18|   |15.00|  |\n-------------+---+---+-----+---+-----+---+-----+---+---+----+---+-----+-----+---+---+---+-----+---+.Before my substrings, this string is repeated for every stations (a few hundred stations) and I use the STN: CODE and +. delimeter to isolate my desired station(CYYC here). Is there a better way to do the substrings and to assign the values to my weather objects?
Obtaining different weather forecasts from the Environment Canada website
c#;parsing
Single responsibilityEach method should have one clear responsibility. Your code is doing a lot of different things all in one method - the entry point of the application no less. Add in some additional methods to make things clearer:For example:private static string GetFullWeatherReport(){    string url = string.Format(http://dd.weather.gc.ca/nowcasting/matrices/SCRIBE.NWCSTG.{0:MM.dd.HH}Z.n.Z, DateTime.Now);    return Decompress.zDecompress(url).ToString();}private static IEnumerable<string> GetStationReports(){    // There appears to be a line with a only a dot between stations    return GetFullWeatherReport().Split(new[] { \n.\n }, StringSplitOptions.RemoveEmptyEntries); }That means you can now replace the first few lines of Main:public static void Main(){     IEnumerable<string> stationReports = GetStationReports();     var cyycReport = stationReports.FirstOrDefault(r => r.StartsWith(STN: CYYC));     foreach (var line in GetDataRows(cyycReport))     {         // ParseWeatherReport();     }} private static IEnumerable<string> GetDataRows(string weatherReport){    return weatherReport.Split(new[] { \n }, StringSplitOptions.RemoveEmptyEntries).Where(IsDataRow);}private static bool IsDataRow(string reportLine){    return !reportLine.StartsWith(-) && !reportLine.StartsWith(DATE) && !reportLine.StartsWith(STN);}Keep going through the code and extracting methods so that you can read Main like a book - I think a good rule of thumb is whether or not a non-programmer has a decent chance of figuring out what's happening.LINQI introduced a new concept or two into your code, one of which was LINQ. I can't explain the full magic of LINQ adequately so I enourage you to go and do some reading on it. The central concept is IEnumerable and a set of extension methods like Select, Where and FirstOrDefault.For example: string[] properties = line.Split('|');for (int i = 0; i < properties.Length; i++){    properties[i] = properties[i].Trim();    if (properties[i] == ){        properties[i] = 0;    }}Could become: string[] lines = line.Split('|').Select(s => s.Trim()).Select(s => string.IsNullOrEmpty(s) ? 0 : s).ToArray();varIf the type of an assignment is obvious, I prefer to use var e.g.var welcomeMessage = Hello!;vs string welcomeMessage = Hello!;I hope that's a useful start - all code typed directly into browser so apologies if it doesn't compile!