I have a bit of a problem. I am barely starting out with C, (comming from a C# background) and I am having problem with double pointers.
I have a structure as follows:
#ifndef __PROCESSINFO_H
#define __PROCESSINFO_H
struct ProcessInfo
{
int ProcesId;
int Priority;
int ExecutionTime;
int EllapsedTime;
char* ProcessName;
};
struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime);
void ProcessInfo_ToString(struct ProcessInfo *processInfo);
void ProcessInfo_Dispose(struct ProcessInfo *processInfo);
#endif
Implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "processinfo.h"
struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime)
{
struct ProcessInfo *processInfo;
processInfo = (struct ProcessInfo *)malloc(sizeof(struct ProcessInfo));
processInfo->ProcessId = processId;
processInfo->ProcessName = processName;
processInfo->Priority = priority;
processInfo->ExecutionTime = executionTime;
processInfo->EllapsedTime = 0;
return processInfo;
}
void ProcessInfo_ToString(struct ProcessInfo *processInfo)
{
printf(" %6i %6i %10i %10i, %25s", processInfo->ProcessId, processInfo->Priority, processInfo->ExecutionTime, processInfo->EllapsedTime, processInfo->ProcessName);
}
void ProcessInfo_Dispose(struct ProcessInfo *processInfo)
{
if(processInfo != NULL)
{
if(processInfo->ProcessName != NULL)
{
free(processInfo->ProcessName);
}
free(processInfo);
}
}
so now I have to manage a whole lot of ProcessInfo instances. I wrote another structure which would hold a pointer to a pointer to the ProcessInfo sturcture because i thought that I can increase and decrease it in size as needed (without too much hassle);
#ifndef __SCHEDULER_H
#define __SCHEDULER_H
struct Scheduler
{
struct ProcessInfo** Processes;
};
struct Scheduler* Scheduler_Allocate(void);
#endif
So the question is how do I initialize the **Processes member inside the Scheduler_Allocate method? How do I add stuff to it?
struct Scheduler s;
s.Processes = malloc(sizeof(struct ProcessInfo*) * size);
s.Processes[0] = ProcessInfo_Allocate(...);
// Add more items:
s.Processes = realloc(malloc(sizeof(struct ProcessInfo*) * (size + 1));
s.Processes[size] = ProcessInfo_Allocate(...);
size++;
Also see my example here:
Array of C structs
You don't need a double pointer to increase/decrease the size. Just use a normal pointer and realloc.
struct ProcessInfo* processes = malloc(sizeof(struct ProcessInfo) * 2);
struct ProcessInfo* processes_tmp;
if (!processes) {
/* bail */
}
/* do whatever with processes[0] and [1] */
processes_tmp = processes;
processes = realloc(processes, sizeof(struct ProcessInfo) * 5);
if (!processes) {
free(processes_tmp);
/* bail */
}
/* processes[0] and [1] are unchanged, and [2] [3] and [4] are now valid */
Then instead of having a ProcessInfo_Allocate, you could create a ProcessInfo_Init that would do most of the same except not allocating the memory:
int ProcessInfo_Init(struct ProcessInfo *pi, int processId, char *processName, int priority, int executionTime)
{
if (!pi) {
return -1;
}
pi->ProcessId = processId;
pi->ProcessName = processName;
pi->Priority = priority;
pi->ExecutionTime = executionTime;
pi->EllapsedTime = 0;
return 0;
}
size_t size = 10;//or what ever is the number of processes
struct ProcessInfo * process = (struct ProcessInfo *)malloc(size * sizeof(struct ProcessInfo));
if(!process)
//perhaps stop program? Do something
Processes = &process;
//later on
int i;
for(i = 0; i < size; i++)
{
printf("Process id =%d",Processes[i]->ProcesId);
etc
}
Pointer to pointer is initialized as array of pointers. So call malloc(count * sizeof(ProcessInfo*)) to initialize it. This way you get array of pointers to ProcessInfo. Then call malloc(sizeof(ProcessInfo)) many times to create particular ProcessInfo structures and put pointers to them to the array.
Also, user470379 is right that you don't need pointer to pointer just to change number of items in your array. But your idea is actually not bad either, you can stay with it if you want.
Also, since you are familiar with C#, I would recommend you to start with writing something like ArrayList in C. Then you can use it in many situations (like this one).
First change your definition to:
typedef struct Scheduler {
struct ProcessInfo** Processes;
} Scheduler;
Then something like this:
Scheduler *s;
s = malloc(sizeof(Scheduler));
if (s == NULL) {
exit(-1);
}
s = memset(s, 0, sizeof(Scheduler));
/* Or enter your own memory allocation stuff here */
i = 0; /* Or use some other number */
s->Processes[i] = someProcessInfo;
Related
I have been trying to make tree which has exactly 9 children of which some are uninitialized, so practically it is a tree of variable number of children. The indices of the children which are initialized are put in an array which has the size of the number of children that the tree node is supposed to have. And while freeing the whole tree of its memory allocation, I wanted to free that array, too, but I have encountered a problem which is that for some reason there is an error when I try to do so. Here is the code snippet which is fully executable after compilation, though, if someone would be so nice to help debug it for me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct moveNode
{
int rating;
// char player;
int numPossibleMoves, *possibleMoves;
struct moveNode **children;
};
struct moveNode *moveTreeHead;
struct moveNode *createHeadNode(void);
void initializeNode(struct moveNode *node, char *boardState);
int main()
{
moveTreeHead = createHeadNode();
printf("moveTreeHead->possibleMoves[1] %d\n", moveTreeHead->possibleMoves[1]);
free(moveTreeHead->possibleMoves);
}
void initializeNode(struct moveNode *node, char *boardState)
{
int i, possibleMovesCounter = -1;
node->numPossibleMoves = 0;
for (i = 0; i < 9; i++)
{
if (boardState[i] != 'x' && boardState[i] != 'o')
{
node->numPossibleMoves++;
}
}
if (node->numPossibleMoves != 0)
{
node->possibleMoves = (int *)malloc(sizeof *(node->possibleMoves));
for (i = 0; i < 9; i++)
{
if (boardState[i] != 'x' && boardState[i] != 'o')
{
possibleMovesCounter++;
node->possibleMoves[possibleMovesCounter] = i;
node->children[i] = (struct moveNode *)malloc(sizeof *(node->children[i]));
node->children[i]->numPossibleMoves = 0;
}
}
}
else
{
node->possibleMoves = NULL;
}
}
struct moveNode *createHeadNode()
{
struct moveNode *ret = (struct moveNode *)malloc(sizeof(struct moveNode));
ret->children = (struct moveNode **)malloc(sizeof *(ret->children) * 9);
initializeNode(ret, "012345678");
return ret;
}
I get the following debugging error message:
warning: HEAP[helloworld.exe]:
warning: Heap block at 0000028AA9C23530 modified at 0000028AA9C23544 past requested size of 4
Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x00007ffa1046a773 in ntdll!RtlRegisterSecureMemoryCacheCallback () from C:\WINDOWS\SYSTEM32\ntdll.dll
What exactly does that mean? All I am trying to do is to free an integer array which has been properly allocated with malloc. What is the problem here? And I even tested out that there is no problem with the array that has been created with printf("moveTreeHead->possibleMoves[1] %d\n", moveTreeHead->possibleMoves[1]).
Edit: Problem solved, thank you!! #UnholySheep
node->possibleMoves = (int *)malloc(sizeof *(node->possibleMoves)); allocates memory for exactly one int yet you later potentially access as if it were a larger array #UnholySheep
Other:
Casts not needed in the various allocations.
I'm doing dining-philosopher problem in C for assignment. And got stuck very begining of my code.
I decided each philosopher to be structure, and forks to be int array.
But I can't use global variable in this assignment.
So, I have to include shared variable in philosopher structure to pass them for arguments of thread routine.
Here is my problem - how to include int array in structure if I can't know proper size of them when initializing?
My plan is just include pointer variable in structure then allocate array's address using &.
But It doesn't work :
#include <stdlib.h>
/* inside structure*/
typedef struct s_share {
int **forks;
} t_share;
/* outside structure */
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
/* malloc structure arrary philo, size = 10 */
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
/* malloc int arrary forks, size = 100 */
forks = (int *)malloc(sizeof(int) * 100);
while (i < 10)
{
philo[i].share->forks = &forks; //error
i++;
}
}
Output : segmentation fault
I tested share->forks size like this :
printf("size of forks : %ld\n", sizeof(philo->share->forks));
Output was 8.
It's enough size to store int * pointer.
Through this I know It's not the memory allocation problem.
Then what is problem? Can someone check this for me?
Edit :
When I try to malloc directly philo->share->forks, I got same error.
typedef struct s_share {
int *forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
while (i < 10)
{
philo[i].share->forks = (int *)malloc(sizeof(int) * 100); //error
i++;
}
}
I thought it's because when philo initialized, sizeof operator calculated forks's memroy to be 8 - which required for pointer.
Is there something wrong?
Edit 2 :
To clear my question,
It's easy to solve this problem, if I write size of array in structure definition.
typedef struct s_share {
int forks[100];
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
but according to my assignmet I have to get philosopher's number from cmd. So I can't do that.
Above is simple version of my origin code
Sorry, Edit 2 is wrong :
typedef struct s_share {
int forks[100];
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
t_share *share;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
while (i < 10)
{
philo[i].share->forks[i] = 1;
i++;
}
}
Output
zsh: segmentation fault ./a.out
I still got segfault when I write array size in struct definition.
I used calloc to initialize all member in my struct but same error occurs :
typedef struct s_share {
int **forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
t_share *share;
int *forks;
int i;
i = 0;
philo = (t_philo *)calloc(10, sizeof(t_philo));
forks = (int *)calloc(100, sizeof(int));
while (i < 10)
{
philo[i].share->forks = &forks; //error
i++;
}
}
Edit 4:
I finally found error. It's because I didn't malloc 'share' struct in philo struct
typedef struct s_share {
int **forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
forks = (int *)malloc(sizeof(int) * 100);
while (i < 10)
{
philo[i].share = (t_share *)malloc(sizeof(t_share)); //here
philo[i].share.forks = &forks;
i++;
}
}
That one line -allocating struct share- solved problem.
Or, I can modify philo struct definition like this :
typedef struct s_philo {
t_share share; //not pointer, just struct
} t_philo;
In this way, I can automatically malloc struct share.
I got confused in this point. Thanks for helping!
this line
philo[i].share->forks
Is dereferencing the pointer 'share' which is not set. You called malloc and did not set any values, so the data inside your allocated buffer is 'garbage' data.
// add begin
t_share* new_share = (t_share*)malloc(sizeof(t_share));
philo[i].share = new_share;
// add end
// don't use &forks
philo[i].share->forks = forks; //error
i++;
// need forks++
forks++;
I Have a struct as
struct myStruct {
int message;
void*packet;
};
is it ok to dynamically allocate memory from a function in runtime like this
struct myStruct* create(int type, int length)
{
if(type==1)
myStruct->packet = (int *)malloc(length * sizeof(int));
if(type==2)
myStruct->packet = (double *)malloc(length * sizeof(double));
}
so that my packet can be configured as double as well as int?
It is not clear from your snippet when you allocate memory for the message container myStruct. Assuming that it is also being dynamically allocated, you can create memory for it and your array simultaneously.
The receiver of this message will need to know how to interpret the information, so we need to encode the information about type and length into it as well. Here is one way to achieve that:
struct myStruct {
int message;
int type;
int length;
};
So this contains the message of your original structure, as well as the information passed into the create() function. Notice that this is just the header, without any of the data allocated yet. We can create specializations with flexible arrays to represent that data.
struct myStructInt {
struct myStruct hdr;
int data[];
};
struct myStructDouble {
struct myStruct hdr;
double data[];
};
Each distinct supported array can have its own specialization. Now, your create() function can do a single allocation for the entire message.
struct myStruct * create (int type, int length) {
struct myStruct hdr = { 0, type, length };
struct myStruct *m;
size_t total = 0;
switch (type) {
case 1: total = sizeof(struct myStructInt) + length * sizeof(int);
break;
case 2: total = sizeof(struct myStructDouble) + length * sizeof(double);
break;
/* ... */
}
if ((m = malloc(total)) != NULL) *m = hdr;
return m;
}
The caller would know what type of message it wanted to create, so it can properly cast the pointer to the intended type after it receives the pointer from create().
In your example there's an error: the struct is not allocated and the create function doesn't return the allocated structure. You cannot do this: myStruct->packet = (int *)malloc(length * sizeof(int)); without before allocating myStruct.
I have written two samples where is used an enum to enumerate the type of packet array in the structure and a union packet to manage the
different kind of data.
The structure myStruct will contain info about the type of contents of the packet union and its array dimension.
The function create, in the 1st sample, uses only one malloc to allocate both structure space and packet space. In this way is more simple to deallocate the structure. Furthermore create may return an error on the parameter err to indicate error conditions, on the other hands in case of error, in this version of 1st sample, the return value of the function shall be NULL.
If you don't need to allocate the structure I've written a second sample that allocates only the space for the union packet (the 2nd sample above). Here the function create allocates packet for an already allocated structure and returns 0 or an error value if an error occurs.
Here the 1st sample:
#include <stdio.h>
#include <stdlib.h>
typedef enum myType {
myTypeDouble,
myTypeInt
} myType;
typedef struct myStruct {
myType myType;
size_t length;
// int message; in this sample this has no mean!
union {
int * i;
double * d;
} packet;
} myStruct;
myStruct * create(myType mtype, size_t length, int *err)
{
myStruct * ms = NULL;
int retVal=0;
size_t mlen = sizeof (myStruct);
switch(mtype) {
case myTypeInt:
mlen += sizeof(int)*length;
break;
case myTypeDouble:
mlen += sizeof(double)*length;
break;
default:
mlen=0;
retVal=1;
break;
}
if (mlen) {
ms = malloc(mlen); // One malloc allocates struct and packet.
if (ms != NULL) {
ms->length = length;
ms->myType=mtype;
/* Don't care myType, the usable space is after
the structure dimension then ms->packet.i=[...]
should be also ms->packet.d=(double *)(ms+1);
*/
ms->packet.i=(int *)(ms+1);
} else {
retVal=2;
}
}
if (err)
*err=retVal;
return ms;
}
int main(void) {
#define PACKLEN 20
myStruct * ms[2]={NULL,NULL};
int err=0;
int i;
ms[0]=create(myTypeInt,PACKLEN,&err);
if (err)
return 1;
ms[1]=create(myTypeDouble,PACKLEN,&err);
if (err) {
if (ms[0])
free(ms[0]);
return 2;
}
for (i=0;i<PACKLEN;i++) {
ms[0]->packet.i[i] = i*2+1;
ms[1]->packet.d[i] = 2.1*(double)(i+1);
}
for (i=0;i<PACKLEN;i++) {
printf("%d ",ms[0]->packet.i[i]);
}
puts("");
for (i=0;i<PACKLEN;i++) {
printf("%g ",ms[1]->packet.d[i]);
}
puts("");
if (ms[0])
free(ms[0]);
if (ms[1])
free(ms[1]);
}
Here the 2nd sample:
#include <stdio.h>
#include <stdlib.h>
typedef enum myType {
myTypeDouble,
myTypeInt
} myType;
typedef struct myStruct {
myType myType;
size_t length;
// int message; don't care in this sample.
union {
int * i;
double * d;
} packet;
} myStruct;
int create(myStruct * ms, myType mtype, size_t length)
{
int retVal=0;
size_t mlen = 0;
if (!ms) {
return 1;
}
switch(mtype) {
case myTypeInt:
mlen = sizeof(int)*length;
break;
case myTypeDouble:
mlen = sizeof(double)*length;
break;
default:
mlen=0;
retVal=2;
break;
}
if (mlen) {
/* Don't care myType! ms->packet.i=[...]
should be also ms->packet.d=malloc(mlen);
*/
ms->packet.i=malloc(mlen);
if (ms) {
ms->length = length;
ms->myType=mtype;
} else {
retVal=3;
}
}
return retVal;
}
int main(void) {
#define PACKLEN 20
myStruct ms[2];
int err=0;
int i;
ms[0].packet.i=NULL;
ms[1].packet.d=NULL; // Although the use of .i has the same behaviour
err=create(&ms[0],myTypeInt,PACKLEN);
if (err)
return 1;
err=create(&ms[1],myTypeDouble,PACKLEN);
if (err) {
if (ms[0].packet.i)
free(ms[0].packet.i);
return 2;
}
for (i=0;i<PACKLEN;i++) {
ms[0].packet.i[i] = i*2+1;
ms[1].packet.d[i] = 2.1*(double)(i+1);
}
for (i=0;i<PACKLEN;i++) {
printf("%d ",ms[0].packet.i[i]);
}
puts("");
for (i=0;i<PACKLEN;i++) {
printf("%g ",ms[1].packet.d[i]);
}
puts("");
if (ms[0].packet.i)
free(ms[0].packet.i);
// Although the use of packet.i has the same behaviour.
if (ms[1].packet.d)
free(ms[1].packet.d);
}
As suggested in the comments, you can solve this problem by using a union.
typedef enum {INT_ARR, DOUBLE_ARR} myType;
struct myStruct {
myType type;
union {
int *iArr;
double *dArr;
} value;
}
The advantage of using a union is that the iArr pointer and dArr pointer occupy the same memory. Which field you should access the pointer as is determined by the type field.
The create function you've supplied is seemingly incomplete, as it never allocates memory for the struct or returns anything. If you choose to use the union scheme, you could write it like this:
struct myStruct *create(myType type, int length) {
// Allocate struct
struct myStruct *res = malloc(sizeof(struct myStruct));
res->type = type;
if(type == INT_ARR)
res->iArr = malloc(length * sizeof(int));
else if(type == DOUBLE_ARR)
res->dArr = malloc(length * sizeof(double));
return res;
}
Note that you should free() the result returned by this create function once you are done with the struct.
Well I am wanting to change the way my structures are written, currently I use array and I need to limit its use, but I wanted a way to create a dynamic array that is the size of the reading done, without always having to edit the array value.
Current Code:
struct sr_flag {
int value_flag;
};
struct er_time {
int value_time;
};
struct se_option {
struct sr_flag flag[50];
struct er_time time[50];
};
struct read_funcs
struct se_option *option;
void (*option_func) (void);
...
}
struct read_funcs func_;
struct read_funcs *func;
int sr_flags(int i, int fg, int val) {
if(i < 0)
return 0;
return func->option[i].flag[fg].value_flag = val;
}
void option_func(void) {
struct se_option fnc;
fnc.option = malloc(500 * sizeof(*(fnc.option)));
}
void read_fnc() {
func = &func_;
func->option = NULL;
func->option_func = option_func;
}
I look for a way to remove the array amount [50] instead each time the sr_flags function is executed the limit is raised
Example: sr_flags function executed 1x array would be [1] if executed 2x would be [2]
I also think about doing the same with the option_func function
I tried using the following more unsuccessfully
struct se_option {
struct sr_flag *flag;
struct er_time time[50];
};
int sr_flags(int i, int fg, int val) {
if(i < 0)
return 0;
func->option[i].flag = malloc(1 * sizeof(*(func->option[i].flag)));
return func->option[i].flag[fg].value_flag = val;
}
int main () {
for(int i < 0; i < 10; i++)
sr_flags(i, 1, 30);
return 0;
}
I'm not 100% certain on what it is you want but I think you just want to call realloc and increase the size by the amount you provide. And that's very easy to do, as for the values you want with the arrays I'm not sure so I just used a placeholder value.
#include <stdio.h>
#include <stdlib.h>
struct sr_flag {
int value_flag;
};
struct er_time {
int value_time;
};
struct se_option {
struct sr_flag* flag;
struct er_time* time;
};
void allocateflags(struct se_option* options, int size, int val){
options->flag = realloc(options->flag, size*sizeof(struct sr_flag));
struct sr_flag* flag = options->flag+size-1;
flag->value_flag = val;
}
void allocatetime(struct se_option* options,int size, int val){
options->time = realloc(options->time, size*sizeof(struct er_time));
struct er_time* time = options->time+size-1;
time->value_time = val;
}
void displayflagvalues(struct se_option* options,int size){
for(int index = 0; index < size ; ++index){
printf("flag: %i\n",options->flag[index].value_flag);
}
}
void displaytimevalues(struct se_option* options, int size){
for(int index = 0; index < size ; ++index){
printf("time: %i\n",options->time[index].value_time);
}
}
int main(){
struct se_option options = {0};
for(int index = 0; index < 10; ++index){
allocateflags(&options, index,index);
allocatetime(&options, index,index);
}
displayflagvalues(&options, 10);
displaytimevalues(&options,10);
return 0;
}
The code creates an se_option structure wheren sr_flag and er_time pointers are null. Then there's two functions one allocateflags and the other allocatetime, both of which call realloc with the size you provide. When you call realloc, all previous memory is copied over to the new array. Also free is called automatically by realloc.
This step
struct sr_flag* flag = options->flag+size-1;
flag->value_flag = val;
struct er_time* time = options->time+size-1;
time->value_time = val;
Is slightly redundant but it was just to show the newest array can hold the value. If you understand pointer arithmetic, all its doing is incrementing the pointer to the last position then subtracting 1 struct size and setting that value. Basically setting the value of the final array in the pointer.
Hello i am slowly learning c and trying my best.
Can someone tell me why my variables are undefined?
"processId, userId, arrivalTime, priority, expectedTimeRemaining, expectedPctCPU, realTime" are all giving an error!
Please help, i provided my code. I tried reading up about structures and pointers. Followed resources, and now i am trying to implement it myself.
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#define _CRT_SECURE_NO_WARNINGS
typedef enum States { NEW, READY, RUNNING, BLOCKED, SUSPENDED, EXIT, SUSPEND_READY } State;
char stateNames[7][14] = { "New", "Ready", "Running", "Blocked", "Suspended", "Exit", "SuspendReady" };
// partial - skips info needed to actually conduct process switch - contents of registers, program counter, stack pointers, ... pointers to page tables ...
// we ARE going to need some way of indicating IO needs so can decide when they should block
struct processblock {
int processId;
int userId; // pointer instead?
State processState; // Not input - initially NEW
int arrivalTime; // time units in simulation, not actual time
int priority; // base priority
int currentPriority; // can be upped or lowered based on what has happened with the process - not input - initially same as base priority
int timeWaitingSoFar; // Not input - initially zero
int timeProcessingLastRun; // Not input - initially zero
int timeProcessingSoFar; // Not input - initially zero
int expectedTimeRemaining;
struct event* waitingOn; // ??? // Not input - initially zero
int expectedMemoryNeed;
int expectedPctCPU; // to get an idea of whether CPU bound or IO bound
bool realTime; // whether a real-time process or not (real-time processes may need immediate attention)
struct processblock* nextPtr; // not used in this program - but preparing for linked list version
};
//fill in the array from file
int fillArrayFromFile(struct processblock processor[], FILE*fPtr, int maxSize) {
int count = 0;
//unsure if realtime is a parameter, pls check and confirm with me
while ((count < maxSize) && fscanf("fPtr,%d,%d,%d,%d,%d,%d,%d", processId, userId, arrivalTime, priority, expectedTimeRemaining, expectedPctCPU, realTime) != EOF) {
//fill in each part of the array
processor[count].processId = count;
}
}
You should use a linked list to store the data you need, here there is an example, this code reads the lines of a file named test.txt that has this layout:
100,101,20,1,50,1,0
102,105,30,1,55,1,1
101,10,40,0,56,1,1
and store all the values in a linked list, that contains your structure. I hope you'll learn something new, happy coding!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define _CRT_SECURE_NO_WARNINGS
typedef enum States { NEW, READY, RUNNING, BLOCKED, SUSPENDED, EXIT, SUSPEND_READY } State;
char * stateNames[7] = { "New", "Ready", "Running", "Blocked", "Suspended", "Exit", "SuspendReady" };
struct processblock {
int processId;
int userId;
int arrivalTime;
int priority;
int expectedTimeRemaining;
int expectedPctCPU;
int realTime; // scanf can't read boolean
State processState;
int currentPriority;
int timeWaitingSoFar;
int timeProcessingLastRun;
int timeProcessingSoFar;
int expectedMemoryNeed;
};
struct Node
{
struct processblock pblock;
struct Node *next;
};
typedef struct Node * List;
void NewNode(List * p , struct processblock pb) //function that creates new linked list nodes
{
List temp;
temp = (List)malloc(sizeof(struct Node));
temp->pblock = pb;
temp->next = *p;
*p = temp;
}
int fillArrayFromFile(char *filename, List * p) {
FILE *fPtr;
int count = 0;
struct processblock pb;
char * buffer;
buffer = malloc(sizeof(struct processblock));
if(!(fPtr= fopen(filename, "r")))
{
perror("No File");
fclose(fPtr);
return 0;
}
while(fgets(buffer,sizeof(struct processblock),fPtr))//read every line of file and store them in a buffer
{
if(sscanf(buffer,"%d,%d,%d,%d,%d,%d,%d", &pb.processId, &pb.userId, &pb.arrivalTime, &pb.priority, &pb.expectedTimeRemaining, &pb.expectedPctCPU, &pb.realTime) == 7 ) // read from the buffer
{
NewNode(p, pb); // creates new node from filled structure
count++;
}
}
free(buffer);
fclose(fPtr);
return count;
}
void ViewElements(List p)
{
struct processblock pb;
while(p != NULL)
{
pb = p->pblock;
printf("%d,%d,%d,%d,%d,%d,%d\n", pb.processId, pb.userId, pb.arrivalTime, pb.priority, pb.expectedTimeRemaining, pb.expectedPctCPU, pb.realTime);
p = p->next;
}
}
int main()
{
List HeadNode = NULL;
printf("Loaded %d lines\n", fillArrayFromFile("test.txt", &HeadNode));
ViewElements(HeadNode);
return 0;
}