Dictionary.ContainsValue() always returning true - c#

I have a dictionary of all alphabets mapped to morse code
Dictionary<string, string> data = new Dictionary<string, string>();
data.Add("a", ".-");
data.Add("b", "-...");
data.Add("c", "-.-.");
data.Add("d", "-..");
data.Add("e", ".");
data.Add("f", "..-.");
data.Add("g", "--.");
data.Add("h", "....");
data.Add("i", "..");
data.Add("j", ".---");
data.Add("k", "-.-");
data.Add("l", ".-..");
data.Add("m", "--");
data.Add("n", "-.");
data.Add("o", "---"); and so on..
I'm trying to check on a condition if the substring of an existing morse code exists in the dictionary or not.
foreach (var item in arraylist)
{
int smallcount=0;
int startIndex = 0;
//check if this combination exists for morse code
for(int w=0;w<shortInput;w++)
{
int substringLength=Convert.ToInt32(item[w].ToString());
string sub = morsecode.Substring(startIndex, substringLength);
if (data.ContainsValue(sub)) ;
{
smallcount++;
}
startIndex = startIndex + substringLength;
}
if(smallcount==shortInput)
{ count++; }
}
Here data.ContainsValue(sub) always returns true even if the value does not exist in the dictionary.
Can anyone tell me if i'm missing anything.?

ContainsValue is not actually returning true, however you have a stray semicolon after the if statement. This means that the following block will always be executed, as it is not executed conditionally. It gets treated as follows:
if (data.ContainsValue(sub))
{
}
{
smallcount++;
}
Instead, remove the semicolon so that you actually have a block directly following the if statement, like so:
if (data.ContaisnValue(sub))
{
smallcount++;
}

Related

Checking Each Element in an Array to See if it is equal to a string

I have a number of elements in an array, I would like to check if a string is equal to any of these elements in the array. The number of elements in the array can change in number.
I have counted the number of elements in the array hoping to get somewhat of an advantage but haven't been able to come up with a solution.
int ArrayCount = FinalEncryptText.Count();
foreach (string i in FinalEncryptText)
{
}
Using the foreach implementation you have provided, you could include an if condition with String.Equals(string) - as Sean pointed out earlier.
But it's worth noting that String.Equals(string) without additional arguments is equivalent to using the == operator. So it's better if you specify the StringComparison type so that you express what kind of comparison you wish to perform.
For example, you could do something like this:
foreach (string element in myStringArray)
{
if(element.Equals("foo", StringComparison.CurrentCultureIgnoreCase))
...
}
You could even include the evaluation as a predicate in a LINQ query. For example, let's say you wanted to see which strings passed the evaluation:
var matches = myStringArray
.Where(element => element.Equals("foo", StringComparison.CurrentCultureIgnoreCase));
You can read more about comparing strings here.
I'm not sure what your method looks like, but I'm assuming.. you're given a random array of strings.. and you want to find a certain element in that array. Using a foreach loop:
public string Check(string[] FinalEncryptText)
{
foreach (string i in FinalEncryptText)
{
//let's say the word you want to match in that array is "whatever"
if (i == "whatever")
{
return "Found the match: " + i;
}
}
}
Using a regular for loop:
public string Check(string[] FinalEncryptText)
{
for (int i = 0; i < FinalEncryptText.Count; i++)
{
//let's say the word you want to match in that array is "whatever"
if (FinalEncryptText[i] == "whatever")
{
//Do Something
return "Found the match: " + FinalEncryptText[i];
}
}
}
Now if you already have a fixed array.. and you're passing in a string to check if that string exists in the array then it would go something like this:
public string Check(string stringToMatch)
{
for (int i = 0; i < FinalEncryptText.Count; i++)
{
//this will match whatever string you pass into the parameter
if (FinalEncryptText[i] == stringToMatch)
{
//Do Something
return "Found the match: " + FinalEncryptText[i];
}
}
}
You could use the String.Equals method in an if statement. More info on String.Method here: String.Equals Method.
if(firstString.Equals(secondString))
{
//whatever you need to do here
}

Not all code paths return a value c#

I have declared a method in a class to compare two numbers and I'm having an issue. I'm getting an error saying not all code paths return a value. I want to return an int for every matching number in the char arrays.
Here is an image of the code.
public int CompareCodes(string rndselect, string personselect)
{
char[] rndnumber = rndselect.ToCharArray(); //take the randoms elected one and convert it to a char array
char[] perNum = personselect.ToCharArray();
likeness0 = 0;
likeness1 = 1;
foreach (char RndNum in rndnumber)
{
foreach (char Pnum in perNum)
{
if (RndNum == Pnum)
{
return likeness1;
}
else
{
return likeness0;
}
}
}
}
What should compiler think if your perNum is empty?
The error says exactly what is wrong with your code. Having a foreach loop doesn't guarantee anything inside the foreach is executed. If rndnumber or perNum happens to be empty, there is nothing to loop through and your code actually doesn't return anything.
If rndselect or perNum is empty string.
So no value is returned.
If you sure these string are always not null. so add
return 0
at the end of block.

