I output something to a array written in c , then I hope to get the information from c# calling via dll, but failed. No warnnings but I can note get the informaton correctly. Test code as follow :
#ips store the output information
UDPDLL_API int get_by_csharp_tst(char *** ips){
char **ip = NULL;
int i = 0;
*ips = (char**)malloc(sizeof(char*)*10);
if(ips == NULL){
perror("overflow");
}
ip = *ips;
for(i =0 ; i <10 ; i++){
*ip = (char*)malloc(16);
memcpy(*ip,"255.255.255.255",16);
*ip++;
}
return 0;
}
calling from c# as follow :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace dll_call
{
class Program
{
[DllImport("udpdll.dll",EntryPoint="get_by_csharp_tst")]
public static extern int get_by_csharp_tst(byte [,] ai);
static void Main(string[] args)
{
int i = 0;
byte[,] ips = new byte[10, 16];
Program.get_by_csharp_tst(ips);
for (i = 0; i < 10; i++) {
Console.WriteLine(ips);
}
Console.Read();
}
}
}
Thank you again. Any help would be greatly appreciated !
This is a horrible API.
For starters, never allocate memory on the native side, if you cannot free it there too.
But if you have to, then read on.
Change the signature to public static extern int get_by_csharp_tst(out IntPtr[] ai);
Call it like:
IntPtr[] ai; // do not allocate, you are doing it on the native side already
get_by_csharp_tst(out ai);
// as we know the size, just use it
string[] results = new string[10];
for (int i = 0; i < 10; i++)
{
results[i] = Marshal.PtrToStringAnsi(ai[i], 16);
}
// you need to free the memory you allocated natively here, else memory leak.
foreach (var s in results)
{
Console.WriteLine(s);
}
Note: It will be potluck even when specifying the length (16) as you never clear the allocated memory and there is no guarantee the last element will be \0.
Related
NOTE: I have figured out that this only affects .NET fiddle if you are using .NET 6. If you aren't using .NET 6 it works fine.
Whenever I use the Console.WriteLine() function on .NET fiddle, it doesn't let me interact with the console. I'm new at coding and .NET fiddle, so it might be a simple fix. I just hope you can figure it out
I've tried just having the Console.WriteLine. I've triple checked I wrote it right. I rewrote the Convert.ToInt32 several times. I looked up to see if anyone else had this problem. I even checked if Console.WriteLine being under the list maker was the problem, it wasn't.
Here is the code:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<string> shoppingList = new List<string>();
Console.WriteLine("How many items on the list?");
int listLength = Convert.ToInt32( Console.ReadLine() );
for(var i = 0; i < 4; i++) {
shoppingList.Add(Console.ReadLine());
}
for(var i = 0; i < shoppingList.Count; i++) {
Console.WriteLine(shoppingList[i]);
}
}
}
It's working fine here on my side, as you can see here. Have you tried cleaning the cookies of your browser? Note that you have to click on the console to type. Also, I fixed your function where it gives the correct size of the List<string>.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<string> shoppingList = new List<string>();
Console.WriteLine("How many items on the list?");
int listLength = Convert.ToInt32( Console.ReadLine() );
for(var i = 0; i < listLength; i++) {
shoppingList.Add(Console.ReadLine());
}
for(var i = 0; i < shoppingList.Count; i++) {
Console.WriteLine(shoppingList[i]);
}
}
}
I was trying to make a lucky dip program where 6 random numbers,1-59, are chosen then printed out in an array. I managed to get this to work, however you needed to use an IndexOf method so that no same number was printed twice by checking if the new number is already in the array.
using System;
namespace LuckyDip
{
class Program
{
static void Main(string[] args)
{
int[] luckyNumbers = new int[6];
Random random = new Random();
for (int x = 0; x<6; x++)
{
num[x] = random.Next(1,59);
Console.WriteLine(num[x]);
}
Console.ReadLine();
}
}
}
It prints out numbers, but sometimes they are the same.
You state that you want to use IndexOf, but that method is used for strings (see docs). Your example has an int array so the solution below uses Contains. This solution adds a check within your loop and generates a new number if this number already exists within your array. If you really need to use IndexOf, create a string array and convert the numbers using String.valueOf(randomNumber)
using System;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
int[] luckyNumbers = new int[6];
Random random = new Random();
for (int x = 0; x<6; x++)
{
int randomNumber = random.Next(1,59);
while (luckyNumbers.Contains(randomNumber))
{
randomNumber = random.Next(1,59);
}
luckyNumbers[x] = randomNumber;
Console.WriteLine(luckyNumbers[x]);
}
}
}
Another possible solution would be:
using System;
using System.Collections;
using System.Linq;
public class Program
{
public static void Main()
{
int arraySize = 6;
int[] luckyNumbers = Enumerable.Range(1,59).OrderBy(g => Guid.NewGuid()).Take(arraySize).ToArray();
for (int x = 0; x < luckyNumbers.Length; x++)
{
Console.WriteLine(luckyNumbers[x]);
}
}
}
I attempting to create a program that uses multiple methods that would print out base numbers, exponents, and their resulting solutions. I am trying to get it to run and it's nearly completed, but I am encountering a couple issues. The code itself seems to run, but doesn't appear to print out on Visual Studio. I did run it on an online compiler and got this as an output:
It seems I am missing something in my code, but I am unclear as to what I may be missing. This is the code I have created for the project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Project
{
class Program
{
static void Main(string[] args)
{
//Our initialized variables.
int intMinBase = 1;
int intMaxBase = 100;
int intMinExpo = 1;
int intMaxExpo = 10;
//Our arrays for the project, all at a length of 5.
long[] baseNumbers = new long[5];
long[] exponents = new long[5];
long[] results = new long[5];
//Randomize the baseNumbers and exponents!
Random randInt = new Random();
for (long i = 0; i < 5; i++)
{
baseNumbers[i] = randInt.Next(intMinBase, intMaxBase);
exponents[i] = randInt.Next(intMinExpo, intMaxExpo);
}
PrintArrays(baseNumbers, exponents, results);
}
//This is potentially experimental code for the Power Method.
public static int Power(int baseNum, int exponent)
{
int answer;
if (exponent == 1)
{
answer = 1;
}
else
{
answer = baseNum * Power(baseNum, exponent - 1);
}
return answer;
}
//The new method to be printed. Is this the correct manner to display this?
public static void PrintArrays(long[] baseNum, long[] exponent, long[] result)
{
Console.WriteLine($"Base\tExponent\tResult");
for (int print = 0; print < result.GetUpperBound(0); print++)
{
Console.WriteLine(baseNum[print]+"\t"+exponent[print]+"\t"+result[print]);
}
}
}
}
My question is mainly am I missing something and why isn't it appearing to print in Visual Studio yet it's appearing on an online compiler? I suspect the answer to the first part of the question has to do with the methods I used, but I am unsure.
First error: Nowhere is the method Power called and nowhere is the array results filled.
Solution example:
for (long i = 0; i < 5; i++)
{
baseNumbers[i] = randInt.Next(intMinBase, intMaxBase);
exponents[i] = randInt.Next(intMinExpo, intMaxExpo);
results[i] = Power(baseNumbers[i], exponents[i]);
}
Can't find why code below with commented Monitor works like synchronized while writing to to g and always returns g=50. I was expecting some discrepancy an result less than 50.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace _7_monitor
{
class Program
{
static object sync = new object();
static int g = 0;
static Barrier b = new Barrier(6, (b) => { Console.WriteLine("barier reached"); } );
public static void tjob(object obj)
{
int t = (int)obj;
for (int i = 0; i < 10; i++)
{
//Monitor.Enter(sync);
g = g + 1;
//Monitor.Exit(sync);
Console.WriteLine("thr {0} iter={1}", t , i);
}
b.SignalAndWait();
}
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Thread d = new Thread(tjob);
d.Start(i);
}
Console.WriteLine("waiting");
b.SignalAndWait();
Console.WriteLine("g={0}",g);
Console.ReadLine();
}
}
}
As others have pointed out, a loop of 10 will complete so quickly that there's a good chance that the other threads haven't even started yet, so you've likely got sequential access to the global static variable g, in any event, hence the apparantly observed consistent result.
With a longer loop (I've taken some of the fluff out) with no protection around g, we do get something resembling a random number generator.
var threads = new List<Thread>();
for (var i = 0; i < 5; i++)
{
var d = new Thread(x => {
for (var loop = 0; loop < 100000; loop++)
{
// unsynchronized mutation
g = g + 1;
}
});
d.Start(i);
threads.Add(d);
}
foreach (var t in threads)
{
t.Join();
}
Console.WriteLine("g={0}", g); // 158609, 173331, 127983, ... (i7 with 4 HT Cores)
As per #Jurgis' comment, instead of a Monitor or lock, Interlocked.Increment has been provided to .Net
Replacing g = g + 1 with Interlocked.Increment(ref g); returns the expected:
g=500000
(and obviously, in the real world, there would be absolutely no point in parallelizing work which would just contend for a shared variable)
Once I run the following local, it is woking fast, but when I submit it to Kattis, It only exceeds 2/5 and I get Time Limit Exceeded.
Any suggestion?
I have tried with a input file with 10000 numbers and it is still fast localy :S
using System;
namespace phonelist
{
class Program
{
static void Main(string[] args)
{
int nrOfPhoneNrs = 0;
bool consistent;
int nrOfTestCases = Convert.ToInt32(Console.ReadLine().Trim());
for (byte i = 0; i < nrOfTestCases; i++)
{
consistent = false;
nrOfPhoneNrs = Convert.ToInt32(Console.ReadLine().Trim());
string[] phList = new string[nrOfPhoneNrs];
int n = 0;
while (n < nrOfPhoneNrs)
{
phList[n] = Console.ReadLine();
n++;
}
Array.Sort(phList);
int runs = nrOfPhoneNrs - 1;
for (int p = 0; p < runs; p++)
{
if (phList[p + 1].StartsWith(phList[p]))
{
consistent= true;
break;
}
}
Console.WriteLine(consistent? "NO" : "YES");
}
}
}
}
I think that your main problem is that you're using StartsWith and Array.Sort methods.
I don't want to give you too detailed advice (so that you can still solve it by yourself) but let me just suggest considering a different data structure than an array of strings, perhaps HashSet<string>.