Why am I getting byte 0x00 at index 0 instead of 0xD0 when calling the SetData() method from outside the class?
Here's a shortened down of the class:
using System;
namespace StackOverflow
{
class Section
{
uint _sectionId;
byte[] _sectionData;
public Section(byte[] sectionData) {
_sectionData = sectionData;
_sectionId = GetUShort(0x0FF4);
Console.WriteLine(_sectionId + ": " + _sectionData[0].ToString("X")); // Gives D0
}
public void SetData() {
switch (_sectionId) {
case 0: SetTrainerInfo(); break;
default: break;
}
}
void SetTrainerInfo() {
Console.WriteLine(_sectionId + ": " + _sectionData[0].ToString("X")); // Can Give 0
byte[] deByte = GetBytes(0x00, 7);
TrainerInfo.playerName = PkmString.GetString(deByte);
Console.WriteLine(TrainerInfo.playerName + "name here");
}
}
}
Works fine if called in the Section constructor, but not from an external source like this:
using System;
namespace StackOverflow
{
class SaveBlock
{
const short SECTIONS = 14, SECTION_SIZE = 4096;
public Section[] sections = new Section[SECTIONS];
public SaveBlock(byte[] blockData) {
byte[] sectionData = new byte[SECTION_SIZE];
for (int i = 0; i < SECTIONS; i++) {
Array.Copy(blockData, SECTION_SIZE * i, sectionData, 0, SECTION_SIZE);
sections[i] = new Section(sectionData);
}
}
public void SetForAll() {
foreach (Section sect in sections)
sect.SetData();
}
}
}
And I get different bytes for the same element:
Look at this code from the SaveBlock constructor:
byte[] sectionData = new byte[SECTION_SIZE];
for (int i = 0; i < SECTIONS; i++) {
Array.Copy(blockData, SECTION_SIZE * i, sectionData, 0, SECTION_SIZE);
sections[i] = new Section(sectionData);
}
The loop copies the blockData bytes to the sectionData array, and then uses sectionData to create a new Section object instance. Here's where things get tricky... arrays are reference types. That means the following line in your Section constructor is only copying the reference to the array:
_sectionData = sectionData;
As you move through the loop, you're copying data into the same array instance over and over, and then assigning that same array instance to the internal data of several Section objects. All of those objects are sharing the same array instance! It's very likely you want a new array for each of those objects:
byte[] sectionData;
for (int i = 0; i < SECTIONS; i++) {
sectionData = new byte[SECTION_SIZE];
Array.Copy(blockData, SECTION_SIZE * i, sectionData, 0, SECTION_SIZE);
sections[i] = new Section(sectionData);
}
That may not be the only problem, as _sectionId is shown defined private an initialized to non-0. The SetData() method looks like this:
public void SetData() {
switch (_sectionId) {
case 0: SetTrainerInfo(); break;
default: break;
}
}
From the code we can see, there is no way that _sectionId will ever be 0, and thus no way that SetTrainerInfo() is ever called.
Related
I'm messing around with recursive types to get used to them and learn, I've written the following class:
public class ParameterData
{
public string[] Values { get; set; } = new string[0];
public ParameterData[] NestedValues { get; set; } = new ParameterData[0];
public bool IsNested { get => NestedValues.Length > 0; }
public int Length { get => IsNested ? NestedValues.Length : Values.Length; }
public dynamic this[int pos]
{
get
{
if (IsNested) return NestedValues[pos];
else return Values[pos];
}
set
{
if (IsNested) NestedValues[pos] = value;
else Values[pos] = value;
}
}
public static implicit operator ParameterData[](ParameterData value)
{
if (Object.ReferenceEquals(null, value))
throw new ArgumentNullException("value");
return value.NestedValues;
}
}
This seems to work properly, according to the values shown in the debugger at least.
I've tried to use them, in an attempt to see where recursive types can be useful, but I've run into a problem, a "simple" loop runs 2 times over the nested items, I can't figure out if it's due to bad object design or bad loop coding. Could you give me some insight?
The code:
[TestMethod()]
public void LoadingWindowTest()
{
ParameterData[] temp = new ParameterData[]{
new ParameterData {Values=new string[]{ "Titulo" } },
new ParameterData {Values=new string[]{ "Autor1" , "Autor2" } },
new ParameterData {NestedValues=new ParameterData[]{
new ParameterData {NestedValues=new ParameterData[]{
new ParameterData {Values = new string[]{"Hola"} },
new ParameterData {Values = new string[]{"Don", "Pepito"} }
} },
new ParameterData {Values = new string[]{"Outta Nest"} }
} },
new ParameterData {Values=new string[]{ "Last" } }
};
print(temp);
}
private void print(ParameterData[] data, int indent = 0)
{
for (int i = 0; i < data.Length; i++)
{
for (int x = 0; x < data[i].Length; x++)
{
if (data[i][x] is string) Console.WriteLine("" + indent + data[i][x]);
else print(data[i], indent + 1);
}
}
}
This is the output:
EDIT:
To clarify the issue: every line that starts with a value greater than 0 it's duplicated. Furthermore it's exponential, the lines are duplicated by 2^n where n it's the line's "level".
As Peter Duniho stated, my issue came from using 2 loops. The following code works as intended:
private void print(ParameterData[] data, int indent = 0)
{
for (int i = 0; i < data.Length; i++)
{
if (data[i].IsNested) print(data[i], indent + 1);
else
{
for (int x = 0; x < data[i].Length; x++) Console.WriteLine("" + indent + data[i][x]);
}
}
}
The source of my confusion was the fact that I implemented an indexer (for the sake of it) and that created the ilusion of working with a 2D array.
For anyone who might have a similar issue in the future:
Don't use indexers(or anything really) where it's not needed
An array of a type that contains an array of itself will be n-dimensional, no matter how it looks(this should be obvious, but here I am, having this issue).
I'm currently working on a project where I have to choose a file and then sort it along with other files. The files are just filled with numbers but each file has linked data. So the first number in a file is linked to the first number in the second file and so on. I Currently have code that allows me to read a file and display the file unsorted and sorted using the bubble sort. I am not sure how I would be able to apply this same principle to multiple files at once. So that I could choose a file and then sort it in line with the same method I have for a single file.
Currently, the program loads and asks the user to choose between 1 and 2. 1 Shows the code unsorted and 2 shows the code sorted. I can read in the files but the problem is sorting and displaying in order. Basically How do I sort multiple files that are linked together. What steps do I need to take to do this?
An example of one file:
4
28
77
96
An example of the second file:
66.698
74.58
2.54
48.657
Any help would be appreciated.
Thanks
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
public class Program
{
public Program()
{
}
public void ReadFile(int [] numbers)
{
string path = "Data1/Day_1.txt";
StreamReader sr = new StreamReader(path);
for (int index = 0; index < numbers.Length; index++)
{
numbers[index] = Convert.ToInt32(sr.ReadLine());
}
sr.Close(); // closes file when done
}
public void SortArray(int[] numbers)
{
bool swap;
int temp;
do
{
swap = false;
for (int index = 0; index < (numbers.Length - 1); index++)
{
if (numbers[index] > numbers[index + 1])
{
temp = numbers[index];
numbers[index] = numbers[index + 1];
numbers[index + 1] = temp;
swap = true;
}
}
} while (swap == true);
}
public void DisplayArray(int[] numbers)
{
for(int index = 0; index < numbers.Length; index++)
{
Console.WriteLine("{0}", numbers[index]);
}
}
}
The main is in another file to keep work organised:
using System;
public class FileDemoTest
{
public static void Main(string[] args)
{
int[] numbers = new int[300];
Program obj = new Program();
int operation = 0;
Console.WriteLine("1 or 2 ?");
operation = Convert.ToInt32(Console.ReadLine());
// call the read from file method
obj.ReadFile(numbers);
if (operation == 1)
{
//Display unsorted values
Console.Write("Unsorted:");
obj.DisplayArray(numbers);
}
if (operation == 2)
{
//sort numbers and display
obj.SortArray(numbers);
Console.Write("Sorted: ");
obj.DisplayArray(numbers);
}
}
}
What I would do is create a class that will hold the values from file 1 and file 2. Then you can populate a list of these classes by reading values from both files. After that, you can sort the list of classes on either field, and the relationships will be maintained (since the two values are stored in a single object).
Here's an example of the class that would hold the file data:
public class FileData
{
public int File1Value { get; set; }
public decimal File2Value { get; set; }
/// <summary>
/// Provides a friendly string representation of this object
/// </summary>
/// <returns>A string showing the File1 and File2 values</returns>
public override string ToString()
{
return $"{File1Value}: {File2Value}";
}
}
Then you can create a method that reads both files and creates and returns a list of these objects:
public static FileData[] GetFileData(string firstFilePath, string secondFilePath)
{
// These guys hold the strongly typed version of the string values in the files
int intHolder = 0;
decimal decHolder = 0;
// Get a list of ints from the first file
var fileOneValues = File
.ReadAllLines(firstFilePath)
.Where(line => int.TryParse(line, out intHolder))
.Select(v => intHolder)
.ToArray();
// Get a list of decimals from the second file
var fileTwoValues = File
.ReadAllLines(secondFilePath)
.Where(line => decimal.TryParse(line, out decHolder))
.Select(v => decHolder)
.ToArray();
// I guess the file lengths should match, but in case they don't,
// use the size of the smaller one so we have matches for all items
var numItems = Math.Min(fileOneValues.Count(), fileTwoValues.Count());
// Populate an array of new FileData objects
var fileData = new FileData[numItems];
for (var index = 0; index < numItems; index++)
{
fileData[index] = new FileData
{
File1Value = fileOneValues[index],
File2Value = fileTwoValues[index]
};
}
return fileData;
}
Now, we need to modify your sorting method to work on a FileData array instead of an int array. I also added an argument that, if set to false, will sort on the File2Data field instead of File1Data:
public static void SortArray(FileData[] fileData, bool sortOnFile1Data = true)
{
bool swap;
do
{
swap = false;
for (int index = 0; index < (fileData.Length - 1); index++)
{
bool comparison = sortOnFile1Data
? fileData[index].File1Value > fileData[index + 1].File1Value
: fileData[index].File2Value > fileData[index + 1].File2Value;
if (comparison)
{
var temp = fileData[index];
fileData[index] = fileData[index + 1];
fileData[index + 1] = temp;
swap = true;
}
}
} while (swap);
}
And finally, you can display the non-sorted and sorted lists of data. Note I added a second question to the user if they choose "Sorted" where they can decide if it should be sorted by File1 or File2:
private static void Main()
{
Console.WriteLine("1 or 2 ?");
int operation = Convert.ToInt32(Console.ReadLine());
var fileData = GetFileData(#"f:\public\temp\temp1.txt", #"f:\public\temp\temp2.txt");
if (operation == 1)
{
//Display unsorted values
Console.WriteLine("Unsorted:");
foreach (var data in fileData)
{
Console.WriteLine(data);
}
}
if (operation == 2)
{
Console.WriteLine("Sort on File1 or File2 (1 or 2)?");
operation = Convert.ToInt32(Console.ReadLine());
//sort numbers and display
SortArray(fileData, operation == 1);
Console.WriteLine("Sorted: ");
foreach (var data in fileData)
{
Console.WriteLine(data);
}
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
If you wanted to use an int to decide which field to sort on, you could do something like the following:
public static void SortArray(FileData[] fileData, int sortFileNumber = 1)
{
bool swap;
do
{
swap = false;
for (int index = 0; index < (fileData.Length - 1); index++)
{
bool comparison;
// Set our comparison to the field sortFileNumber
if (sortFileNumber == 1)
{
comparison = fileData[index].File1Value > fileData[index + 1].File1Value;
}
else if (sortFileNumber == 2)
{
comparison = fileData[index].File2Value > fileData[index + 1].File2Value;
}
else // File3Value becomes default for anything else
{
comparison = fileData[index].File3Value > fileData[index + 1].File3Value;
}
if (comparison)
{
var temp = fileData[index];
fileData[index] = fileData[index + 1];
fileData[index + 1] = temp;
swap = true;
}
}
} while (swap);
}
This is a bit of a doozy and it's been a while since I worked with C#, so bear with me:
I'm running a jruby script to iterate through 900 files (5 Mb - 1500 Mb in size) to figure out how many dupes STILL exist within these (already uniq'd) files. I had little luck with awk.
My latest idea was to insert them into a local MongoDB instance like so:
db.collection('hashes').update({ :_id => hash}, { $inc: { count: 1} }, { upsert: true)
... so that later I could just query it like db.collection.where({ count: { $gt: 1 } }) to get all the dupes.
This is working great except it's been over 24 hours and at the time of writing I'm at 72,532,927 Mongo entries and growing.
I think Ruby's .each_line is bottlnecking the IO hardcore:
So what I'm thinking now is compiling a C# program which fires up a thread PER EACH FILE and inserts the line (md5 hash) into a Redis list.
From there, I could have another compiled C# program simply pop the values off and ignore the save if the count is 1.
So the questions are:
Will using a compiled file reader and multithreading the file reads significantly improve performance?
Is using Redis even necessary? With a tremendous amount of AWS memory, could I not just use the threads to fill some sort of a list atomically and proceed from there?
Thanks in advance.
Updated
New solution. Old solution. The main idea is to calculate dummy hashes(just sum of all chars in string) of each line and store it in Dictionary<ulong, List<LinePosition>> _hash2LinePositions. It's possible to have multiple hashes in the same stream and it solves by List in Dictionary Value. When the hashes are the same, we read and compare the strings from the streams. LinePosition is using for storing info about line - position in stream and its length. I don't have such huge files as you, but my tests shows that it works. Here is the full code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class Solution
{
struct LinePosition
{
public long Start;
public long Length;
public LinePosition(long start, long count)
{
Start = start;
Length = count;
}
public override string ToString()
{
return string.Format("Start: {0}, Length: {1}", Start, Length);
}
}
class TextFileHasher : IDisposable
{
readonly Dictionary<ulong, List<LinePosition>> _hash2LinePositions;
readonly Stream _stream;
bool _isDisposed;
public HashSet<ulong> Hashes { get; private set; }
public string Name { get; private set; }
public TextFileHasher(string name, Stream stream)
{
Name = name;
_stream = stream;
_hash2LinePositions = new Dictionary<ulong, List<LinePosition>>();
Hashes = new HashSet<ulong>();
}
public override string ToString()
{
return Name;
}
public void CalculateFileHash()
{
int readByte = -1;
ulong dummyLineHash = 0;
// Line start position in file
long startPosition = 0;
while ((readByte = _stream.ReadByte()) != -1) {
// Read until new line
if (readByte == '\r' || readByte == '\n') {
// If there was data
if (dummyLineHash != 0) {
// Add line hash and line position to the dict
AddToDictAndHash(dummyLineHash, startPosition, _stream.Position - 1 - startPosition);
// Reset line hash
dummyLineHash = 0;
}
}
else {
// Was it new line ?
if (dummyLineHash == 0)
startPosition = _stream.Position - 1;
// Calculate dummy hash
dummyLineHash += (uint)readByte;
}
}
if (dummyLineHash != 0) {
// Add line hash and line position to the dict
AddToDictAndHash(dummyLineHash, startPosition, _stream.Position - startPosition);
// Reset line hash
dummyLineHash = 0;
}
}
public List<LinePosition> GetLinePositions(ulong hash)
{
return _hash2LinePositions[hash];
}
public List<string> GetDuplicates()
{
List<string> duplicates = new List<string>();
foreach (var key in _hash2LinePositions.Keys) {
List<LinePosition> linesPos = _hash2LinePositions[key];
if (linesPos.Count > 1) {
duplicates.AddRange(FindExactDuplicates(linesPos));
}
}
return duplicates;
}
public void Dispose()
{
if (_isDisposed)
return;
_stream.Dispose();
_isDisposed = true;
}
private void AddToDictAndHash(ulong hash, long start, long count)
{
List<LinePosition> linesPosition;
if (!_hash2LinePositions.TryGetValue(hash, out linesPosition)) {
linesPosition = new List<LinePosition>() { new LinePosition(start, count) };
_hash2LinePositions.Add(hash, linesPosition);
}
else {
linesPosition.Add(new LinePosition(start, count));
}
Hashes.Add(hash);
}
public byte[] GetLineAsByteArray(LinePosition prevPos)
{
long len = prevPos.Length;
byte[] lineBytes = new byte[len];
_stream.Seek(prevPos.Start, SeekOrigin.Begin);
_stream.Read(lineBytes, 0, (int)len);
return lineBytes;
}
private List<string> FindExactDuplicates(List<LinePosition> linesPos)
{
List<string> duplicates = new List<string>();
linesPos.Sort((x, y) => x.Length.CompareTo(y.Length));
LinePosition prevPos = linesPos[0];
for (int i = 1; i < linesPos.Count; i++) {
if (prevPos.Length == linesPos[i].Length) {
var prevLineArray = GetLineAsByteArray(prevPos);
var thisLineArray = GetLineAsByteArray(linesPos[i]);
if (prevLineArray.SequenceEqual(thisLineArray)) {
var line = System.Text.Encoding.Default.GetString(prevLineArray);
duplicates.Add(line);
}
#if false
string prevLine = System.Text.Encoding.Default.GetString(prevLineArray);
string thisLine = System.Text.Encoding.Default.GetString(thisLineArray);
Console.WriteLine("PrevLine: {0}\r\nThisLine: {1}", prevLine, thisLine);
StringBuilder sb = new StringBuilder();
sb.Append(prevPos);
sb.Append(" is '");
sb.Append(prevLine);
sb.Append("'. ");
sb.AppendLine();
sb.Append(linesPos[i]);
sb.Append(" is '");
sb.Append(thisLine);
sb.AppendLine("'. ");
sb.Append("Equals => ");
sb.Append(prevLine.CompareTo(thisLine) == 0);
Console.WriteLine(sb.ToString());
#endif
}
else {
prevPos = linesPos[i];
}
}
return duplicates;
}
}
public static void Main(String[] args)
{
List<TextFileHasher> textFileHashers = new List<TextFileHasher>();
string text1 = "abc\r\ncba\r\nabc";
TextFileHasher tfh1 = new TextFileHasher("Text1", new MemoryStream(System.Text.Encoding.Default.GetBytes(text1)));
tfh1.CalculateFileHash();
textFileHashers.Add(tfh1);
string text2 = "def\r\ncba\r\nwet";
TextFileHasher tfh2 = new TextFileHasher("Text2", new MemoryStream(System.Text.Encoding.Default.GetBytes(text2)));
tfh2.CalculateFileHash();
textFileHashers.Add(tfh2);
string text3 = "def\r\nbla\r\nwat";
TextFileHasher tfh3 = new TextFileHasher("Text3", new MemoryStream(System.Text.Encoding.Default.GetBytes(text3)));
tfh3.CalculateFileHash();
textFileHashers.Add(tfh3);
List<string> totalDuplicates = new List<string>();
Dictionary<ulong, Dictionary<TextFileHasher, List<LinePosition>>> totalHashes = new Dictionary<ulong, Dictionary<TextFileHasher, List<LinePosition>>>();
textFileHashers.ForEach(tfh => {
foreach(var dummyHash in tfh.Hashes) {
Dictionary<TextFileHasher, List<LinePosition>> tfh2LinePositions = null;
if (!totalHashes.TryGetValue(dummyHash, out tfh2LinePositions))
totalHashes[dummyHash] = new Dictionary<TextFileHasher, List<LinePosition>>() { { tfh, tfh.GetLinePositions(dummyHash) } };
else {
List<LinePosition> linePositions = null;
if (!tfh2LinePositions.TryGetValue(tfh, out linePositions))
tfh2LinePositions[tfh] = tfh.GetLinePositions(dummyHash);
else
linePositions.AddRange(tfh.GetLinePositions(dummyHash));
}
}
});
HashSet<TextFileHasher> alreadyGotDuplicates = new HashSet<TextFileHasher>();
foreach(var hash in totalHashes.Keys) {
var tfh2LinePositions = totalHashes[hash];
var tfh = tfh2LinePositions.Keys.FirstOrDefault();
// Get duplicates in the TextFileHasher itself
if (tfh != null && !alreadyGotDuplicates.Contains(tfh)) {
totalDuplicates.AddRange(tfh.GetDuplicates());
alreadyGotDuplicates.Add(tfh);
}
if (tfh2LinePositions.Count <= 1) {
continue;
}
// Algo to get duplicates in more than 1 TextFileHashers
var tfhs = tfh2LinePositions.Keys.ToArray();
for (int i = 0; i < tfhs.Length; i++) {
var tfh1Positions = tfhs[i].GetLinePositions(hash);
for (int j = i + 1; j < tfhs.Length; j++) {
var tfh2Positions = tfhs[j].GetLinePositions(hash);
for (int k = 0; k < tfh1Positions.Count; k++) {
var tfh1Pos = tfh1Positions[k];
var tfh1ByteArray = tfhs[i].GetLineAsByteArray(tfh1Pos);
for (int m = 0; m < tfh2Positions.Count; m++) {
var tfh2Pos = tfh2Positions[m];
if (tfh1Pos.Length != tfh2Pos.Length)
continue;
var tfh2ByteArray = tfhs[j].GetLineAsByteArray(tfh2Pos);
if (tfh1ByteArray.SequenceEqual(tfh2ByteArray)) {
var line = System.Text.Encoding.Default.GetString(tfh1ByteArray);
totalDuplicates.Add(line);
}
}
}
}
}
}
Console.WriteLine();
if (totalDuplicates.Count > 0) {
Console.WriteLine("Total number of duplicates: {0}", totalDuplicates.Count);
Console.WriteLine("#######################");
totalDuplicates.ForEach(x => Console.WriteLine("{0}", x));
Console.WriteLine("#######################");
}
// Free resources
foreach (var tfh in textFileHashers)
tfh.Dispose();
}
}
If you have tons of ram... You guys are overthinking it...
var fileLines = File.ReadAllLines(#"c:\file.csv").Distinct();
I'm having a strange issue while using the MLApp.GetWorkspaceData function. I noticed that this functions works properly when I do the following:
matlab = new MLApp.MLAppClass();
object myObject;
matlab.GetWorkspaceData("myVariable", "base", out myObject);
But if I then try to use the same object as an output I get an "Invalid Callee" exception. In addition this also gives the same error:
matlab = new MLApp.MLAppClass();
object myObject = new object();
matlab.GetWorkspaceData("myVariable", "base", out myObject);
This is very troublesome because I need to get a large amount of data from Matlab to Visual Studio, and I cannot practically create 52K uninitialized variables and keep them around. Is there some way to "uninitialize" a variable? Is there some concept I'm missing here?
As #wonko79 explained in the comments, if you want to reuse the out variable, you should set it to null first.
Here is a tested example calling MATLAB from C#:
using System;
namespace CSharp_matlab_com
{
class Program
{
static void Main(string[] args)
{
MLApp.MLAppClass matlab = new MLApp.MLAppClass();
// create variables: a_0, a_1, ..., a_4
for (int k = 0; k < 5; k++) {
matlab.Execute(string.Format("a_{0} = rand(2);", k));
}
// retrieve variables from MATLAB and print their contents
object a;
for (int k = 0; k < 5; k++) {
// current variable name
string varname = string.Format("a_{0}", k);
// get data array
a = null; // without this line, an exception is thrown!
matlab.GetWorkspaceData(varname, "base", out a);
// print contents
var arr = (double[,]) a;
Console.WriteLine("\nndims(a) = {0}, numel(a) = {1}", arr.Rank, arr.Length);
for (int i = 0; i < arr.GetLength(0); i++) {
for (int j = 0; j < arr.GetLength(1); j++) {
Console.WriteLine("{0}[{1},{2}] = {3}", varname, i, j, arr[i,j]);
}
}
}
}
}
}
The output:
ndims(a) = 2, numel(a) = 4
a_0[0,0] = 0.251806122472313
a_0[0,1] = 0.617090884393223
a_0[1,0] = 0.290440664276979
a_0[1,1] = 0.265280909810029
...
ndims(a) = 2, numel(a) = 4
a_4[0,0] = 0.425259320214135
a_4[0,1] = 0.16148474431175
a_4[1,0] = 0.312718886820616
a_4[1,1] = 0.178766186752368
You can create a wrapper for GetWorkspaceData method, like in the next example:
public object GetData(string name)
{
object data;
mlApp.GetWorkspaceData(name, "base", out data);
return data;
}
Or, even more useful, a generic wrapper:
public T GetData<T>(string name)
{
object data;
mlApp.GetWorkspaceData(name, "base", out data);
if (data == null)
return default(T);
if (data is T)
return (T)data;
else
throw new InvalidCastException($"The variable '{name}', of type '{data.GetType().Name}' cannot be casted to type '{typeof(T).Name}'.");
}
The solution is to set the output object to null.
I found it here.
I'm learning C and C# and this question is for C#. I looking at pointers at msdn and this code is not compiling, it gives the error:Error 1 Cannot implicitly convert type int** to int*. An explicit conversion exists (are you missing a cast?). What am I missing here?
Here is the code:
int ix = 10;
unsafe
{
int* px1;
int* px2 = &ix; **The error is on this line**
}
EDIT:
Here is the program in its entirety:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.Diagnostics;
using System.Windows.Forms;
using practice;
class Program
{
public delegate bool ThisIsTheDelegate(int number);
public delegate bool ThisIsAnotherDelegate(int number);
private static string address;
public static String Address
{
get
{
return address;
}
set
{
address = value;
}
}
static void Main()
{
int[] someArray = new int[] { 1, 2, 3, 5, 6, 7, 8, 9, 0 };
foreach (int number in someArray)
{
Console.WriteLine(number);
}
int integer = 98;
string someString = "edited";
string[] someStr = { "edited" };
String[] anotherStringSomestr = new String[] { "edited" };
var readWithLinq = from far in anotherStringSomestr
select far;
foreach (var some in readWithLinq)
{
Console.WriteLine(some);
}
Program newPro = new Program();
bool isEven1 = newPro.isEven(99);
Console.WriteLine(isEven1);
ThisIsTheDelegate newDelegate = newPro.isEven;
Console.WriteLine(newDelegate(98));
int[] numbers = { 1, 2, 3, 5, 6, 7, 8, 9 };
List<int> evenNumbers = FilterArray(numbers, newDelegate);
foreach(int integer1 in evenNumbers)
{
Console.WriteLine(integer1);
}
List<int> oddNumbers = FilterArray(numbers, isOdd);
foreach (int integer1 in oddNumbers)
{
Console.WriteLine(integer1);
}
ThisIsAnotherDelegate anotherDelegate;
anotherDelegate = number => (number % 2 == 0);
Console.WriteLine("{0} is a even number", anotherDelegate(4));
for (int i = 0; i < someString.Length; i++)
{
Console.WriteLine(someString);
}
for (int i = 0; i < someStr.Length; i++)
{
Console.WriteLine(someStr[i]);
}
Console.WriteLine(integer);
SimpleStruct structss = new SimpleStruct();
structss.DisplayX();
M.x = 1;
structss.x = 98;
Console.WriteLine(M.x);
Console.WriteLine(structss.x);
M.structtaker(ref structss);
M.classtaker();
Console.WriteLine(structss.x);
Console.WriteLine(M.x);
M.x = 1;
structss.x = 98;
int ix = 10;
unsafe
{
int* px1;
int* px2 = &ix;
}
int selection = 98;
while (selection != 0)
{
mainMenu();
Console.Write("Enter choice: ");
selection = Convert.ToInt32(Console.ReadLine());
switch (selection)
{
case 0:
break;
case 1:
openSomething();
break;
case 2:
calculator();
break;
case 3:
coolestProgramEverALive();
break;
case 4:
make_to_do_list();
break;
case 5:
add_to_do_list();
break;
case 6:
readToDoList();
break;
case 7:
linq_and_arrays();
break;
case 8:
calendar();
break;
case 9:
linq_and_collections();
break;
default:
Console.WriteLine("Unkown selection. Try again");
break;
}
}
}
private static bool isOdd(int number)
{
return (number % 2 == 1);
}
private static List<int> FilterArray(int[] numbers, ThisIsTheDelegate newDelegate)
{
List<int> result = new List<int>();
foreach (int item in numbers)
{
if (newDelegate(item))
result.Add(item);
}
return result;
}
private static void linq_and_collections()
{
List<string> names = new List<string>();
names.Add("Billy");
names.Add("Steve");
names.Add("Casandra");
names.Insert(0, "Johanna");
names.Add("Sonny");
names.Add("Suzanne");
names.Insert(2, "Sid");
var queryLinqUpper = from name in names
where (name.StartsWith("S") || name.StartsWith("B") || name.StartsWith("J"))
let namesToUpper = name.ToUpper()
orderby namesToUpper
select namesToUpper;
foreach (var linqToUpper in queryLinqUpper)
{
Console.Write(linqToUpper + " ");
}
Console.WriteLine();
M.WriteTextToConsole("Hello, world. Programming in C# is fun");
char c = 'A';
int count = 14;
String str = new String(c, count);
str.WriteTextToConsole();
M.WriteTextToConsole(str);
}
private static void calendar()
{
Application.Run(new Form1());
}
private static void readToDoList()
{
var files = from file in Directory.GetFiles(#"C:\data", "*.txt")
select file;
int number = 1;
foreach (var file in files)
{
Console.WriteLine(number + ". " + file);
number++;
}
Console.Write("What todolist do you want to read? Give me the name:");
try
{
string name = Console.ReadLine();
Address = Path.Combine(#"C:\data", name + ".txt");
TextReader inFile = new StreamReader(Address);
while (inFile.Peek() != -1)
{
string line = inFile.ReadLine();
Console.WriteLine(line);
}
inFile.Close();
}
catch (Exception ex)
{
MessageBox.Show("Exception thrown!", "Error");
Console.WriteLine(ex.ToString());
}
}
private static void linq_and_arrays()
{
int numberOfElements;
Console.WriteLine("Start by setting the int[] array.");
Console.Write("How many elements are there in your array?");
numberOfElements = Convert.ToInt32(Console.ReadLine());
int[] array = new int[numberOfElements];
for (int i = 0, j = numberOfElements; i < numberOfElements; i++, j--)
{
Console.Write("Integers left to add {0}. Enter an integer:", j);
array[i] = Convert.ToInt32(Console.ReadLine());
}
var arrayquery = from value in array
select value;
foreach (var val in arrayquery)
{
Console.WriteLine("Value from array:{0}", val);
}
}
private static void add_to_do_list()
{
Console.WriteLine("Which todolist do you want to modify?");
listToDoLists();
Console.Write("Enter name of todolist: ");
string name = Console.ReadLine();
Address = Path.Combine(#"C:\data", name + ".txt");
String tempString;
StreamWriter stream;
stream = File.AppendText(Address);
Console.Write("Enter your new ToDo: ");
tempString = Console.ReadLine();
stream.WriteLine(tempString);
stream.Close();
TextReader inFile;
inFile = new StreamReader(Address);
while (inFile.Peek() != -1)
{
string line = inFile.ReadLine();
Console.WriteLine(line);
}
inFile.Close();
}
private static void listToDoLists()
{
int filenumber = 1;
string[] filepaths = Directory.GetFiles("C:\\data\\", "*.txt");
foreach (string file in filepaths)
{
Console.WriteLine(filenumber + ". " + file);
filenumber++;
}
}
private static void make_to_do_list()
{
string path, name;
string yesOrNo;
Console.Write("Enter name of todolist: ");
name = Console.ReadLine();
path = Path.Combine(#"C:\data", name + ".txt");
TextWriter outFile = new StreamWriter(path);
labelOne: // else clause : unknown answer
Console.WriteLine("Do you want to add something to todolist.Y/N?");
yesOrNo = Console.ReadLine();
if (yesOrNo.ToLower() == "y")
{
string line;
int lines;
Console.Write("How many lines?");
lines = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < lines; i++)
{
Console.Write("Enter a line of text: ");
line = Console.ReadLine();
outFile.WriteLine(line);
}
outFile.Close();
}
else if (yesOrNo.ToLower() == "n")
{
Console.WriteLine("You can close the application now.");
}
else
{
Console.WriteLine("Unknown answer. Try again");
goto labelOne;
}
}
private static void coolestProgramEverALive()
{
System.Diagnostics.Process.Start(#"C:\Users\KristjanBEstur\Documents\Visual Studio 2012\Projects\The_coolest_program_ever_alive\The_coolest_program_ever_alive\obj\Debug\The_coolest_program_ever_alive.exe");
}
private static void calculator()
{
System.Diagnostics.Process.Start("calc");
}
private static void openSomething()
{
System.Diagnostics.Process.Start("notepad");
}
private static void mainMenu()
{
Console.WriteLine("Main Menu");
Console.WriteLine("0. Quit");
Console.WriteLine("1. OpenSomething");
Console.WriteLine("2. Calculator");
Console.WriteLine("3. coolestProgramEverAlive");
Console.WriteLine("4. Make todolist");
Console.WriteLine("5. Add to todolist");
Console.WriteLine("6. Read to do list");
Console.WriteLine("7. Linq and arrays");
Console.WriteLine("8. Calendar");
Console.WriteLine("9. Linq and collections");
}
public bool isEven(int number)
{
return (number % 2 == 0);
}
}
static class M
{
public static int x;
public static void WriteTextToConsole(this string text)
{
Console.WriteLine(text);
}
public static void structtaker(ref SimpleStruct s)
{
s.x = 5;
}
public static void classtaker()
{
M.x = 5;
}
}
class Test
{
static int value = 20;
unsafe static void F(out int* pi1, ref int* pi2) {
int i = 10;
pi1 = &i;
fixed (int* pj = &value) {
// ...
pi2 = pj;
}
}
}
struct SimpleStruct
{
public int x;
private int xval;
public int X
{
get
{
return xval;
}
set
{
if (value < 100)
xval = value;
}
}
public void DisplayX()
{
Console.WriteLine("The stored value is: {0}", X);
}
}
I wished I could replicate this it seems like a rather interesting issue. Here is the section of the standard that I believe applies to this (sorry about the formatting):
18.3 Fixed and moveable variables The address-of operator (§18.5.4) and the fixed statement (§18.6) divide variables into two categories:
Fixed variables and moveable variables. Fixed variables reside in
storage locations that are unaffected by operation of the garbage
collector. (Examples of fixed variables include local variables, value
parameters, and variables created by dereferencing pointers.) On the
other hand, moveable variables reside in storage locations that are
subject to relocation or disposal by the garbage collector. (Examples
of moveable variables include fields in objects and elements of
arrays.) The & operator (§18.5.4) permits the address of a fixed
variable to be obtained without restrictions. However, because a
moveable variable is subject to relocation or disposal by the garbage
collector, the address of a moveable variable can only be obtained
using a fixed statement (§18.6), and that address remains valid only
for the duration of that fixed statement. In precise terms, a fixed
variable is one of the following: • A variable resulting from a
simple-name (§7.6.2) that refers to a local variable or a value
parameter, unless the variable is captured by an anonymous function.
• A variable resulting from a member-access (§7.6.4) of the form V.I,
where V is a fixed variable of a struct-type. • A variable resulting
from a pointer-indirection-expression (§18.5.1) of the form *P, a
pointer-member-access (§18.5.2) of the form P->I, or a
pointer-element-access (§18.5.3) of the form P[E]. All other variables
are classified as moveable variables. Note that a static field is
classified as a moveable variable. Also note that a ref or out
parameter is classified as a moveable variable, even if the argument
given for the parameter is a fixed variable. Finally, note that a
variable produced by dereferencing a pointer is always classified as a
fixed variable.
I spend some time trying to create a similar error but wasn't about to. The only way I was able to recreate the issue was with the following code:
void test() {
int ix = 10;
unsafe {
int* px1 = &ix;
int* px2 = &px1; // **The error is on this line**
}
}
Of course this code cannot be fixed by moving the ix declaration into the safe scope. Perhaps you could try replicating the original problem in a very small bit of code (like above) and verify that both the problem and the fix replicate. Perhaps VS became confused. I have had problems that made no sense and went away by exiting VS and restarting (not often but a few times).
I moved the i declaration down inside the unsafe block and it fixed it, I don't know why?
Here is the code:
unsafe
{
int ix = 10;
int* px1;
int* px2 = &ix;
}
I've moved the expression "int i = 10;" out of the unsafe block and now it compiles. I've also put the code in question in a new project of another instance of vs2012pro. And that also compiles. So now I'm unable to replicate the error.
Here is the code:
int ix = 10;
unsafe
{
int* px1;
int* px2 = &ix;
Test.F(out px1, ref px2);
Console.WriteLine("*px1 = {0}, *px2 = {1}",
*px1, *px2); // undefined behavior
}
Here is the other project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace saxerium
{
class Program
{
static void Main(string[] args)
{
int ix = 10;
unsafe
{
int* px1;
int* px2 = &ix;
Test.F(out px1, ref px2);
Console.WriteLine("*px1 = {0}, *px2 = {1}",
*px1, *px2); // undefined behavior
}
}
}
class Test
{
static int value = 20;
public unsafe static void F(out int* pi1, ref int* pi2)
{
int i = 10;
pi1 = &i;
fixed (int* pj = &value)
{
// ...
pi2 = pj;
}
}
}
}