i've this piece of code from an open source c# program.
I'm trying to figure out the purpose behind this snippet.
internal static bool ReadAsDirectoryEntry(BinaryReader br)
{
bool dir;
br.BaseStream.Seek(8, SeekOrigin.Current);
dir = br.ReadInt32() < 0;
br.BaseStream.Seek(-12, SeekOrigin.Current);
return dir;
}
The code on LINE 6 is unclear to me , can anyone explain what it does ?
How can a bool have a value of the returned int32 and smaller than zero ?
Thanks!
You read an int and check if this int is smaller than 0. The expression br.ReadInt32() < 0 will result in a bool. This bool result you assign to your variable.
internal static bool ReadAsDirectoryEntry(BinaryReader br)
{
bool dir;
// Skip 8 bytes starting from current position
br.BaseStream.Seek(8, SeekOrigin.Current);
// Read next bytes as an Int32 which requires 32 bits (4 bytes) to be read
// Store whether or not this integer value is less then zero
// Possibly it is a flag which holds some information like if it is a directory entry or not
dir = br.ReadInt32() < 0;
// Till here, we read 12 bytes from stream. 8 for skipping + 4 for Int32
// So reset stream position to where it was before this method has called
br.BaseStream.Seek(-12, SeekOrigin.Current);
return dir;
}
basically, that is logically equivalent to (but terser than):
bool dir;
int tmp = br.ReadInt32();
if(tmp < 0)
{
dir = true;
}
else
{
dir = false;
}
It:
does the call to ReadInt32() (which will result in an int)
tests whether the result of that is < 0 (which will result in either true or false)
and assigns that result (true or false) to dir
To basically, it will return true if and only if the call to ReadInt32() gives a negative number.
The line 6 means : read an Int32 then compare it to 0 and then store the comparison result into a Boolean.
It's equivalent as :
Int32 tmp = br.ReadInt32();
dir = tmp < 0;
Related
SUMMARY
in reading bytes from a file in chunks(not got a specific size between 128 - 1024, haven't decided yet) and i want to search the buffer to see if it contains a signature(pattern) of another byte array, and if it finds some of the pattern at the very end of the buffer it should read the next few bytes from the files to see if its found a match
What I've Tried
public static bool Contains(byte[] buffer, byte[] signiture, FileStream file)
{
for (var i = buffer.Length - 1; i >= signiture.Length - 1; i--) //move backwards through array stop if < signature
{
var found = true; //set found to true at start
for (var j = signiture.Length - 1; j >= 0 && found; j--) //loop backwards throughsignature
{
found = buffer[i - (signiture.Length - 1 - j)] == signiture[j];// compare signature's element with corresponding element of buffer
}
if (found)
return true; //if signature is found return true
}
//checking end of buffer for partial signiture
for (var x = signiture.Length - 1; x >= 1; x--)
{
if (buffer.Skip(buffer.Length - x).Take(x).SequenceEqual(signiture.Skip(0).Take(x))) //check if partial is equal to partial signiture
{
byte[] nextBytes = new byte[signiture.Length - x];
file.Read(nextBytes, 0, signiture.Length - x); //read next needed bytes from file
if (!signiture.Skip(0).Take(x).ToArray().Concat(nextBytes).SequenceEqual(signiture))
return false; //return false if not a match
return true; //return true if a match
}
}
return false; //if not found return false
}
This works but I've been told linq is slow and that i should use Array.IndexOf(). I've tried that but cant figure out how to implement it
You can make use of Span<T>, AsSpan and MemoryExtensions.SequenceEqual. The latter is not LINQ; it is optimized, especially for byte arrays. It unrolls the loop and uses unsafe code to essentially do a memcmp.
If you aren't using a framework that includes these types/methods by default, (.Netcore2.1+,. Netstandard 2.1) you can add the System.Memory nuget package. The implementation of SequenceEqual is a bit different (the so-called "slow version") but it is still faster than using LINQ's SequenceEqual.
Note that you also need to check the return value of FileStream.Read.
public static bool Contains(byte[] buffer, byte[] signiture, FileStream file)
{
var sigSpan = signiture.AsSpan();
//move backwards through buffer and check if signature found
for (var i = buffer.Length - signiture.Length; i >= 0; i--)
{
if (buffer.AsSpan(i, signiture.Length).SequenceEqual(sigSpan))
return true;
}
for (var x = signiture.Length - 1; x >= 1; x--)
{
var sig = sigSpan.Slice(0, x);
if (buffer.AsSpan(buffer.Length - x).SequenceEqual(sig)) //check if partial is equal to partial signiture
{
var sigLen = signiture.Length;
byte[] nextBytes = ArrayPool<byte>.Shared.Rent(sigLen - x);
// need to store number of bytes read
var read = file.Read(nextBytes, 0, sigLen - x); //read next needed bytes from file
var next = nextBytes.AsSpan(0, read);
// don't need to concat with signature, because obviously signature is going to
// start with signature.Skip(0).Take(...)
// just test that the number of bytes we read, plus the number we will skip equals
// the actual length, then check the remainder
var result = (read + x == signiture.Length
&& signiture.AsSpan(x).SequenceEqual(next));
ArrayPool<byte>.Shared.Return(nextBytes);
return result;
}
}
return false; //if not found return false
}
I have made a program that reads an input of a bunch of random numbers and tests them to see if they meet certain criteria. If they meet the criteria then the method returns true.
What i'm wondering is whether or not there is a way I can keep a total of how many values return true.
To save space ill just post the input method and the count method I have started to use!
Any help would be greatly appreciated!
This is where I am at so far...
public bool Requirement(int input, int countOfTrue)
{
if (input % 8 == 0 && input % 11 == 0)
{
Console.WriteLine("True");
countOfTrue = countOfTrue + 1;
return true;
}
return false;
}
public int TotalTrue(int countOfTrue)
{
Console.WriteLine("Number of True: ");
return countOfTrue;
}
Change it to:
public bool Requirement(int input, ref int countOfTrue)
{
if (input % 8 == 0 && input % 11 == 0)
{
Console.WriteLine("True");
countOfTrue = countOfTrue + 1;
return true;
}
return false;
}
Adding ref will modify the original variable, not just the stack-local one.
As Kevin pointed out, you actually can't use out since the variable won't get assigned if the if condition is false.
You can make a property for true count instead of making method. The would save the method call and also space for code. Saving space with wrong design is not a good practice. You can use the ref to send the initial value that could be incremented but you would need to save the returned value to be used for next call.
public TotalTrueCount {get; set;}
public bool Requirement(int input)
{
if (input % 8 == 0 && input % 11 == 0)
{
Console.WriteLine("True");
TotalTrueCount++;
return true;
}
return false;
}
The best and most consice way is to use the FindAll method, which is designed specifically for this.
var numbers = new List<int>();
// read the numbers into the list (e.g. from file)
var results = numbers.FindAll(num => num % 8 == 0 && num % 11 == 0); // returns a new list with all the numbers matching your predicate
var resultsCount = results.Count; // number of resulting numbers
I am trying to implement the IComparable interface in my custom object so that List.Sort() can sort them alphabetically.
My object has a field called _name which is a string type, and I want it to sort based on that. Here is the method I implemented:
public int CompareTo(object obj)
{
//Int reference table:
//1 or greater means the current instance occurs after obj
//0 means both elements occur in the same position
//-1 or less means the current instance occurs before obj
if (obj == null)
return 1;
Upgrade otherUpgrade = obj as Upgrade;
if (otherUpgrade != null)
return _name.CompareTo(otherUpgrade.Name);
else
throw new ArgumentException("Passed object is not an Upgrade.");
}
Not sure if I did something wrong or if it's just the way the string CompareTo works, but basically my List was sorted like this:
Test Upgrade
Test Upgrade 10
Test Upgrade 11
Test Upgrade 12
Test Upgrade 13
Test Upgrade 14
Test Upgrade 15
Test Upgrade 2
Test Upgrade 3
Test Upgrade 4
Test Upgrade 5
I want them to be sorted like this:
Test Upgrade
Test Upgrade 2
Test Upgrade 3
...etc
You want "natural order" -- the collation that a human who is familiar with the conventions of English would choose -- as opposed to what you've got, which is "lexicographic" collation: assign every letter a strict ordering, and then sort by each letter in turn.
Jeff has a good article on some of the ins and outs here, with links to different algorithms that try to solve the problem:
http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html
and Raymond discussed how Windows dealt with it here:
http://technet.microsoft.com/en-us/magazine/hh475812.aspx
Basically the problem is: natural order collation requires solving an artificial intelligence problem; you're trying to emulate what a human would do, and that can be surprisingly tricky. Good luck!
Strings are sorted in lexicographic order. You'll have to either format all your numbers to have the same length (eg: Test Upgrade 02) or parse the number in your comparer and incorporate it in your comparison logic.
The reason this happens is that you are doing string comparison, which has no explicit knowledge of numbers. It orders each string by the respective character codes of each character.
To get the effect you want will require a bit more work. See this question: Sort on a string that may contain a number
AlphaNumeric Sorting
public class AlphanumComparatorFast : IComparer
{
public int Compare(object x, object y)
{
string s1 = x as string;
if (s1 == null)
{
return 0;
}
string s2 = y as string;
if (s2 == null)
{
return 0;
}
int len1 = s1.Length;
int len2 = s2.Length;
int marker1 = 0;
int marker2 = 0;
// Walk through two the strings with two markers.
while (marker1 < len1 && marker2 < len2)
{
char ch1 = s1[marker1];
char ch2 = s2[marker2];
// Some buffers we can build up characters in for each chunk.
char[] space1 = new char[len1];
int loc1 = 0;
char[] space2 = new char[len2];
int loc2 = 0;
// Walk through all following characters that are digits or
// characters in BOTH strings starting at the appropriate marker.
// Collect char arrays.
do
{
space1[loc1++] = ch1;
marker1++;
if (marker1 < len1)
{
ch1 = s1[marker1];
}
else
{
break;
}
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
do
{
space2[loc2++] = ch2;
marker2++;
if (marker2 < len2)
{
ch2 = s2[marker2];
}
else
{
break;
}
} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
// If we have collected numbers, compare them numerically.
// Otherwise, if we have strings, compare them alphabetically.
string str1 = new string(space1);
string str2 = new string(space2);
int result;
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
{
int thisNumericChunk = int.Parse(str1);
int thatNumericChunk = int.Parse(str2);
result = thisNumericChunk.CompareTo(thatNumericChunk);
}
else
{
result = str1.CompareTo(str2);
}
if (result != 0)
{
return result;
}
}
return len1 - len2;
}
}
Usage :
using System;
using System.Collections;
class Program
{
static void Main()
{
string[] highways = new string[]
{
"100F",
"50F",
"SR100",
"SR9"
};
//
// We want to sort a string array called highways in an
// alphanumeric way. Call the static Array.Sort method.
//
Array.Sort(highways, new AlphanumComparatorFast());
//
// Display the results
//
foreach (string h in highways)
{
Console.WriteLine(h);
}
}
}
Output
50F 100F SR9 SR100
Thanks for all the replies guys. I did my own method and it seems to work fine. It doesn't work for all cases but it works for my scenario. Here is the code for anyone who is interested:
/// <summary>
/// Compares the upgrade to another upgrade
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public int CompareTo(object obj)
{
//Int reference table:
//1 or greater means the current instance occurs after obj
//0 means both elements occur in the same position
//-1 or less means the current instance occurs before obj
if (obj == null)
return 1;
Upgrade otherUpgrade = obj as Upgrade;
if (otherUpgrade != null)
{
//Split strings into arrays
string[] splitStringOne = _name.Split(new char[] { ' ' });
string[] splitStringTwo = otherUpgrade.Name.Split(new char[] { ' ' });
//Will hold checks to see which comparer will be used
bool sameWords = false, sameLength = false, bothInt = false;
//Will hold the last part of the string if it is an int
int intOne = 0, intTwo = 0;
//Check if they have the same length
sameLength = (splitStringOne.Length == splitStringTwo.Length);
if (sameLength)
{
//Check to see if they both end in an int
bothInt = (int.TryParse(splitStringOne[splitStringOne.Length - 1], out intOne) && int.TryParse(splitStringTwo[splitStringTwo.Length - 1], out intTwo));
if (bothInt)
{
//Check to see if the previous parts of the string are equal
for (int i = 0; i < splitStringOne.Length - 2; i++)
{
sameWords = (splitStringOne[i].ToLower().Equals(splitStringTwo[i].ToLower()));
if (!sameWords)
break;
}
}
}
//If all criteria is met, use the customk comparer
if (sameWords && sameLength && bothInt)
{
if (intOne < intTwo)
return -1;
else if (intOne > intTwo)
return 1;
else //Both equal
return 0;
}
//Else use the default string comparer
else
return _name.CompareTo(otherUpgrade.Name);
}
else
throw new ArgumentException("Passed object is not an Upgrade.");
}
Will work for strings spaced out using a " " character, like so:
Test data:
Hello 11
Hello 2
Hello 13
Result
Hello 2
Hello 11
Hello 13
Will not work for data such as Hello11 and Hello2 since it cannot split them. Not case sensitive.
I have 2 functions within a class and getting error on the call for ParseBits() function i.e. "int num_elements = ParseBits(bits, buffer);" because of the "buffer" arguement I am passing "public int ParseBits(string bits, int* buffer)":
Function 1:
public float AssignFitness(string bits, int target_value)
{
//holds decimal values of gene sequence
int[] buffer = new int[(VM_Placement.AlgorithmParameters.chromo_length / VM_Placement.AlgorithmParameters.gene_length)];
int num_elements = ParseBits(bits, buffer);
// ok, we have a buffer filled with valid values of: operator - number - operator - number..
// now we calculate what this represents.
float result = 0.0f;
for (int i=0; i < num_elements-1; i+=2)
{
switch (buffer[i])
{
case 10:
result += buffer[i+1];
break;
case 11:
result -= buffer[i+1];
break;
case 12:
result *= buffer[i+1];
break;
case 13:
result /= buffer[i+1];
break;
}//end switch
}
// Now we calculate the fitness. First check to see if a solution has been found
// and assign an arbitarily high fitness score if this is so.
if (result == (float)target_value)
return 999.0f;
else
return 1/(float)fabs((double)(target_value - result));
// return result;
}
Function 2:
public int ParseBits(string bits, int* buffer)
{
//counter for buffer position
int cBuff = 0;
// step through bits a gene at a time until end and store decimal values
// of valid operators and numbers. Don't forget we are looking for operator -
// number - operator - number and so on... We ignore the unused genes 1111
// and 1110
//flag to determine if we are looking for an operator or a number
bool bOperator = true;
//storage for decimal value of currently tested gene
int this_gene = 0;
for (int i = 0; i < VM_Placement.AlgorithmParameters.chromo_length; i += VM_Placement.AlgorithmParameters.gene_length)
{
//convert the current gene to decimal
this_gene = BinToDec(bits.Substring(i, VM_Placement.AlgorithmParameters.gene_length));
//find a gene which represents an operator
if (bOperator)
{
if ((this_gene < 10) || (this_gene > 13))
continue;
else
{
bOperator = false;
buffer[cBuff++] = this_gene;
continue;
}
}
//find a gene which represents a number
else
{
if (this_gene > 9)
continue;
else
{
bOperator = true;
buffer[cBuff++] = this_gene;
continue;
}
}
}//next gene
// now we have to run through buffer to see if a possible divide by zero
// is included and delete it. (ie a '/' followed by a '0'). We take an easy
// way out here and just change the '/' to a '+'. This will not effect the
// evolution of the solution
for (int i = 0; i < cBuff; i++)
{
if ((buffer[i] == 13) && (buffer[i + 1] == 0))
buffer[i] = 10;
}
return cBuff;
}
I am getting 2 errors for this functions on the highlighted lines:
Error 1: The best overloaded method match for 'VM_Placement.Program.ParseBits(string, int*)' has some invalid arguments
Error 2: Pointers and fixed size buffers may only be used in an unsafe context
You need to enclose your function using raw pointers in an unsafe block.
unsafe
{
//your code
}
I had the same problem, but it wasn't solved by any of the other answers up here. I kept getting different errors.
Whatever functions use unsafe code simply need to be declared with the "unsafe" keyword.
For example:
static unsafe void myFunction(int* myInt, float* myFloat)
{
// Function definition
}
Personally, I was trying to do this when making a wrapper class.
For those interested, it ended up looking something like this:
using System.Runtime.InteropServices;
namespace myNamespace
{
public class myClass
{
[DllImport("myLib.so", EntryPoint = "myFunction")]
public static extern unsafe void myFunction(float* var1, float* var2);
}
}
Theres a lot of great information in the MSDN "Unsafe Code Tutorial":
https://msdn.microsoft.com/en-us/library/aa288474(v=vs.71).aspx
It's probably worth a read, I found it quite useful.
Perhaps I've missed it, but you don't appear to be doing anything that actually requires the use of a int*. Why not simply pass it an int array and change the ParseBits function signature to:
public int ParseBits(string bits, int[] buffer)
and remove the unsafe{ ... } blocks altogether.
Basically comparing a string that is entered, and trying to get that position from the array.
If I initialize position to 0 then it returns the position zero of the array, if I initialize to 1 then it gives me the item in slot 1, so it's skipping the compare statement.
I also tried using (custStatus == cardStatus[i])
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
int position= 0;
int discount;
for(int i = 0; i < 2; i++)
{
if (string.Equals(custStatus, cardStatus[i]))
position = i;
}
discount = pDiscount[position];
return discount;
}
With your code, there's no way to tell if position = 0 means custStatus was found in your cardStatus array or if no match was made at all and the default value is being used. I'd recommend either using a boolean matchFound variable or setting position = -1 and adding an extra if statement at the end either way. Either:
boolean matchFound = false;
...
if(matchFound)
{
discount = pDiscount[position];
}
or else
int position = -1;
...
if(position >= 0)
{
discount = pDiscount[position];
}
Give this a try:
public static int discount(string[] cardStatus, int[] pDiscount, string custStatus) {
var position = Array.IndexOf(cardStatus, custStatus);
return (position == -1) ? -1 : pDiscount[position];
}
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
for(int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length); i++)
{
if (string.Equals(custStatus, cardStatus[i]))
{
return pDiscount[i];
}
}
return -1;
}
Don't be afraid to return directly from FOR-loop, it is old-school that teaches to have only one return point from method. You can have as many returns as it helps you to keep your code clean and easy to read.
And perhaps it would be better to use the following expression in for-loop as it will guard you from possible different lengths of arrays:
for (int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length; i++)
This looks ok, even though this is somewhat more straightforward:
for(int i = 0; i < cardStatus.Length; i++)
{
if (custStatus == cardStatus[i])
{
position = i;
break;
}
}
Given your question it appears to be the case that all cardStatus[i] match custStatus - did you check the input?
Also given your code what happens if there is no match? Currently you would return pDiscount[0] - that doesn't seem to be correct.