say i have the following two struct definitions in C.
struct child {
int x;
};
struct Yoyo {
struct child **Kids;
};
How would i go about allocating the memory for Kids.
say for example i have some function Yoyo_create().
static struct Yoyo * yoyo_create() {
int n = 32000;
struct Yoyo *y;
y = malloc(sizeof( *Yoyo));
y->Kids = malloc(n*sizeof(*Child));
for (i = 0 ; i < n ; i ++) { y->Kids[i] = NULL; }
}
and then to destroy the Kids in some "destructor function" i would do.
void yoyo_destroy(struct yoyo *y)
{
free(y->Kids);
free(y);
}
Does that make sense?
you don't need these lines
y->Kids = malloc(n*sizeof(*Child)); and <br>
free(y->Kids);
because your y contains kids structure in it. And except these , you are going well
y = malloc(sizeof(struct Yoyo));
y->Kids = malloc(n*sizeof(struct Child));
Related
I'm trying to understand Rust' memory mechanism, especially how it works when you need it to interoperate with C code.
Here I have small C code represents a linked list and a function prints its attr to stdout:
// this is wrapper.h
typedef struct elem {
int attr;
struct elem *next;
} elem;
typedef struct wrapper {
char name[16];
struct elem *first_elem;
} wrapper;
void print_all_attrs(wrapper *w);
// -----
// and this is how wrapper.c looks like:
#include <stdio.h>
#include "wrapper.h"
void print_all_attrs(wrapper *w) {
printf("NAME = %s\n", w->name);
elem *elem = w->first_elem;
while(elem != NULL) {
printf("ATTR = %d\n", elem->attr);
elem = elem->next;
}
}
We all know how to prepare a wrapper that can hold a linkedlist of elem which is created dynamically: we need to create a wrapper variable, then a logic allocates an area in heap for every elem, assigns the first one into wrapper->first_elem and then others to previous' next pointer. here the code does exactly same thing:
void main() {
wrapper w = {
.name = "ABCD",
};
elem *prev = NULL;
for(int i=0; i<10; i++) {
elem *new = malloc(sizeof(elem));
new->attr = i;
if(w.first_elem == NULL) {
w.first_elem = new;
prev = new;
continue;
}
prev->next = new;
prev = prev->next;
}
print_all_attrs(&w);
// CLEARING HEAP STUFF HERE...
}
So, in Rust, I'm trying to use those definitions by generating code bindgen and cc libraries, I'm skipping these details right now.
If I want to allocate something into heap, I know I can use Box but it doesn't work at all because it drops when it goes out scope. take a look below code that exits with segmentation fault:
unsafe {
let mut prev: *mut xxx::elem = w.first_elem;
for n in 0..10 {
let mut elem = Box::new(xxx::elem {
attr: n,
next: ptr::null_mut(),
});
if w.first_elem.is_null() {
w.first_elem = &mut *elem;
prev = &mut *elem;
continue;
}
(*prev).next = &mut *elem;
prev = (*prev).next;
}
xxx::print_all_attrs(&mut w);
}
I managed to use Layout and alloc, but these guys bring a cost that I need to dealloc the things after use:
unsafe {
use std::alloc::{Layout, alloc};
let mut prev: *mut xxx::elem = w.first_elem;
for n in 0..10 {
let layout = Layout::new::<xxx::elem>();
let mut p = alloc(layout) as *mut xxx::elem;
(*p).attr = n;
(*p).next = ptr::null_mut();
if w.first_elem.is_null() {
w.first_elem = p;
prev = p;
continue;
}
(*prev).next = p;
prev = (*prev).next;
}
xxx::print_all_attrs(&mut w);
// dealloc stuff here.
}
I wonder that if there is another possible way to do that without using Layout and its friends? I see this is one of the proper way to make it but it makes me feel this is not the expected "Rust-way".
The current code:
class A {
List<int> listOne = [];
List<int> listTwo = [];
List≤int> listOfLists = [
...listOne,
...listTwo
];
}
Results in the following error for each list with an spread operator (...):
error: The instance member 'listOne' can't be accessed in an initializer.
error: The instance member 'listTwo' can't be accessed in an initializer.
What I know:
listOne etc. can't be referenced in another initializer
So what I tried: https://dart.dev/tools/diagnostic-messages#implicit_this_reference_in_initializer
class C {
int x;
C() : x = defaultX;
static int get defaultX => 0;
}
Unfortunately, I do not know how to translate that to solve my problem.
Can you guys help me out?
You need to explicitly make a constructor and do the assignment there.
class A {
List<int> listOne = [];
List<int> listTwo = [];
List<int> listOfLists;
A() {
listOfLists = [...listOne, ...listTwo];
}
}
If you're using null-safety then you should add the late keyword.
class A {
List<int> listOne = [];
List<int> listTwo = [];
late List<int> listOfLists;
A() {
listOfLists = [...listOne, ...listTwo];
}
}
How can I pick N unique random enums in dart?
enum Fruits { Apple, Peach, Orange, Mango }
List<Fruits> fruit = Fruits.random(N) // <-- implement this
you can create an extension for enum
enum Fruits { Apple, Peach, Orange, Mango }
extension FruitsExt on Fruits {
static List<Fruits> generateRandomFruits(int n) {
var rnd = Random();
return List.generate(n, (i) => Fruits.values[rnd.nextInt(Fruits.values.length)]);
}
static List<Fruits> generateRandomUniqueFruits(int n) {
var list = List<Fruits>.from(Fruits.values)..shuffle();
return list.take(n).toList();
}
}
and use it like this
List<Fruits> fruits = FruitsExt.generateRandomFruits(10);
List<Fruits> fruits = FruitsExt.generateRandomUniqueFruits(3);
or use it without extension
var rnd = Random();
var list = List.generate(10, (i) => Fruits.values[rnd.nextInt(Fruits.values.length)]);
or, as mentioned in comments below by #Irn
you can make them top level functions
List<Fruits> generateRandomFruits(int n) {
var rnd = Random();
return List.generate(n, (i) => Fruits.values[rnd.nextInt(Fruits.values.length)]);
}
List<Fruits> generateRandomUniqueFruits(int n) {
var list = List<Fruits>.from(Fruits.values)..shuffle();
return list.take(n).toList();
}
Some user's answers is indeed helping. But if we would consider your option of having only unique enums, then we might use some other approach. The approach is basically to use Set class to store only the unique data. And we are concerned about getting the final data as List(), then convert it using toList()
import 'dart:math';
enum Fruits { Apple, Peach, Orange, Mango }
void main() {
// we are initializing our Fruits to be a set to store UNIQUE DATA ONLY
Set<Fruits> _fruits = {};
// this will go on for the length of Fruits, which is 5 right now
for(int i=0; i<Fruits.values.length; i++){
// this will only generate the number till your enum's length
var index = Random().nextInt(Fruits.values.length);
_fruits.add(Fruits.values[index]);
}
// converting it to List finally
print(_fruits.toList());
}
OUTPUT
[Fruits.Apple, Fruits.Orange, Fruits.Peach]
You can get a list of all values from the enums.values, then shuffle the list and take an appropriate long sublist of it:
enum Fruits { Apple, Peach, Orange, Mango }
void main() {
List<Fruits> fruit = List.from(Fruits.values);
for(int i=0;i<3;++i) {
fruit.shuffle();
print(fruit.sublist(0,3));
}
}
Output:
[Fruits.Mango, Fruits.Orange, Fruits.Apple]
[Fruits.Apple, Fruits.Orange, Fruits.Mango]
[Fruits.Orange, Fruits.Apple, Fruits.Peach]
I solved it eventually with sets as #Alok suggested:
import 'dart:math';
List<T> generateRandomList<T>(int N, List<T> list) {
Set<T> setOfT = {};
var rnd = Random();
while (setOfT.length < N) {
setOfT.add(list[rnd.nextInt(list.length)]);
}
return setOfT.toList()..shuffle();
}
usage:
enum Fruits { Apple, Peach, Orange, Mango }
print(generateRandomList(2, Fruits.values));
output:
[Fruits.Peach, Fruits.Mango]
A general approach for picking a number of elements from any list (or iterable) uniformly at random would be:
import "dart:math";
extension<T> on Iterable<T> {
/// Chooses [count] of the elements of this iterable.
///
/// The elements are chosen at random, with each
/// element having an equal chance of being in the
/// resulting list.
/// The returned elements are not in any specific order.
List<T> choose(int count, [Random random]) {
var iterator = this.iterator;
List<T> result = [
for (var i = 0; i < count; i++)
if (iterator.moveNext())
iterator.current
else
throw StateError("Too few elements")
];
random ??= Random();
var seenCount = count;
while (iterator.moveNext()) {
seenCount++;
var pos = random.nextInt(seenCount);
if (pos < count) result[pos] = iterator.current;
}
return result;
}
}
You can then use it on enums as var someFruits = Fruites.values.choose(2);.
I am actually working with maps in Dart and I couldn't figure out why the map variable in my example is behaving strangely or I am doing something wrong in my code.
Please can someone help me to debug the code, I have posted the code to reproduce the issue.
example.dart
void main() {
var data2 = {};
var data1 = {};
var floorDetails = new Map();
floorDetails.clear();
for (int i = 0; i < 2; i++) {
data2.clear();
data1.clear();
for (int j = 0; j < 2; j++) {
data1 = {
'flat${(i + 1) * 100 + (j + 1)}': {'flattype': "flat"},
};
data2.addAll(data1);
}
print('data2=$data2');
floorDetails['floor${(i+1)}'] = data2;
print('floorDetails = $floorDetails');
}
print(floorDetails.keys);
}
The output from the code is:
floorDetails = {
floor1: {
flat201: {flattype: flat},
flat202: {flattype: flat}
},
floor2: {
flat201: {flattype: flat},
flat202: {flattype: flat}
}
}
Actually I was expecting the output to be:
floorDetails = {
floor1: {
flat101: {flattype: flat},
flat102: {flattype: flat}
},
floor2: {
flat201: {flattype: flat},
flat202: {flattype: flat}
}
}
this is actually overwriting the values of all the keys inside the map floorDetails as per documentation for Map.addAll() method
void addAll(
Map<K, V> other
)
Adds all key-value pairs of other to this map.
If a key of other is already in this map, its value is overwritten.
The operation is equivalent to doing this[key] = value for each key and associated value in other. It iterates over other, which must therefore not change during the iteration.
although in the given example the keys are different but it is still overwriting the values.
Please, any help would be much appreciated.
Many Thanks,
Mahi
In the first iteration, here you assign data2
floorDetails['floor${(i+1)}'] = data2;
but the first line in the next iteration is
data2.clear();
which clears data2. This also clears the content of floorDetails['floor1']`, because it references the same map.
Either you create a new map, instead of clearing it by changing
data2.clear();
data1.clear();
to
data2 = {}; // or new Map()
data1 = {};
or create a copy of the map before assigning it
floorDetails['floor${(i+1)}'] = new Map.from(data2);
Map is an object and copied by reference. Only primitive types like bool, double, int, and String are copied by value.
I'd like to know if there's any Dart function like PHP's strrev(). If not, could you please show my any source code how to make it on my own?
Thank you.
Lists can be reversed, so you can use this to reverse a String as well:
new String.fromCharCodes("input".charCodes.reversed.toList());
I haven't found one in the API, as a brand new Dart user (as of this afternoon). However, reversing a string is pretty easy to do in any language. Here's the typical O(n) solution in Dart form:
String reverse(String s) {
var chars = s.splitChars();
var len = s.length - 1;
var i = 0;
while (i < len) {
var tmp = chars[i];
chars[i] = chars[len];
chars[len] = tmp;
i++;
len--;
}
return Strings.concatAll(chars);
}
void main() {
var s = "dog";
print(s);
print(reverse(s));
}
May be a standardized reverse() method will be implemented in future in List (dart issue 2804), the following is about 8 to 10 times faster than the previous typical solution:
String reverse(String s) {
// null or empty
if (s == null|| s.length == 0)
return s;
List<int> charCodes = new List<int>();
for (int i = s.length-1; i>= 0; i-- )
charCodes.addLast(s.charCodeAt(i)) ;
return new String.fromCharCodes(charCodes);
}
try this instead of others.
String try(str) {
return str.split('').reversed.join('');
}
String theString = "reverse the string";
List<String> reslt = theString.split("");
List<String> reversedString = List.from(reslt.reversed);
String joinString = reversedString.join("");
print(joinString);
Ouput: gnirts eht esrever