...currently am practicing to fill a struct that contains an array(char array to store multiple elements). The scenario am trying to implement is as follows:
The general task is (to store student information, name as string and courses taken by the student as a list or char**)
student information is first loaded from file!(myfile.txt)
tokenize/parse student information and load to struct
The file that contains my student information is:
myfile.txt (each line contains student name and list of courses) delimited by ":"
Austin Barbra:Biology,chemistry,maths,music
Romio Chandra:Mechanics,IT,Geology,music,Astronomy
.
.
My main.c is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define path "myfile.txt"
typedef struct student_info
{
char *studt_name;
char *cources_as_string;
char **cources_as_list;
}std_info ;
std_info *myinfo; //a global var that will conatain student info
int student_count = 0,cource_count=0;
void load_file()
{
int i,yu,index=0;
char *line =NULL,* token = NULL;
size_t len=0;
FILE *fp;
fp =fopen(path,"r");
if(fp==NULL)
{
perror("FILE OPEN ERROR[IN load_file]: ");
return;
}
if (( myinfo = (struct student_info *) malloc( 2 * sizeof(myinfo) ) ) == NULL)//malloc for 2 students
puts ("malloc fail");
while (getline(&line, &len, fp) != -1 )
{
strtok(line,"\n");
char *token;
token = strtok(line,":");
myinfo[index].studt_name=(char * ) malloc(200 * sizeof(char ) );
strcpy(myinfo[index].studt_name,token);
token = strtok(NULL, ":");
myinfo[index].cources_as_string=(char * ) malloc(200 * sizeof(char ) );
strcpy(myinfo[index].cources_as_string,token);
index++;
}
student_count = index;
fclose(fp);
}
char** return_cource_list(char* cources_string)
{
char *token;
char **cource_list = malloc (sizeof (char *) * 10);
int index = 0;
//course_string is delimited by ",": (eg. Biology,chemistry,maths,music). parse this and add to my char ** variable.
token = strtok(cources_string,",");
cource_list[0]= token;
while (token != NULL)
{
cource_list[index]= token;
token = strtok (NULL, ",");
index++;
}
cource_count = index;
return cource_list;
}
int main()
{
int i,j;
load_file();
for(i=0;i<student_count;i++)
{
printf("============================\n");
printf("NAME: %s >>COURCE_string: %s\n",myinfo[i].studt_name,myinfo[i].cources_as_string);
char ip_list[200];
char** std_cource_list = return_cource_list(myinfo[i].cources_as_string);
for(j=0;j<cource_count;j++)
{
printf("\tCOURCE_list[%d]: %s\n",j,std_cource_list[j]);
//segmentation fault exists here, to copy "std_cource_list[j]" to my struct...(need help here).
strcpy(myinfo[i].cources_as_list[j],std_cource_list[j]);
}
}
}
The problem am facing is to fill the "char **cources_as_list;" member of the struct. Am getting a seg_fault from the inner for loop(iterating on j). Do i miss something in my code?
I fixed it quick so that it doesn't crash and output is correct, it can be better (there are leaks we can fix) but it actually prints your stuff now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define path "myfile.txt"
typedef struct student_info {
char *studt_name;
char *cources_as_string;
char **cources_as_list;
} std_info;
std_info *myinfo; //a global var that will conatain student info
int student_count = 0, cource_count = 0;
void load_file() {
int i, yu, index = 0;
char *line = NULL, *token = NULL;
size_t len = 0;
FILE *fp;
fp = fopen(path, "r");
if (fp == NULL) {
perror("FILE OPEN ERROR[IN load_file]: ");
return;
}
if ((myinfo = (struct student_info *) malloc(2 * sizeof(*myinfo))) == NULL)//malloc for 2 students
puts("malloc fail");
while (getline(&line, &len, fp) != -1) {
strtok(line, "\n");
char *token;
token = strtok(line, ":");
myinfo[index].studt_name = malloc(200 * sizeof(char));
strcpy(myinfo[index].studt_name, token);
token = strtok(NULL, ":");
myinfo[index].cources_as_string = malloc(200 * sizeof(char));
strcpy(myinfo[index].cources_as_string, token);
index++;
}
student_count = index;
//fclose(fp);
}
char **return_cource_list(char *cources_string) {
char *token;
char **cource_list = malloc(sizeof(char *) * 10);
int index = 0;
//course_string is delimited by ",": (eg. Biology,chemistry,maths,music). parse this and add to my char ** variable.
token = strtok(cources_string, ",");
cource_list[0] = token;
while (token != NULL) {
cource_list[index] = strdup(token);
token = strtok(NULL, ",");
index++;
}
cource_count = index;
return cource_list;
}
/* returns an array of char*, all of which NULL */
char **alloc_argv(unsigned rows) {
char **matrix = malloc(rows * sizeof(char *));
if (!matrix) abort();
for (unsigned row = 0; row < rows; row++) {
matrix[row] = malloc(rows * sizeof(char *));
matrix[row] = "\0";
if (!matrix[row]) abort();
}
return matrix;
}
int main() {
int i, j;
load_file();
for (i = 0; i < student_count; i++) {
printf("============================\n");
printf("NAME: %s >>COURCE_string: %s\n", myinfo[i].studt_name, myinfo[i].cources_as_string);
char ip_list[200];
char **std_cource_list = return_cource_list(myinfo[i].cources_as_string);
for (j = 0; j < cource_count; j++) {
printf("\tCOURCE_list[%d]: %s\n", j, std_cource_list[j]);
//segmentation fault exists here, to copy "std_cource_list[j]" to my struct...(need help here).
myinfo[i].cources_as_list = alloc_argv(100);
myinfo[i].cources_as_list[j] = malloc(sizeof(char **));
strcpy(myinfo[i].cources_as_list[j], std_cource_list[j]);
}
}
}
Output
============================
NAME: Austin Barbra >>COURCE_string: Biology,chemistry,maths,music
COURCE_list[0]: Biology
COURCE_list[1]: chemistry
COURCE_list[2]: maths
COURCE_list[3]: music
============================
NAME: Romio Chandra >>COURCE_string: Mechanics,IT,Geology,music,Astronomy
COURCE_list[0]: Mechanics
COURCE_list[1]: IT
COURCE_list[2]: Geology
COURCE_list[3]: music
COURCE_list[4]: Astronomy
Process finished with exit code 0
Related
How i can create a function for reading structure from a test.txt. I have a good works code in main, but i need to carry out it from main(). How combine (struct student PI1[N] and (fread() or fgets() or fwrite()));
struct student {
char surname[50];
char name[50];
char dayBirth[50];
int mark;
};
struct student PI1[N];
int main()
{
int counter = 0;
char str[50];
const char s[2] = " ";
char* token;
FILE* ptr;
int i = 0;
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
char* tmp;
int Itmp;
while (fgets(str, 50, ptr) != NULL) {
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
strcpy(PI1[i].name, token);
token = strtok(NULL, s);
strcpy(PI1[i].dayBirth, token);
token = strtok(NULL, s);
Itmp = atoi(token);
PI1[i].mark = Itmp;
i++;
counter++;
}
}
Rather than "can create a function for reading structure from a test.txt", start with a function to convert a string from fgets() into a struct. Then call it as needed.
Use sprintf() and " %n" to detect complete scan with no extra text.
// Return success flag
bool string_to_student(struct student *stu, const char *s) {
int n = 0;
sscanf(s, "%49s%49s%49s%d %n", stu->surname, stu->name,
stu->dayBirth, &stu->mark, &n);
return n > 0 && s[n] == '\0';
}
Use
while (i < N && fgets(str, sizeof str, ptr) &&
string_to_student(&PI1[i], str)) {
i++;
}
counter = i;
I'm trying to read in a text file, say input.txt, into an array of structs to then print out (and free memory of course). My C coding is a bit scratchy though, and I'm looking for help.
Input.txt contains lines of information about a single person. I want to read in the people, sort by name and print out in sorted order. Before I can do this, I'm just trying to create an array of people, allocate memory to each person, copy in the details from the text file, and then print them out finally. It's not even getting to the print out, as you can see it gives a segmentation fault:
I'm using the following:
gcc -Wall -O2 -o program filename.c
and getting this
Segmentation fault: 11
input.txt contents:
Joan 0212672938 joan#gmail.com
John 0365242939 john#yahoo.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
char *phone;
char *email;
};
int main(void) {
int i;
int peopleSize = 0;
char * pch;
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
struct person** people = malloc(100 * (sizeof (people[0])));
/* Create 100 people */
char *nameTmp = malloc(30 * sizeof nameTmp[0]);
char *phoneTmp = malloc(30 * sizeof phoneTmp[0]);
char *emailTmp = malloc(30 * sizeof emailTmp[0]);
/* Open the file for reading */
char *line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, f);
while (line_size >= 1) {
line_count += 1;
people[line_count-1] = malloc(sizeof (people[line_count-1]));
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%s\n", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc((strlen(nameTmp) + 1) * sizeof (people[line_count-1]->name[0]));
people[line_count-1]->phone = malloc((strlen(phoneTmp) + 1) * sizeof (people[line_count-1]->phone[0]));
people[line_count-1]->email = malloc((strlen(emailTmp) + 1) * sizeof (people[line_count-1]->email[0]));
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i++) {
printf("%s\t", people[i]->name);
printf("%s\t", people[i]->phone);
printf("%s", people[i]->email);
printf("\n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i++) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}
In general, when debugging, I would recommend compiling without optimizations and with the debug flag (-g). Then step through your program in GDB and see where it breaks.
Most of the fixes were already mentioned in the comments. See the code below for a line-by-line explanation of the fixes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // now you can use "person" type rather than "struct person"
char *name;
char *phone;
char *email;
} person;
int main(void) {
int i;
int peopleSize = 0;
char * pch = malloc(30); // Must be initialized before use
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
person** people = malloc(100 * (sizeof(person*))); //This is an array of 100 pointers to person so you want sizeof(person*)
/* Create 100 people */
char *nameTmp = malloc(30); // These are char arrays. Each char occupys a byte and malloc allocates byte by default.
char *phoneTmp = malloc(30);
char *emailTmp = malloc(30);
/* Open the file for reading */
char *line_buf = malloc(30); // MUst be initialized before use;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, f);
while (line_size >= 1) {
line_count += 1;
people[line_count-1] = malloc(sizeof(person)); // You are allocating memory for a single person, so you want sizeof(person)
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%s\n", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc(strlen(nameTmp) + 1); // As above these are char arrays so there is no need for sizeof
people[line_count-1]->phone = malloc(strlen(phoneTmp) + 1);
people[line_count-1]->email = malloc(strlen(emailTmp) + 1);
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i++) {
printf("%s\t", people[i]->name);
printf("%s\t", people[i]->phone);
printf("%s", people[i]->email);
printf("\n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i++) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}
This code reads file and split it lines into array in order to compare lines elements to each other.
The problem that it gives me as the first line
)�H� 2382 2382
I think that the function char **linecontent(char *line) is the problem but I am new in C and I tried every possible solution and I have nothing.
I am very sorry for asking.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** split(char string[],const char seps[])
{
char ** res = NULL;
char * p = strtok(string, seps);
int n_spaces = 0, i;
while (p) {
res = realloc(res, sizeof (char*) * ++n_spaces);
if (res == NULL) {
exit(-1); /* memory allocation failed */
}
res[n_spaces-1] = p;
p = strtok(NULL, seps);
}
res = realloc(res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = '\0';
return res;
free(res);
}
char** readfile(char *name, int *lsize)
{
FILE *fp;
char *result;
char line[500];
char *pline = NULL;
char **lines = NULL;
int i = 0;
int l = 0;
fp = fopen(name, "r");
while (fgets(line,500, fp)) {
i++;
pline = strdup(line);
lines = (char**)realloc(lines, sizeof (char**) * (++l));
/* Add to lines */
lines[l-1] = pline;
*lsize += 1;
pline = NULL;
}
fclose(fp);
return lines;
}
char** linecontent(char *line)
{
char **linecont;
char hit[300];
strncpy(hit, line, sizeof(hit) - 1);
hit[sizeof(hit) - 1] = '\0';
linecont = split(hit, "\t");
return linecont;
}
int main()
{
char **lines = NULL;
int lsize = 0;
lines = readfile("TEMP", &lsize);
int i = 0;
while (i != lsize) {
char **linecont1;
char *thisline=lines[i];
linecont1=linecontent(thisline);
char *pname1 = linecont1[0];
char *acc1 = linecont1[1];
int start1 = atoi(linecont1[3]);
int miss1 = atoi(linecont1[4]);
printf("%s\t%s\t%d\t%d\n", pname1, acc1, start1, start1);
i++;
}
}
In the last two days i have asked a question to load struct, but i have a problem to access my struct out side my loop(a loop to load my struct). i have edited my question/and code this way:
myfile.txt
Biology,chemistry,maths,music
Mechanics,IT,Geology,music,Astronomy
football,vollyball,baseball
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define path "myfile.txt"
typedef struct student_info
{
char **cources_as_list;
} std_info;
std_info *myinfo; //a global var that will conatain student info
int line_count = 0, cource_count = 0;
char** load_file()
{
char *line = NULL;
size_t len = 0;
FILE *fp;
int indexq=0;
fp = fopen(path, "r");
if (fp == NULL)
{
perror("FILE OPEN ERROR[IN load_file]: ");
exit(1);
}
char **mydata = malloc (sizeof (char *) * 4);//aup to four elements
while (getline(&line, &len, fp) != -1)
{
strtok(line, "\n");
mydata[indexq]= strdup(line);
indexq++;
}
line_count = indexq;
return mydata;
}
char **return_cource_list(char *cources_string) {
char *token;
char **cource_list = malloc(sizeof(char *) * 10);
int index = 0;
//course_string is delimited by ",": (eg. Biology,chemistry,maths,music). parse this and add to my char ** variable.
token = strtok(cources_string, ",");
while (token != NULL)
{
cource_list[index] = strdup(token);
token = strtok(NULL, ",");
index++;
}
cource_count = index;
return cource_list;
}
int main()
{
int i, j;
char** mydata = load_file(); //returns lines as a list/char ** array from file
for (i = 0; i < line_count; i++) //line_count is the number of elements/lines in "mydata"
{
printf("line_data: %s\n",mydata[i]);//i can see all my lines!
char **std_cource_list = return_cource_list(mydata[i]);
for (j = 0; j < cource_count; j++)
{
printf("\tcourse[%d]: %s\n",j,std_cource_list[j]);//i have all my courses as a list from each line
}
//can i load my struct like this? or any option to load my struct?
myinfo[i].cources_as_list = std_cource_list;
}
// i want to see my structure elements here, (nested for loop required).
}
Am getting seg_fault error while loading my char array to my struct.
(i.e: this line: myinfo[i].cources_as_list = std_cource_list;)
You need to allocate the memory for your struct.
std_info *myinfo = malloc(sizeof(std_info));
Also don't make it global, since there is really no need for global variables in this task.
Try
std_info * myinfo = malloc(line_count * sizeof *myinfo);
This allocates memory to hold line_count objects of std_info, with myinfo pointing to the 1st.
You never allocate space for myinfo and I would suggest making it a local variable. There is almost no need for global variables except in very specific cases.
Also, you are using malloc() almost only for fixed size allocations which would be easier to manage and more efficient if you do statically in the sense that you can use arrays for that.
This might be what you're interested in
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
struct student_info
{
char **courses;
size_t size;
};
char **
load_file(const char *const path)
{
char *line;
FILE *file;
char **data;
size_t row;
size_t length;
size_t count;
file = fopen(path, "r");
if (file == NULL)
{
perror("FILE OPEN ERROR[IN load_file]: ");
return NULL; // Notify the caller that there was a problem
// but do not necessarily quit as you might
// retry with another path.
}
count = 0;
for (int chr = fgetc(file) ; chr != EOF ; chr = fgetc(file))
count += (chr == '\n') ? 1 : 0;
rewind(file);
data = malloc((count + 1) * sizeof(*data));
if (data == NULL)
{
// Perhaps notify the error
fclose(file);
return NULL;
}
data[count] = NULL; // Use as end of array delimiter
row = 0;
line = NULL;
length = 0;
while ((length = getline(&line, &length, file)) != -1)
{
// The last character is always `\n' so remove it
data[row] = malloc(length);
if (data == NULL)
{
fclose(file);
for (size_t i = row ; i >= 0 ; --i)
{
free(data[i]);
free(data);
return NULL;
}
}
data[row][length - 1] = '\0';
memcpy(data[row], line, length - 1);
++row;
}
fclose(file);
// You need to `free' this, read the documentation
free(line);
return data;
}
char **
extract_courses_as_list(const char *const input)
{
char **courses;
size_t index;
const char *tail;
const char *head;
size_t count;
head = input;
count = 0;
/* Count the number of fields to allocate memory */
while (head != NULL)
{
tail = strchr(head, ',');
if (tail != NULL)
head = tail + 1;
else
head = NULL;
count += 1;
}
index = 0;
/* Allocate memory for the list, and the sentinel */
courses = malloc((count + 1) * sizeof(*courses));
head = input;
while (head != NULL)
{
ptrdiff_t length;
/* find the next `,' in the input string */
tail = strchr(head, ',');
if (tail == NULL) /* if it's not there, it's the last one */
tail = strchr(head, '\0');
/* compute the number of characters of the field */
length = (ptrdiff_t) (tail - head);
/* allocate space to copy the string */
courses[index] = malloc(length + 1);
if (courses == NULL) /* always be safe and check */
{
for (size_t i = index ; i >= 0 ; --i)
free(courses[index]);
free(courses);
return NULL;
}
/* always remember to `null' terminate */
courses[index][length] = '\0';
/* finally, copy the string */
memcpy(courses[index], head, length);
/* check whehter it was the last field and
* update the pointer to the next one accordingly
*/
if ((tail != NULL) && (*tail != '\0'))
head = tail + 1;
else
head = NULL;
/* Don't forget the fields counter */
index++;
}
courses[count] = NULL;
return courses;
}
void
concatenate_lists(struct student_info *info, char **source)
{
char **temporary;
size_t length;
length = info->size;
for (size_t i = 0 ; source[i] != NULL ; ++i)
length++;
temporary = realloc(info->courses, length * sizeof(*temporary));
if (temporary == NULL)
return;
for (size_t i = 0 ; source[i] != NULL ; ++i)
temporary[i + info->size] = strdup(source[i]);
info->courses = temporary;
info->size = length;
}
void
free_list(char **lines)
{
if (lines == NULL)
return;
for (size_t i = 0 ; lines[i] != '\0' ; ++i)
free(lines[i]);
free(lines);
}
int
main()
{
struct student_info info;
char **lines;
lines = load_file("data.tx");
if (lines == NULL)
return -1;
info.courses = NULL;
info.size = 0;
for (size_t i = 0 ; lines[i] != NULL ; ++i)
{
char **courses;
courses = extract_courses_as_list(lines[i]);
if (courses == NULL)
continue;
concatenate_lists(&info, courses);
free_list(courses);
}
for (size_t i = 0 ; i < info.size ; ++i)
{
fprintf(stderr, "%s\n", info.courses[i]);
free(info.courses[i]);
}
free(info.courses);
free_list(lines);
return 0;
}
You will notice that I never used strdup(), the reason being that the length of the string that we want to copy is always known.
I am trying to dynamically allocate an array of structs but whenever I run the program I keep getting: a.out(6487,0x7fff7ecb8300) malloc: * error for object 0x7fff6f670000: pointer being realloc'd was not allocated
* set a breakpoint in malloc_error_break to debug
struct node {
char course[25];
char category[20];
char prereq[50];
char notes[50];
};
int main(int argc, char* argv[])
{
FILE *fp;
char *filename = argv[1];
char *token;
char buffer[100];
char *del = ",\n";
int num = 5, i = 0, j =0, count = 0;
struct node *d = malloc(num * sizeof(struct node));
char** complete = malloc(num * sizeof(char*));
printf("%s\n", filename);
if( (fp = fopen(filename, "r")) == NULL )
{
printf("unable to open %s\n", filename);
exit(1);
}
while(fgets(buffer, sizeof(buffer), fp) != NULL)
{
if(count == num)
{
num = num + 5;
struct node *d = realloc(d, sizeof(d)*num);
printf("Reallocating\n");
}
token = strtok(buffer, del);
if(strncmp(token, "#", 1) != 0)
{
strcpy(d[count].course, token);
printf("%s\n", d[count].course);
strcpy(d[count].category, strtok(NULL, del));
printf("%s\n", d[count].category);
strcpy(d[count].prereq, strtok(NULL, del));
printf("%s\n", d[count].prereq);
strcpy(d[count].notes, strtok(NULL, del));
printf("%s\n", d[count].notes);
count++;
}
}
struct node *d = realloc(d, sizeof(d)*num);
You're declaring a new d variable which shadows the previous one, and feed its yet-uninitialized value to realloc.
You need to do this :
struct node *newD = realloc(d, num * sizeof *d);
if(!newD) {
// Allocation failure, do something about it and break out
} /* else */
d = newD;
Also note that I corrected the sizeof, which measured the size of the pointer, not the pointee's.
In:
struct node *d = realloc(d, sizeof(d)*num);
That declares a new variable d with initially undetermined value and passes it into realloc. Change that to:
struct node *tmp = realloc(d, sizeof(*d)*num);
if(!tmp)
; // handle error
d = tmp;