Find biggest concatenation word in array

I'm new to C#, can someone help me understand why my code doesnt work?
Seems like there something wrong with variable word which needs to be returned, but I don't understand what.
public virtual bool concatOnly()
{
int tmp = 0;
foreach (string word in words)
{
tmp += word.Length;
}
return (tmp <= word.Length);
}
I also don't really understand what I need to do in this:
public virtual void removeRepeat()
{
IEnumerator<string> iterator = words.GetEnumerator();
string checkWord = null;
while (iterator.MoveNext())
{
checkWord = iterator.Current;
foreach (string tmpWord in words)
{
if (tmpWord.Contains(checkWord) && checkWord.Length < tmpWord.Length)
{
iterator.Remove();
break;
}
}
}
}
Here's my full code
Update 3
In order to fix the second compile error (see Update 2), you need to remove from the list without doing so via Iterator, which has no remove method. One way would be the following, which saves up the indexes for removal after traversal by the iterator. Note that I remove the indexes in reverse order, so that the index numbers to be removed are not changed by prior removals.
public virtual void removeRepeat()
{
IEnumerator<string> iterator = words.GetEnumerator();
string checkWord = null;
List<int> removeIndexes = new List<int>();
int i = -1;
while (iterator.MoveNext())
{
checkWord = iterator.Current;
i++;
foreach (string tmpWord in words)
{
if (tmpWord.Contains(checkWord) && checkWord.Length < tmpWord.Length)
{
removeIndexes.Add(i);
break;
}
}
}
removeIndexes.Reverse();
foreach(var index in removeIndexes) {
words.RemoveAt(index);
}
}
Update 2
After fixing the first compile error (see my original answer below, which now works), your code is still giving this compile error main.cs(90,38): error CS1061: TypeSystem.Collections.Generic.IEnumerator' does not contain a definition for Remove' and no extension methodRemove' of typ
e `System.Collections.Generic.IEnumerator' could be found.
Update
I've changed my original answer to something that at least compiles. What I did is to change the original return (tmp <= word.Length); back to using word, which is the class member variable, not the local variable.
Original
Change the name of variable word in method concatOnly():
public virtual bool concatOnly()
{
int tmp = 0;
foreach (string w in words)
{
tmp += w.Length;
}
return (tmp <= word.Length);
}
This is because your class ConcatWord, of which concatOnly is a member method, already has a member variable named word: internal string word;.
FYI, the above shows that you also need to post the full code for the class ConcatWord. It's fine to give the link to the full code that you provided, that can be helpful, but everything required to reproduce the error also needs to be present in your question here at SO.

Not all code paths return a values

I have written a function to find the the line by searching the text and after it find that particular line, I want to read the next line and return that text. The function is as follows:
public static string NextString(string textfind)
{
List<string> found = new List<string>();
string linejd;
using (StreamReader efile = new StreamReader(FILENAME))
{
int counter = 0;
while ((linejd = efile.ReadLine()) != null)
{
counter++;
if (linejd.Contains(textfind))
{
found.Add(linejd);
string nextstring = efile.ReadLine();
return nextstring;
}
}
}
}
File name has been defined as:
const string FILENAME = #"E:\model\Yen and Lee\AQRun01\eratc.inp";
However, I keep on getting error:
AQ.Program.NextString(string)': not all code paths return a value
What if in your function above, your code doesn't enter the loop or the if (linejd.Contains(textfind)) block? The function returns no value!
I tend to recommend declaring a function's result variable and setting its value within the function and then returning it at the end:
static public string nextstring(string textfind)
{
string result = string.Empty;
List<string> found = new List<string>();
string linejd;
/* ********************************************************
* Find the line with certain string */
using (StreamReader efile = new StreamReader(FILENAME))
// using (efile)
{
int counter = 0;
while ((linejd = efile.ReadLine()) != null
&& string.IsNullOrWhiteSpace(result)) // Quit the loop once we have a result!
{
counter++;
if (linejd.Contains(textfind))
{
found.Add(linejd);
string nextstring = efile.ReadLine();
result = nextstring; }
}
}
return result;
}
If the condition linejd.Contains(textfind) is never true then the function will never return anything, yet the function declaration states that it will return a string. You can fix this by returning a default value (such as an empty string) after the using block.
There are two reasons to why the function could exit without a return value:
The file is empty, so the while loop is never entered.
The condition linejd.Contains(textfind) is never true.
Even if you know that the file is never empty, and that the string can always be found in the file, the compiler doesn't know that. (Although, the while loop doesn't make sense if you know that the string can always be found, as that means that you will never reach the end of the file.)
You need to tell the compiler what to do for both those cases, for example by adding return null; at the end of the function.
Alternatively rewrite the code so that it actually relies on the file always containing something and that the string is always found. That way there is no loose ends to take care about. That of course means that the code will crash or hang if the file actually would be empty or the string is not found.
How about using Linq?
public static string NextString(string textfind)
{
return File.ReadLines(FILENAME)
.SkipWhile(line => !line.Contains(textfind))
.Skip(1)
.First();
}
when the if case is always fault, then your method will return nothing.. That's why you get an error.
try writing a return value before the end of your method like:
public static string NextString(string textfind)
{
List<string> found = new List<string>();
string linejd;
string new_string = string.Empty;
using (StreamReader efile = new StreamReader(FILENAME))
{
int counter = 0;
while ((linejd = efile.ReadLine()) != null)
{
counter++;
if (linejd.Contains(textfind))
{
found.Add(linejd);
string nextstring = efile.ReadLine();
return nextstring;
}
}
}
return (new_string);
}

The given key was not present in the dictionary. Even when dictionary.ContainsKey("given_key") == true

I have a class that gathers 7-day forecast data from the Bureau or Meteorology and presents it on a web page. A script runs every 30 minutes to get updated data from the Bureau.
The bureau provides data in a tab delimited format with a header row. After extracting all the fields, I put the values into a Dictionary<string,string> for parsing. For obvious reasons, the important field for organising the data is the "forecast_date". So before I begin parsing, I make sure that my dictionary actually contains this key.
Here is a very simplified example of what I'm doing:
static object ForecastLockingObj= new object();
private void UpdateWeather()
{
if(isTimeForUpdate())
{
lock(ForecastLockingObj)
{
if(isTimeForUpdate())
{
Dictionary<string, string> ForecastData = Get7DayForecast();
int forecastDate = int.MinValue;
if (ForecastData.ContainsKey("forecast_date") && int.TryParse(ForecastData["forecast_date"], out forecastDate))
{
//Parse the data
SetNextUpdateTime();
}
}
}
}
}
This actually works for the most part. But very occasionally I'll get the following exception:
[KeyNotFoundException: The given key was not present in the dictionary.]
System.ThrowHelper.ThrowKeyNotFoundException() +28
System.Collections.Generic.Dictionary`2.get_Item(TKey key) +7457036
CoA.WebUI.Controls.WeatherWidget.UpdateWeather() in C:\dev\WeatherWidget.cs:231
Where line 231 is the if statement that checks the existence of "forecast_date" then attempts to parse it into an integer. Note; the service reliably renders dates as integers (e.g. 20130515) and so this is more of a sanity check.
ContainsKey should not be throwing this exception, so I feel it must be where I refer to ForecastData["forecast_date"] in my TryParse.
My question is this; surely if ContainsKey returns false, then TryParse should not run. So why would it report the existence of a key in one statement and then deny its existence in the very next statement... whilst we are inside a lock and the Dictionary we're working on is non-static and local?
As an aside; this typically happens in the afternoon, when the Bureau releases the next long range forecast. The exception happens for a few page-loads and then rights itself.
Here is the full Get7DayForecast method
private Dictionary<string, string> Get7DayForecast()
{
int linenumber = 0;
int locationNameKey = 0;
List<string> keys = new List<string>();
Dictionary<string, string> myLocationData = new Dictionary<string, string>();
FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(ForecastURL);
ftp.Method = WebRequestMethods.Ftp.DownloadFile;
ftp.Credentials = new NetworkCredential();
FtpWebResponse ftp_response = (FtpWebResponse)ftp.GetResponse();
if (ftp_response.WelcomeMessage.StartsWith("230") && ftp_response.StatusDescription.StartsWith("150"))
{
Stream ftp_responseStream = ftp_response.GetResponseStream();
StreamReader ftp_reader = new StreamReader(ftp_responseStream);
while (ftp_reader.Peek() >= 0)
{
linenumber++;
string line = ftp_reader.ReadLine();
List<string> temp = (List<string>)line.Split(ForecastDelimiter).ToList<string>();
if (linenumber == 1)
{
//Break if the header line does not contain the fields we require
if (!ForecastRequiredFields.All(line.Contains)) { break; }
keys = temp;
locationNameKey = keys.IndexOf(ForecastLocationFieldName);
}
else if (temp.Count == keys.Count && temp[locationNameKey] == ForecastLocationName)
{
for (int i = 0; i < keys.Count; i++)
{
myLocationData.Add(keys[i], temp[i]);
}
//Break if we've just parsed the data we were looking for
break;
}
}
ftp_reader.Close();
}
ftp_response.Close();
return myLocationData;
}
Honestly I cannot see why your code would fail but you should consider taking advantage of Trace to see what is up. Also it couldn't hurt to use TryGetValue instead.
var map = Get7DayForecast();
string forecastDateString;
if (!map.TryGetValue("forecast_date", out forecastDateString))
{
Trace.WriteLine("forecast_date entry was not found.");
return;
}
int foreCastDate;
if (!int.TryParse(forecastDateString, out foreCastDate)
{
Trace.WriteLine("Value was not a valid integer: " + forecastDateString);
return;
}
SetNextUpdateTime();

Categories

Resources