I am not able to initialize all three pointers to struct S, and I don't know why.
I am using a fixed-length array as stack to store values.
The header file is created this way to hide information (struct S), and should be kept as generic as possible.
main.c
// main.c
#include <stdio.h>
#include "stack_exercise4.h"
int main(void) {
Stack *stack_1, *stack_2, *stack_3;
int a, b;
make_empty(stack_1);
make_empty(stack_2);
make_empty(stack_3);
return 0;
}
Problem is, after Stack *stack_1, *stack_2, *stack_3, only stack_2 has a valid address for Struct stack. stack_1 and stack_3 have some strange looking addresses, and I can't assign any values to stack_1->top, nor stack_3->top. What is the problem?
header file
// stack_exercise4.h
#ifndef STACK_EXERCISE4_H
#define STACK_EXERCISE4_H
#include <stdbool.h> /* C99 only */
typedef struct S Stack; /* incomplete type to hide the content
of S. */
void make_empty(Stack *s);
bool is_empty(const Stack *s);
bool is_full(const Stack *s);
void push(Stack *s, int i);
int pop(Stack *s);
#endif
stack source file
// stack_exercise4a.c
#include "stack_exercise4.h"
#include <stdio.h>
#define MAX_STACK_SIZE (10)
struct S {
int top;
int contents[MAX_STACK_SIZE];
};
void make_empty(Stack *s) {
s->top = 0;
}
bool is_empty(const Stack *s) {
return (s->top <= 0);
}
bool is_full(const Stack *s) {
return (s->top >= MAX_STACK_SIZE - 1);
}
void push(Stack *s, int i) {
if (!is_full(s)){
(s->contents)[s->top++] = i;
} else {
printf("Failed to push, Stack is full.\n");
}
}
int pop(Stack *s) {
return (s->contents)[s->top--];
}
The stack pointers must point on memory spaces before being dereferenced in make_empty(). Something like this could be the starting point: make_empty() allocates the memory space.
void make_empty(Stack **s) {
(*s) = (struct S *)malloc(sizeof(struct S));
(*s)->top = 0;
}
And so the initialization of the pointers would be:
make_empty(&stack_1);
make_empty(&stack_2);
make_empty(&stack_3);
Declare stack_X on stack instead.
#include <stdio.h>
#include "stack_exercise4.h"
int main(void) {
Stack stack_1 = {0}, stack_2 = {0}, stack_3 = {0};
int a, b;
make_empty(&stack_1);
make_empty(&stack_2);
make_empty(&stack_3);
return 0;
}
Otherwise, I't would need to have constructor/destructor for your Stack data structure e.g new_stack(Stack *ptr) del_stack(Stack *ptr). For beginner, I would recommend to use stack instead of heap (stay away from malloc).
I'm trying to create a stack in C using structures but the push() function I wrote is acting strangely. I'm sure it is something obvious that I'm missing but I just couldn't figure out what.
#include <stdio.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
void push(STACK* st, int newitem)
{
st->top++;
st->items[st->top] = newitem;
printf("%d", st->items[st->top]);
}
int main()
{
int n = 1;
STACK* st;
printf("test 1\n");
st->top = -1;
push(st, n);
printf("test 2\n");
return 0;
}
DevCpp only compiles but doesn't execute the code. OnlineGDB runs it but only prints the first test.
This is because your variable STACK* st; was never initialized properly.
Some Important Points:
Don't assign -1 to the length (top), 0 would be better
STACK* st; should be just STACK st;
Your function void push(STACK* st, int newitem) should be declared with static linkage.
Write st->top++
Pass st variable by address to the push() function
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
As your total STACK_SIZE is only 50 so, int will be sufficient. But as your STACK_SIZE grows use size_t for your length(top).
use int main(void) { }, instead of int main() { }
NOTE: If STACK_SIZE and top becomes equal means your array is filled completely then further addition of data will lead to Undefined Behavior.
Final Code
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
static void push(STACK* st, int newitem)
{
if(st->top == STACK_SIZE)
{
fprintf(stderr, "stack size reached maximum length\n");
exit(EXIT_FAILURE);
}
st->items[st->top++] = newitem;
printf("%d\n", st->items[st->top - 1]); // we added +1 to `top` in the above line
}
int main(void)
{
int n = 1;
STACK st;
printf("test 1\n");
st.top = 0;
push(&st, n); //pass by address
return EXIT_SUCCESS;
}
I am trying to create a stack but I am having a problem initiating it. The code that I have is:
#define LINELN 72
#define STACKSZ 25
#define NEWLN '\n'
#include <stdlib.h>
#include <stdio.h>
// interface struct for stack
typedef struct stack {
char data[STACKSZ];
int top;
} stack;
void initstk(stack *s1);
int emptystk(stack s);
int main() {
stack s1;
initstk(s1);
printf("%d",emptystk(s1));
exit(0);
}
void initstk(stack *s1) {
s1->top=-1;
}
int emptystk(stack s) {
if(s.top == -1){
return 1;
}
else{
return 0;
}
}
I want it to print out 1 since the stack is empty but it is print out 0 still. I don't really understand. Could it be because of the pointer?
You declare:
void initstk(stack *s1);
/*...*/
int main() {
stack s1;
but then you invoke as:
initstk(s1);
Because initstk takes a pointer argument, you should pass the address of s1:
initstk(&s1);
I'm surprised your compiler didn't warn you about the mismatch.
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;
}
I just wrote some C code:
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef struct {
void **data;
time_t lastModified;
} container;
container *container_init() {
container *c = malloc(sizeof(container));
void *data = NULL;
c->data = &data;
c->lastModified = time(NULL);
return c;
}
void *container_getData(container *c) {
void **containerData = c->data;
return *containerData;
}
// only pass manually allocated data that can be free()'d!
void container_setData(container *c, void *data) {
free(container_getData(c));
c->data = &data;
}
void container_free(container *c) {
free(container_getData(c)); // <--- THIS LINE
free(c);
}
int main(int argc, const char *argv[]) {
for (int i = 0; i < 100000000; i++) {
char *data = strdup("Hi, I don't understand pointers!");
container *c = container_init();
container_setData(c, data);
container_free(c);
}
}
My logic was the following: When I call container_setData(), the old data is free()'d and a pointer to the new data is stored. That new data will have to be released at some point. That happens for the last time during the call to container_free().
I have marked a line in the container_free() function. I would have sworn I'd need that line in order to prevent a memory leak. However, I can't use the line ("object beeing freed was not allocated") and there's no memory leak if I delete it. How does the string from my loop ever get released?!
Could someone explain where the error is?
c->data = &data;
stores the address of the pointer data (the argument to your function), not the actual pointer. I.e., you're storing a pointer to a temporary.
You could have built the container structure with just a void *data member.
To explain larsmans answer with code make these changes:
typedef struct {
void *data;
time_t lastModified;
} container;
void *container_getData(container *c) {
return c->data;
}
void container_setData(container *c, void *data) {
free(c->data);
c->data = data;
}
void container_free(container *c) {
free(c->data);
free(c);
}
And other changes too -- this just gets you on the right track.