Failing to construct a stack using array in C - arrays

Now I have an input consists of a random string with '(' and ')'. I want to push these parentheses into a stack called "balance". But after I input, the program would terminate, and there was nothing in the stack. How can I fix this?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 1000
struct stack
{
int top;
char items[STACKSIZE];
};
void push(struct stack *pb, char x)
{
if(pb->top==STACKSIZE)
printf("The stack is full\n");
else
pb->items[pb->top++]=x;
}
int main()
{
while(1)
{
struct stack balance; //the stack called "balance"
struct stack *b; //the pointer of stack
char line[STACKSIZE]; //input
scanf("%s", line);
if(!strcmp(line, "-1")) //program stops when only "-1"
break;
b->top=0; //initializing top value
for(int i=0;i<STACKSIZE-1;i++)
{
if(line[i]=='(' || line[i]==')') //push '(' and ')' in the input to the stack
push(b, line[i]);
}
printf("test"); //can't reach this line
printf("%s\n", b->items);
}
return 0;
}

For some reason, you're using b as a pointer to the stack, instead of &balance itself. This is not wrong, but you must initialize b so it really points to the struct. So, instead of:
struct stack *b;
You should have:
struct stack *b = &balance;
Another potential problem is that you're reading until i reaches STACKSIZE. This is wrong, since you don't know whether the input is going to reach that length, and if it does not, then you're reading ahead of the end of line.
So, instead of:
for(int i=0;i<STACKSIZE-1;i++)
{
You should have:
for(int i=0;line[i] != '\0';i++)
{
BTW, you don't need to define ("redefine for each iteration"), all your locals inside the loop. That's is actually not going to happen, since the optimizer will move them out, but anyway.
Talking of potential problems, it is always a bad idea to have and infinite loop. Define exactly what is the exit condition, and you'll be in the safe side. You can even define something exceptional to happen and call break in that case, but not as the common rule.
You're reading input, and in this case something really common is the read-ahead technique.
int input_status = scanf("%s", line);
while(input_status != EOF
&& strcmp(line, "-1"))
{
// more things...
input_status = scanf("%s", line);
}
This way, each time you're testing the exit condition, you've just read and check whether the end condition ("-1" at input) or there is simply not more input (scanf returns EOF).
Here comes the complete code:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 1000
struct stack
{
int top;
char items[STACKSIZE];
};
void push(struct stack *pb, char x)
{
if(pb->top==STACKSIZE)
printf("The stack is full\n");
else
pb->items[pb->top++]=x;
}
int main()
{
struct stack balance; //the stack called "balance"
struct stack *b = &balance; //the pointer of stack
char line[STACKSIZE]; //input
int input_status = scanf("%s", line);
while(input_status != EOF
&& strcmp(line, "-1"))
{
b->top=0; //initializing top value
for(int i=0;line[i] != '\0';i++)
{
if(line[i]=='(' || line[i]==')') //push '(' and ')' in the input to the stack
push(b, line[i]);
}
printf("test"); //can't reach this line
printf("%s\n", b->items);
input_status = scanf("%s", line);
}
return 0;
}

Related

Simple stack program not accepting input and crashing

I am learning stacks right now and I decided to try to make a little program involving the stack from Magic the Gathering rules, which also follows a LIFO order.
The user asked whether they would like to
play a spell (push)
resolve a spell (pop) or
exit.
Now the tricky part is that I am trying to allow the elements of the stack to be multiple words each. This has been causing A LOT of problems.
I can input a word and print it outside the while(1) loop but if I put it inside everything goes haywire. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct {
char item[SIZE];
int top;
} stack;
void init(stack*);
void push(stack*, char[]);
char pop(stack*);
void init(stack* st) {
st->top = -1;
}
void push(stack* st, char* value) {
if (st->top == SIZE - 1) {
printf("STACK OVERFLOW\n");
return;
}
st->top++;
strcpy(st->item[st->top], value);
}
char pop(stack* st) {
if (st->top == -1) {
printf("STACK UNDERFLOW\n");
return -1;
}
char value;
strcpy(value, st->item[st->top]);
st->top--;
return value;
}
int main() {
stack st1, st2;
int choice;
char val[20];
init(&st1);
init(&st2);
printf("You have priority. What would you like to do?\n\n");
printf("1. Cast a spell\n2. Resolve the next spell\n3. Pass priority\n\n");
while (1) {
scanf("%d", &choice);
switch (choice) {
case 1:
printf("What is the spell?\n\n");
scanf("%[^\n]s", val);
printf("%s", val);
push(&st1, val);
case 2:
strcpy(val, pop(&st1));
printf("%s resolves.\n\n", val);
case 3:
exit(0);
}
}
return 0;
}
The reason you would be getting errors is that because of the type conversions.
char pop(stack* st) {
if (st->top == -1) {
printf("STACK UNDERFLOW\n");
return -1;
}
char value;
strcpy(value, st->item[st->top]);
st->top--;
return value;
}
The first thing, you don't need to pass the address when dealing with the arrays. The another thing is that you are trying to copy a whole string into a single character variable. So, there are so much type conversion problems in your code.
I suggest you to make the functions of void data type and provide the functionality within the block of the function. Just call the pop function with top value as an argument, and print the string within the function that you are popping.
Stack is a zero order data structure so it doesn't require inputs for popping purpose.

Error while printing the given inputs

This code:
#include<stdio.h>
struct my_structure {
char name[20];
int number;
int rank;
};
int main()
{
int n,i;
scanf("%d",&n);
struct my_structure variable[n];
struct my_structure *ptr;
ptr = &variable;
for(i=0; i<n; i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
scanf("%d",&ptr->rank);
}
for(i=0; i<n; i++)
{
printf("NAME: %s\n", ptr->name);
printf("NUMBER: %d\n", ptr->number);
printf("RANK: %d", ptr->rank);
}
return 0;
}
It is not printing correctly. I want to print the 1st input first and then the second. But I'm getting the output like printing only the second input two times.
Two changes you need to do:-
ptr = variable ;
Then you can increase ptr in loop.(The use of scanf is not robust - how to do it better is shown in the end of the answer).
for(i=0;i<n;i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
...
ptr++;
}
After that again do the assignment ptr = variable;.
You can also do this (Illustration on the users code)
..
scanf("%s",ptr[i].name);
scanf("%d",&ptr[i].number);
...
printf("%s",ptr[i].name);
printf("%d",ptr[i].number);
Earlier you have type mismatch in assignment. You were assigning a struct my_structure (*)[n] to struct my_structure*. Check the return value of scanf and also check the value n (n>1).
You can do it on your way also:(Illustration on the users code)
struct my_structure (*ptr)[n] = &variable;
for(i=0;i<n;i++)
{
scanf("%s",(*ptr)[i].name);
scanf("%d",&((*ptr)[i].number));
scanf("%d",&((*ptr)[i].rank));
}
...
printf("%s",(*ptr)[i].name);
printf("%d",((*ptr)[i].number));
Correct way to use scanf would be:-(Notice that here 19 is used - otherwise there is a chance of buffer overrun - and this is being checked using this.This is one less than the size of the array because of the \0 character ) (Correct way)
if(scanf("%19s",ptr[i].name) != 1){
/* error in input */
fprintf(stderr,"Error in input\n");
exit(EXIT_FAILURE);
}
Compile your program with all warnings enabled. gcc -Wall -Werror progname.c.
Clearly you don't even need to use this pointer - why would you do that? You can simply use the array itself in the scanf or printf.

How to reset allocated memory and resources in c?

My program consists of a Menu, where you can select 1 of 2 options.
The second is just to exit the program. The first, however, is where you can find a specific sequence of bits that you choose, in a separate ".txt" file with 100.000 lines.
It does what I want the first time, and then returns to the Menu.
The problem is when the user goes for a second (or more) search. The program prints on screen random information.
It seems like I didn't do a "reset" of the resources, memory or values on the first search.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char ID[8];
char content[2048];
int distance;
} DATA;
void search(){
FILE *f;
DADO *z=NULL;
long int tot=0;
int a;
int c;
int i;
int j=1;
int k=0;
char e;
char b[2048];
printf("\n");
f=fopen("DANGER_DB_LARGE.txt", "r");
printf("\n");
printf("How many results do you wish?\n");
scanf("%d",&a);
printf("Introduce the sequence:\n");
scanf("%s",b);
c=strlen(b);
printf("\n");
z=(DATA*)realloc(z,(++tot)*sizeof(DATA));
while(e!=EOF){
e=fgetc(f);
if(k<8){
z[tot-1].ID[k]=e;
}
else if(k==8 && e=='\t'){
continue;
}
else if(k>=9 && e!='\n'){
z[tot-1].content[k-9]=e;
}
else if(e=='\n'){
k=(-1);
z=(DATA*)realloc(z,(++tot)*sizeof(DATA));
}
k++;
}
for(i=1; i<=tot; i++){
distance(z,i,c,b);
}
free(z);
fclose(f);
}
I proceed to store the ID and content of every single one of those 100.000 lines of text. I end the function by doing free(z), but when I search again the program just prints random stuff.
Use of uninitialised variables without an intervening assignment is undefined behaviour. It may work on the first Wednesday of every month, on the first time through the loop, only when the boss is looking, ...
int e; // originally was char
//...
while (e != EOF) { // uninitialised, no intervening assignment
Realloc returns void by the way
void *realloc(void *ptr, size_t size)
plus it takes a pointer as input so its pass by reference.
update: This function returns a pointer to the newly allocated memory, or NULL if the request fails.
my bad.

Program with array of structs crashes

I have an array with multiple structs. When i ask the user to enter data the first time everything works but when i ask again for the next position in the array the program crashes. If this method doesn't work souldn't the program crash in the beginning? Is something wrong with malloc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
void init(int n)
{
stack = malloc(n);
}
int push(struct student_or_prof **pinx,int *head,int n)
{
char name[50];
printf("\nn= %d\n",n);
printf("\nhead= %d\n",*head);
if(*head==n)
{
printf("Stack is full.\n");
return 1;
}
char x;
printf("Student or Professor? [s/p] ");
getchar() != '\n';
scanf("%c",&x);
if(x=='s')
{
getchar() != '\n';
pinx[*head]->flag = 0;
printf("\n\nGive student's name: ");
fgets(pinx[*head]->student.name,sizeof(pinx[*head]->student.name),stdin);
printf("\nGive student's semester: ");
scanf("%d",&(pinx[*head]->student.semester));
printf("\nName = %s\tSemester = %d",pinx[*head]->student.name,pinx[*head]->student.semester);
}
else if(x=='p')
{
getchar() != '\n';
pinx[*head]->flag = 1;
printf("\n\nGive professor's name: ");
fgets(pinx[*head]->prof.name,sizeof(pinx[*head]->prof.name),stdin);
printf("\nGive course: ");
fgets(pinx[*head]->prof.course,sizeof(pinx[*head]->prof.course),stdin);
printf("\nName = %s\tCourse = %s\n",pinx[*head]->prof.name,pinx[*head]->prof.course);
}
(*head)++;
printf("\nhead= %d\n",*head);
}
int main()
{
int n,i;
printf("Give size: ");
scanf("%d",&n);
init(n);
for(i=0;i<n;i++)
push(&stack,&exp1.head,n);
return 0;
}
You need to malloc the structure not n
malloc(sizeof(struct student_or_prof)*n)
EDIT:
And your code crashes again because pinx is a double pointer, so this operation is not valid:
pinx[*head]->flag = 0;
this is equivalent to:
*(pinx + *head)->flag = 0;
Since you are not changing what stack points to, you are better off using a single pointer instead of a double pointer.
So instead you should change your push API:
int push(struct student_or_prof *pinx,int *head,int n)
and call it like:
push(stack,&exp1.head,n);
malloc allocates the given number of bytes.
You have to multiply n with the size of your struct, to allocate enough memory.
pinx does not point to an array, so pinx[*head] is going to access invalid memory unless *head is zero.
I think you meant (*pinx)[*head] , which accesses the N-th element of the array you allocated via malloc. For example (*pinx)[*head].prof.name etc.
BTW, your head number doesn't seem to be used at all, except for exp1.head, maybe it'd be better to remove head from the struct, and just have a single variable head?

Issues with passing structures into functions

I have several years of experience with java, but I'm very new to C. I'm still struggling to figure out when and when not to use pointers. I was given this base code and need to finish the 'push' method so that it pushes the next element onto the stack, but I'm getting errors saying:
request for member 'top' in something not a structure.
#include <assert.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
int exit_status = EXIT_SUCCESS;
#define EMPTY (-1)
#define SIZE 16
typedef struct stack stack;
struct stack {
int top;
double numbers[SIZE];
};
void push (stack *the_stack, double number) {
if(&&the_stack.top>=SIZE-1){
printf("error");
}else{
the_stack.numbers[&&the_stack.top++ ] = number;
}
}
int main (int argc, char **argv) {
if (argc != 1) {
fprintf (stderr, "Usage: %s\n", basename (argv[0]));
fflush (NULL);
exit (EXIT_FAILURE);
}
stack the_stack;
the_stack.top = EMPTY;
char buffer[1024];
for (;;) {
int scanrc = scanf ("%1023s", buffer);
if (scanrc == EOF) break;
assert (scanrc == 1);
if (buffer[0] == '#') {
scanrc = scanf ("%1023[^\n]", buffer);
continue;
}
char *endptr;
double number = strtod (buffer, &endptr);
if (*endptr == '\0') {
push (&the_stack, number);
}else if (buffer[1] != '\0') {
bad_operator (buffer);
}else {
do_operator (&the_stack, buffer);
}
}
return exit_status;
}
Am I overlooking something very basic?
When accessing members of a structure, there are two operators: The dot operator . which is used for non-pointer structures, and the "arrow" operator -> which is used for pointers to structures.
You have a pointer to a structure in your push function, so you need to use the "arrow" operator.
There are other problems with your code, like the double ampersand in the push function. You also don't need to flush any files when exiting the program, the runtime will do that for you.
It seems very clearly that you have less experience in C. There are lots of compile time errors in your code like for example :
In push function top and numbers should be invoked as :
the_stack->top
the_stack->numbers[]
An arrow is used to invoke the members of a pointer variable.
Now Comparing it with Java:
Java uses only references not pointers. But internally they are pointing to some location in memory.
https://www.dropbox.com/s/qfk86yb3drdlmz2/C%20to%20Java.JPG Image
http://erikdemaine.org/papers/CPE98/paper.pdf Paper
Check this link to correlate C code and Java code.

Resources