C- Character Push and Pop operation [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Stack create(int c)
{
Stack S=(Stack)malloc(sizeof(struct stack));
S->size=c;
S->top=-1;
S->array=(char *)malloc(sizeof(char)*c);
return S;
}
Stack makeEmpty(void)
{
Stack *S1=create(100);
S1[0]->top=-1;
return S1;
}
char pop(Stack S)
{
return S->array[S->top--];
};
int main(void)
{
Stack *S1;
S1=makeEmpty();
int j;
int k=0;
char result[30];
for(j=0; j<2; j++)
{
char result1=pop(S1);
strcat(result, result1);
k++;
}
}
I skipped some parts, like typedef struct stack Stack;
What I wanted to do was pop out elements from the stack while for-loop works. Then, store those elements in a new array which is result. To check whether it works or not, I printed out but I had a runtime error. How to store the element and how to print it out?

I've made copy&paste of your code, and it doesn't get compiled. I think that
you are either not posting your actually code nor you don't bother to compile and read the compiler warnings. It's rather difficult to help you. Here some things I noticed:
1.
create must return a pointer to Stack, not the object.
Stack *create(int c)
{
Stack *S = malloc(sizeof *S);
S->size=c;
S->top=-1;
S->array = malloc(c);
return S;
}
2.
Same goes for makeEmpty
Stack *makeEmpty(void)
{
Stack *S1=create(100);
S1->top=-1;
return S1;
}
3.
pop should get a pointer to Stack, not the object
char pop(Stack *S)
{
return S->array[S->top--];
};
Here you should check whether there are elements on your stack. int pop(Stack *S, char *val) where it returns 1 and writes on *val on
success, and returns 0 otherwise would be better.
4.
Judging from your pop you are pushing char only. I don't get what you
are trying to do with strcat. Either way, you are doing strcat wrong. You
are declaring a stack with 100 spaces, but you are only declaring 30 spaces
for result. What if you have more than 31 elements on your stack? I know
that you are only inspecting 2 elements but it's easy to overlook that and
expand it to go through all the stack without changing the memory requirements
for result.
Also strcat is a function that works with C-Strings, that means it expects
C-Strings. A C-String must be \0 terminated, yours are not. You have
something that looks like a C-String but it's not. If you insist on using
strcat, the you should do it like this:
for(j=0; j<2; j++)
{
char result1[] = { pop(S1), 0 };
strcat(result, result1);
}

Related

best way to write a function to return an array of String with limited size (char *x[MAX] vs char **x)? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
What is the best way to write a function to return an array of String.
I use the following function:
void getOperatorNames(char *names[]) {
int i=0;
for(; i<MAX_OPERATORS; i++) {
names[i] = malloc(64 * sizeof(char));
strcpy(names[i], op[i].fname);
}
}
and call it :
char *MenuItems[MAX_OPERATORS];
getOperatorNames(MenuItems);
But when I use MenuItems in a function with argument char ** it rises an exception and I don't know what is the cause.
What is the difference between char *x[] and char **x? IMO they must be equal!!
EDITTED:
struct operator{
int id;
char fname[32];
char ename[32];
};
struct operator op[MAX_OPERATORS];
the operators is filled by random text.
One way is to pack the array and its size together in a super-struct, and avoid the nasty-sized functions arguments:
#include <stdio.h>
#include <stdlib.h>
#define MAX_OPERATORS 666
struct operators {
unsigned count;
struct operator{
int id;
char fname[32];
char ename[32];
} ops[MAX_OPERATORS];
} ;
struct operators * getops(void)
{
struct operators *ret;
unsigned uu;
ret = malloc (sizeof *ret);
if (!ret) return ret;
ret->count = MAX_OPERATORS;
for(uu=0; uu < ret->count; uu++) {
ret->ops[uu].id= uu;
sprintf(ret->ops[uu].fname, "f%2u", uu);
sprintf(ret->ops[uu].ename, "e%2u", uu);
}
return ret;
}
This is only the beginning, you can lateron make the array variable-sized (using malloc, or a VLA), but the interface would stay the same, and the caller would not need to know the value of MAX_OPERATORS, it only needs the ->count structure element. You could also reuse it for other tables, using different counts.

How to remove duplicates from stack? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
TASK: Let's say there is an integer stack S with M elements. Give the algorithm that will remove all those numbers from stack S that appear two or more times. (write the task using C/C++)
NOTE: We are not allowed to use std::stack to solve this task.
First of all I decided to use C language, and this is stack implementation I use.
int* stack = (int*)malloc(10 * sizeof(int));
int size = 10;
int sp = -1;
bool isempty() {
return (sp == -1);
}
bool isfull() {
return (sp == size - 1);
}
void push(int x) {
if (isfull()) {
printf("Full!");
}
else {
sp++;
stack[sp] = x;
}
}
int pop() {
int x;
if (isempty()) {
printf("Empty!");
}
else {
x = stack[sp];
sp--;
}
return x;
}
void peek() {
if (!isempty()) {
printf("%d", stack[sp]);
}
}
void clear() {
while (!isempty()) {
pop();
}
}
void print() {
if (!isempty()) {
for (int i = 0; i < sp+1; i++) {
printf("%d ", stack[i]);
}
}
printf("\n");
}
My idea of solving this task was to make another temp stack and copy main stack into it, than use two for loops to compare all elements and inside that I used if statment to check if they are same or not, if they are not same I just pushed them into back into stack that was previously cleared, by this way I'm supposed to skip all duplicate elements but for some reason this code is not working properly it keeps spamming me "Full!" message.
void removeDuplicates() {
int* temp = (int*)malloc(10 * sizeof(int));
int temp_size = 10;
int temp_sp = -1;
for (int i = 0; i < sp + 1; i++) {
temp[i] = stack[i];
}
temp_sp = sp;
clear();
for (int i = 0; i < temp_sp+1; i++) {
for (int j = i + 1; j < temp_sp+1; i++) {
if (!(temp[i] == temp[j])) {
push(temp[i]);
}
}
}
}
This is main function that I used to test out functions:
int main() {
push(1);
push(2);
push(3);
push(4);
push(3);
push(5);
removeDuplicates();
print();
return 0;
}
If there is simpler way to solve this by using C++ (not std::stack), let me know.
this code that is supposed to work for normal array, but not sure if it's right for stack as we might using dynamic memory
Whether your code is correct for stacks is nothing to do with dynamic allocation, and everything to do with the interface of a stack. Do you know what that is? It's absolutely essential to solving your problem, and I don't see any hint that you either know how a stack behaves, or tried to research it.
Here you are, the stack abstract datatype:
preserves last-in first-out order
allows you to push a new element onto the top of the stack
allows you to pop the most recently pushed element (that wasn't already popped) from the top of the stack.
That's everything, and there is no random access (ie, stack[j] will never be a valid expression), so it is obviously impossible for the algorithm you showed to work.
If you don't have a stack implementation already - write one! You're going to need a stack to compile and test your algorithm anyway. The definitions you show describe the storage, but not the interface.
There are only two functions to code (plus the two to create and destroy a stack, and optionally one to query the size).
Now for the algorithm - you can only ever access the top element of a stack, so you need to think about what to with the elements you pop that aren't duplicates. They have to go somewhere, because you can't see below them while they're on your main stack, and you mustn't lose them.
Your edit shows you do have a stack datatype, sort of: it uses three global variables which you have to take care not to break, and you can't reuse any of the functions for your temporary stack, because they operate on those globals.
Even in C, I'd expect to see something like this (untested, un-compiled sample code based on yours above)
struct Stack {
int size;
int sp;
int data[];
};
struct Stack* stack_create(int elements) {
struct Stack *s = malloc(sizeof(*s) + elements * sizeof(int));
s->size = elements;
s->sp = -1;
return s;
}
bool stack_isEmpty(struct Stack *s) { return s->sp == -1; }
bool stack_isFull(struct Stack *s) { return s->sp == s->size - 1; }
void stack_push(struct Stack *s, int x)
{
assert(!stack_isFull(s));
s->data[++s->sp] = x;
}
int stack_pop(struct Stack *s)
{
assert(!stack_isEmpty(s));
return s->data[(s->sp)--];
}
because then you can use the same operations on your main and temporary stacks.
If the removeDuplicates message is supposed to be implemented in terms of the stack abstraction, you need an algorithm you can implement in terms of stack_push, stack_pop etc.
If the removeDuplicates message is supposed to be an internal function operating directly on the stack implementation, rather than being implemented in terms of the stack abstraction - then your basic approach is probably OK (if very far from optimal), and you just need to learn to debug your code.
I still don't know which one of those is true (so I won't vote to re-open yet), but they are completely different questions.
I see a few problems with your current code:
In the loop
for (k = j; k < size; k++)
{
stack[k] = stack[k + 1];
}
you go out of bounds because you use stack[k+1]. How would you fix that?
But then after you have moved all the elements down by 1, the new stack[j] may be another duplicate of stack[i]. How would you fix that? You might consider using a while loop.
You use a global variable size which is the stack size. But there is also a variable sp that is the stack pointer and indicates the part of the stack in use. So instead of looping over size you should loop over sp.
Note what the stack pointer points at: the value -1 means stack empty, so any other value points at the current value at the top of the stack. (This is important beause the other interpretation of the stack pointer is that it points at the next free element of the stack.)
This sp of course decreases with every duplicate you remove from the stack.

Stack smashing detected, core dumped [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
#include<stdio.h>
#define MAXSIZE 10
#define OK 1
#define NOK 0
int check_validity(int);
void input_array_elements(int,int *);
void Display_array_elements(int,int *);
int main()
{
int array[MAXSIZE];
int i,num,negative_sum=0,positive_sum=0;
float total=0.0,average;
printf("Enter the value of N\n");
scanf("%d",&num);
while(1)
{
int Return_val;
Return_val=check_validity(num);
if(Return_val == OK)
{
printf("sizeof array=%d\n",sizeof(array));
break;
}
else
{
printf("please enter a value <= 10\n");
scanf("%d",&num);
}
}
input_array_elements(num,&array[MAXSIZE]);
Display_array_elements(num,&array[MAXSIZE]);
}
int check_validity(int num)
{
if(num<MAXSIZE)
{
printf("OK\n");
return OK;
}
else
{
printf("NOK\n");
return NOK;
}
}
void input_array_elements(int num,int *array)
{
int i;
for(i=0;i<num;i++)
{
scanf("%d",&array[i]);
}
}
void Display_array_elements(int num,int *array)
{
int i;
for(i=0;i<num;i++)
{
printf("array[%d]=%d\n",i,array[i]);
}
}
What is "stack smashing"? How to solve this problem?
I'm compiling my program and I'm having error:
* stack smashing detected *: ./a.out terminated Segmentation fault (core dumped)
I don't know what I'm doing wrong.
The pointer to &array[MAXSIZE] is a pointer to one beyond the end of the array. That means your functions will start out of bounds of the array which leads to undefined behavior. The system detects is as a "stack smash" and crashes your program.
If you want to pass a pointer to the first element then use either &array[0], or plain array (as that will decay to &array[0]).
Segmentation fault (or stack smashing as you are getting) happens when you try to access a memory that is not accessible to your program or process.
In your function Display_array_elements I guess you are trying to print the array elements. The second argument should provide the address to the beginning of the array.
By passing &array[MAXSIZE] you are already pointing to the last element and then trying to access the other elements on this array, which is beyond valid array bounds. This is the reason for segmentation fault.
Change this call to one of the below
Display_array_elements(num,&array[0]);
OR
Display_array_elements(num,array);
Segmentation error comes when allocated memory space exceeds by a variable. Once variable declared, amount of memory is allocated in the stack.
Your array causing the problem. Hence array is defined to a particular size, next insertions going above the space and try to access the space of onother variable/ instruction.

qsort not working c program [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I am trying to sort an array of names via qsort.
This is my code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int myCompare (const void * a, const void * b ) {
return *(char*)a - *(char*)b;
}
int main(void) {
int i;
char fileArr[] = {"inputbv", "inputa","inputzef",};
int stringLen = sizeof(fileArr) / sizeof(char *);
qsort(fileArr, stringLen, sizeof(char *), myCompare);
for (i=0; i<stringLen; ++i)
printf("%d: %s\n", i, fileArr[i]);
}
This code doesn't print anything at the end. It just ends so it seems like it deletes the entries in the char array
First off, you're missing a *:
char *fileArr[] = {"inputbv", "inputa","inputzef",};
This doesn't explain why you're not sorting correctly, which is a different issue, but it does explain why you're getting no output. (A validating compiler, like gcc -Wall, would have told you that that declaration is invalid without that missing star.)
There are a number of other issues here, though. First off, as one of the commenters alluded to, the myCompare() function is declared with the right type, but it doesn't quite do what you think it does:
int myCompare(const void *a, const void *b)
{
...
}
That's because qsort() passes the address to each chunk of data, not the chunk of data itself. The chunks of data in this case are pointers to character arrays, so qsort() is going to pass pointers to pointers to your comparison function. Those aren't single stars there; they're actually two stars in disguise.
Secondly, comparing pointers does you no good: The pointers are, almost by definition, random values. Your comparison function, as written, even if you corrected it for the number of *'s that are supposed to be there, would still be wrong:
/* Don't do this. */
return *(char **)a - *(char **)b;
That's literally more-or-less "sort by the random locations of these strings in memory," which doesn't help you at all for putting them in order.
The right thing to do is not to add yet another star (writing **(char **)a - **(char **)b literally means "compare the first characters against each other"). The right thing to do is invoke strcmp() to compare the two strings lexically:
int myCompare(const void *a, const void *b)
{
return strcmp(*(char **)a, *(char **)b);
}
That's what you should be using.

sort an array of strings in alphabetical in c [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
i have a linked list of srtings that i need to sort in alphabetical order
and i am tryping to copy the strings to an array and then sort and print them in alphabetical order
void DisplayAll(k *l,p *p)
{
int i,j;
p *temp;
temp = malloc(l->num*sizeof *temp);
for (i = 0; i < l->num; i++)
{
strcpy_s(temp[i].name, 20, p->name);
p = p->next;
i++;
}
for (i = 0; i < l->num - 1; i++){
for (j = i + 1; j< l->num; j++)
{
if (strcmp(temp[i].name, temp[j].name) > 0)
{
strcpy_s(temp->name,20, temp[i].name);
strcpy_s(temp->name[i],20, temp[j].name);
strcpy_s(temp->name[j],20, temp->name);
}
}
for (i = 0; i < l->num-1; i++){
printf("%s\n", temp[i].name);
}
}
this is the k struct and the p stuct
typedef struct p
{
char name[20];
struct p* next;
}p;
typedef struct k
{
int num;
p *head;
}k;
and i getting an Error evey time i run it
There's a couple of problems with your code:
First off: This doesn't look right at all:
strcpy_s(temp->name,20, temp[i].name);
strcpy_s(temp->name[i],20, temp[j].name);
strcpy_s(temp->name[j],20, temp->name);
according to the docs:
errno_t strcpy_s(
char *strDestination,
size_t numberOfElements,
const char *strSource
);
The first and last arguments are expected to be of the type char*. You've defined struct p .name as char[20], so temp->name[i] will be of type char.
I guess you're actually trying to do something like this:
//get struct p at offset i in temp, access member "name"
strcpy_s(temp[i].name, 20, temp[j].name);
Secondly: You're allocating memory for temp, but you fail to free it once you're done (ie when your function returns). You have, in other words, a memory leak. Sure, once your program exits, the memory is almost certainly going to be freed, but if you're writing programs that have to run for extended periods of time, and functions like this are getting called several times over, your memory consumption will gradually increase, and you don't want that to happen. In short, after your last loop (where you print everything out), add this:
free(temp);
Edit
You've added the free call now, and -correctly- wrap it in an if (temp). However: if malloc had returned a NULL pointer, don't you think you should've cought that at the beginning of the function?
temp = malloc(l->num * sizeof *temp);
if (!temp)
return;//or return int to indicate error or or exit EXIT_FAILURE; or something
There's no reason for you to reach the point where you free(temp) without having successfully allocated the memory.
Third: As #Bluepixy pointed out in his comment, there's a syntax error, too: the if (strcmp(temp[i].name, temp[j].name) > 0) branch is never closed properly: you're missing a closing bracket after the third strcpy_s call.
Lastly, you're allocating enough memory to accomodate l->num structs. You initialize them in such a way that every other struct will be assigned the name member of the next struct p in a list. You're not really making sure that p->next isn't a null pointer. This could cause problems (dereferencing a null pointer). So change the first loop into something like this:
int l_num = l->num;//you'll see why
for (i = 0; i < l_num; i+=2)//increment twice if you want/need to
{
strcpy_s(temp[i].name, 20, p->name);
p = p->next;
if (p == NULL)
{
l_num = i+1;//this is as far as we ought to go in the subsequent loops
break;//or handle error in some way
}
}
After this, replace all your ;i < l->num; conditions in your loops with i < l_num or j < l_num to avoid using uninitialized string values.
Just a final tip: If you're not working on anything too time critical, it might be useful to use calloc instead of malloc, especially when dealing with strings, or use memset(temp[i]->name, 0, 20); to ensure all char[] members are indeed empty strings.
If you find yourself using a lot of str* functions (strncat, strncpy and the like), even something as simple as temp[i]->name[0] = '\0'; can make life a lot easier.

Resources