I'm trying to store a string in a linked list, but for some reason, I keep getting segmentaion fault error.
I've tried everything, and I feel I'm missing something really stupid and easy, please any thoughts?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 60
typedef struct Node
{
char *getInput;
struct Node *next;
} Node;
typedef struct list
{
Node *head;
} list;
void readText(Node **a)
{
char c;
int i = 0;
while ((c = getchar()) != EOF)
(*a)->getInput[i++] = c;
}
void main()
{
Node *b;
b->getInput = (char *)calloc(SIZE, sizeof(char));
if (b == NULL)
{
printf("sadsa");
exit(1);
}
readText(&b);
printf("%s", b->getInput);
}
You mave to allocate a valid region and assign to b before dereferencing that.
Also checking if b is not NULL must be taken place before dereferencing.
You should use standard int main(void) in hosted environment instead of void main(), which is illegal in C89 and implementation-defined in C99 or later, unless you have some special reason to use non-standard signature.
getchar() returns int, so the return value should be assigned to an int variable. Otherwise, it will be difficult to distinguish between a valid character and EOF.
You should terminate strings by adding terminating null-character before using that for %s. (In this case it is not necessary because the buffer is initialized to zero via calloc(), but this will improve safety for another usage of the function)
void readText(Node **a)
{
int c; /* use proper type */
int i = 0;
while ((c = getchar()) != EOF)
(*a)->getInput[i++] = c;
(*a)->getInput[i] = '\0'; /* terminate the string */
}
int main(void) /* use standard signature */
{
Node *b = malloc(sizeof(*b)); /* allocate buffer */
if (b == NULL) /* check if allocation is successful before dereferencing */
{
printf("sadsa");
exit(1);
}
b->getInput = (char *)calloc(SIZE, sizeof(char));
readText(&b);
printf("%s", b->getInput);
}
Related
I'm writing a code to convert postfix to infix. but when i try to print the stack elements to check it it's not showing any thing. in the push function it prints the top element, but the display function only shows the top element no matter what. and there is segmentation fault after the line strcat(nn,y).The input i tried was 09+.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX 20
char *stk[MAX], a[MAX];
int t = -1;
void push(char x[]);
void pop();
void display();
int main()
{
int i = 0;
char *x, *y, nn[MAX];
printf("enter expression:");
gets(a);
while (a[i] != '\0')
{
if (isdigit(a[i]))
{
push((char [2]){ a[i], '\0' });
}
else
{
display();
pop();
x = stk[t];
pop();
y = stk[t];
strcpy(nn, "");
strcat(nn, "(");
strcat(nn, y);
strcat(nn, (char [2]){ a[i], '\0' });
strcat(nn, x);
strcat(nn, ")");
push(nn);
}
i++;
}
printf("%s", stk[0]);
}
void push(char x[])
{
t = t + 1;
stk[t] = x;
printf("curtop %d:%s\n", t, stk[t]);
}
void pop()
{
t = t - 1;
}
void display()
{
printf("%s:%s", stk[t], stk[t - 1]);
}
I will reiterate the comments, with some references, and add a few thoughts of my own.
The first thing you should do is read Why is the gets function so dangerous that it should not be used? gets was removed from language in C11, any halfway modern tool chain should not include it:
example.c:5:9: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
fgets is the suggested replacement. Use it.
Both compound literals
(char [2]){ a[i], '\0' }
occur at block scope, and thus have automatic storage duration. This means the lifetime of each object ends when their respective enclosing blocks end.
As such, you are pushing a soon-to-be dangling pointer on to the stack.
This is an example of Undefined Behaviour.
The following
push(nn);
repeatedly pushes the same pointer to the first element of nn on to the stack. This pointer value is always the same, and always points to the current contents of the array, which is constantly being changed.
Both these problems are solved by using dynamic memory to create copies of the strings pushed on to the stack.
nn (infix expression buffer) has the same size as a (postfix expression buffer), with both being much too small.
Remembering that to store a string in a buffer, the size of the buffer must be at least the length of the string plus one (for the null terminating byte).
The postfix expression
09+6+10*+63-/
has a string length of 13, which fits in a. With your parenthesis rules, this creates the infix expression
((((0+9)+6)+(1*0))/(6-3))
which has a string length of 25. This does not fit in nn, and strcat does nothing to guard against buffer overflows.
This would be another example of Undefined Behaviour.
As a quick point of design
pop();
x = stk[t];
is clumsy.
While the use of file scope variables (globals) and functions that wrap around them is a very common way data structures are introduced to beginners, you should still aim to implement something closer to an abstract data type.
pop should return the topmost element of the stack, and you as a user of the pop function should not care how that is managed, just that it behaves as expected.
char *x = pop();
The next step is to remove the file scope variables, so that more than one stack can exist in your programs at the same time.
Here is a cursory example program that addresses most of the issues discussed. Note that it parses input slightly differently, using whitespace as a delimiter. It follows your rules for parenthesis.
It does not validate operands or the resulting expression. Operands can be longer than a single character.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 256
#define SEP " \r\n"
#define STACK_INIT { 0 }
#define STACK_MAX 64
struct stack {
size_t height;
char *data[STACK_MAX];
};
size_t count(struct stack *s)
{
return s->height;
}
int push(struct stack *s, const char *item)
{
if (s->height >= STACK_MAX)
return 0;
char *copy = malloc(1 + strlen(item));
if (!copy)
return 0;
strcpy(copy, item);
s->data[s->height++] = copy;
return 1;
}
char *pop(struct stack *s)
{
return s->height ? s->data[--s->height] : NULL;
}
void free_stack(struct stack *s)
{
char *item;
while ((item = pop(s)))
free(item);
}
int main(void)
{
char buffer[BUF_SIZE];
printf("enter expression: ");
fflush(stdout);
if (!fgets(buffer, sizeof buffer, stdin)) {
if (ferror(stdin))
perror("reading stdin");
return EXIT_FAILURE;
}
struct stack tokens = STACK_INIT;
char *tok = strtok(buffer, SEP);
while (tok) {
char expr[BUF_SIZE * 2];
/* is the first and only character an operator? */
int is_op = strchr("+-/*", *tok) && !tok[1];
if (is_op) {
if (count(&tokens) < 2) {
fprintf(stderr, "Operator (%c) needs two operands.\n", *tok);
free_stack(&tokens);
return EXIT_FAILURE;
}
char *rhs = pop(&tokens);
char *lhs = pop(&tokens);
if (snprintf(expr, sizeof expr, "(%s %c %s)", lhs, *tok, rhs) >= sizeof expr)
fprintf(stderr, "Warning: expression truncated.\n");
free(rhs);
free(lhs);
}
if (!push(&tokens, is_op ? expr : tok)) {
fprintf(stderr, "Failed to push stack item.\n");
free_stack(&tokens);
return EXIT_FAILURE;
}
tok = strtok(NULL, SEP);
}
for (char *s; (s = pop(&tokens)); free(s))
printf("%s\n", s);
}
So my tutor asked me to acquire an integer for a data struct , but 2 of the int parts im supposed to get , is via gets , im thinking he meant me to use gets(temp) // temp stand for char temp[50] and then perform x=strlen(temp);
here is my work so far :
#include<stdio.h>
#include<conio.h>
#include<string.h>
#define N 20
struct one
{
int ak;
char pin[N];
};
struct two
{
int data,mat[N];
struct one melos,item;
};
int main(void)
{
bool x=true;
int i;
char temp[N];
struct one person;
struct two memb;
/*GETTING VARS*/
gets(person.pin);
gets(memb.item.pin);
gets(memb.melos.pin);
person.ak=(int)gets(temp);
memb.data=(int)gets(temp);
for(i=0;i<N;i++)
scanf("%d",&memb.mat[i]);
scanf("%d",&memb.melos.ak);
scanf("%d",&memb.item.ak);
putchar('\n');
/*CHECKING VARS*/
puts("Posting vars in Data Struct ""one"" \n");
printf("%d\n",person.ak);
puts(person.pin);
puts("Posting vars in Data Struct ""two"" \n");
printf("%d\n",memb.data);
putchar('\n');
for(i=0;i<N;i++)
printf("%d\t",memb.mat[i]);
printf("\n%d\n",memb.melos.ak);
puts(memb.melos.pin);
printf("%d\n",memb.item.ak);
puts(memb.item.pin);
puts("**********************\n---POST_END---");
return 1;
}
The return value of gets() is the pointer to the buffer passed if successful, and NULL if failed. It won't mean the integer read.
Also note that you shouldn't use gets(), which has unavoidable risk of buffer overrun.
You will have to convert the string read to integer.
Try this:
#include<stdio.h>
#include<stdlib.h> /* for using atoi() */
#include<string.h>
#define N 20
/* read one line while checking the size read */
char* safer_gets(char* outbuf, size_t max){
size_t idx = 0;
int input;
if(max == 0) return NULL;
while(idx + 1 < max && (input = getchar()) != EOF && input != '\n'){
outbuf[idx++] = input;
}
if (idx == 0 && input == EOF) return NULL;
outbuf[idx] = '\0';
return outbuf;
}
/* read one line and convert it to integer */
int get_int(void) {
char temp[N];
safer_gets(temp, sizeof(temp));
return atoi(temp);
}
struct one
{
int ak;
char pin[N];
};
struct two
{
int data,mat[N];
struct one melos,item;
};
int main(void)
{
int i;
struct one person;
struct two memb;
/*GETTING VARS*/
safer_gets(person.pin, sizeof(person.pin));
safer_gets(memb.item.pin, sizeof(memb.item.pin));
safer_gets(memb.melos.pin, sizeof(memb.melos.pin));
person.ak=get_int();
memb.data=get_int();
/* latter part omitted */
}
Avoid gets - I'm surprised your class mentions it because it's been removed from all of the recent C language specifications and now deprecated in C++11.
But if you must...
http://www.cplusplus.com/reference/cstdio/gets/
long int getIntegerWithGetS() {
char* end;
char* buffer = calloc( 1024, sizeof(char) ); // 1024 bytes should be enough
long int result;
bool got_result_yet = false;
while( !got_result_yet ) {
gets( buffer ); // DANGER WILL ROBINSON
result = strtol( buffer, &end, 10 );
if( result == 0 ) {
if( end != buffer ) {
result = 0;
got_result_yet = true;
}
} else {
if( result != LONG_MAX && result != LONG_MIN && errno != ERANGE ) got_result_yet = true;
}
}
free(buffer);
return result;
}
Note how I call my code in a loop so we will persist until we get valid input from the user. I start off calling gets (to fill the buffer), then using strtol to convert the human-readable text in buffer to an actual computer int value - note that strtol is more powerful than atoi and uses long int instead of int as its declared type. Then the code checks for the strtol error conditions (in case a user types in "0" when the function returns 0 on failure anyway).
I don't return immediately, because the buffer must be free'd before execution leaves the scope, otherwise that buffer will remain unallocated and so leaked.
I am learning pointer in c
i have written a small program , but i am getting segmentaion fault
i dont know where i am having the issue
please let me know the issue with the code , it is an array of pointers to string ,
which is in a pointer to structure .
# include <stdio.h>
#include <stdlib.h>
# include <string.h>
char *sum(char **sol) ;
char *summer_sum(char*** solcs) ;
int main()
{
char* datum ="teststring";
sum(&datum);
}
char *sum(char** sol)
{
printf("\n value is : %s",*sol);
summer_sum(&sol);
return "1" ;
}
char *summer_sum(char*** solcs)
{
int i=0;
typedef struct
{
char *asg[40];
}nlist;
nlist *n1;
for( i=0 ; i<= 38 ;i++)
{
n1->asg[i] = calloc(1,1*sizeof(*solcs));
strcpy(n1->asg[i],**solcs);
printf("\n %d value is : %s",i,n1->asg[i]);
}
return NULL;
}
n1 is used uninitialized:
n1->asg[i] = calloc(1,1*sizeof(*solcs));
On the other hand, if you want to allocate enough space for the use of strcpy, you must use strlen instead of sizeof
And you don't need a double or triple pointer, your code simplified:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sum(char *sol);
char *summer_sum(char *solcs);
int main(void)
{
char *datum = "teststring";
sum(datum);
}
void sum(char *sol)
{
printf("\n value is : %s", sol);
summer_sum(sol);
}
char *summer_sum(char *solcs)
{
int i = 0;
size_t len;
typedef struct {
char *asg[40];
} nlist;
nlist *n1 = malloc(sizeof(*n1));
if (n1 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
len = strlen(solcs); /* No need to compute len on each iteration */
for (i = 0; i <= 38; i++) { /* you are filling 39 and declared 40 */
n1->asg[i] = calloc(1, len);
/* Always check the result of (m/c/re)alloc */
if (n1->asg[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(n1->asg[i], solcs);
printf("\n %d value is : %s", i, n1->asg[i]);
/* Don't forget to free */
free(n1->asg[i]);
}
free(n1);
return NULL;
}
Before using n1->... You will have allocate memory to n1 as well using calloc()
There are two problems which involves dynamic memory allocation in your code:
n1 is not initialized, you should add a statement like n1 = malloc(sizeof(*n1)); before the for statement in summer_sum()
you did not allocate enough space for each asg[i], you should allocate spaces for these asg[i] by n1->asg[i] = malloc(strlen(**solcs) + 1);
You are using your pointer n1 uninitialized. Your program invokes undefined behavior. In such case you may get either expected or unexpected result.
Second, you are missing a closing brace } in function summer_sum.
Here I'm taking a sentence a checking if it is a palindrome or not.I'm doing this in the process of learning stacks.
Is there a way i can use pointers instead of char array 'sent' so that the number of input characters need not be constrained to 20 in the following code?
The code is working fine, but should there be any improvements in terms of performance or anything else?
is there anything important about pointers i should remember while using stacks, like initializing it to NULL?
Thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node
{
char data;
struct node *link;
}StackNode;
void insertData(StackNode **);
void push(StackNode **, char);
void checkData(StackNode **);
bool pop(StackNode **,char *);
char sent[20] = "";
void main()
{
StackNode *stackTop;
stackTop = NULL;
insertData(&stackTop);
checkData(&stackTop);
printf("\n");
return;
}
void insertData(StackNode **stackTop)
{
char c;
int len;
printf("Enter the Sentence\n");
while( ( ( c = getchar() ) != '\n'))
{
if( ( ( c>='a' &&c<='z') || (c>='A' && c<='Z')))
{
if((c>='A' && c<='Z'))
{
int rem;
rem = c-'A';
c='a' + rem;
}
push(stackTop,c);
len = strlen(sent);
sent[len++]=c;
sent[len]='\0';
}
}
printf("Letters are %s\n\n",sent);
}
void push(StackNode **stackTop,char c)
{
StackNode *pNew;
pNew = (StackNode*) malloc(sizeof(StackNode));
if(!pNew)
{
printf("Error 100:Out of memory\n");
exit(100);
}
pNew->data = c;
pNew->link = *stackTop;
*stackTop = pNew;
}
void checkData(StackNode **stackTop)
{
char c;
int i=0;
while(pop(stackTop,&c))
{
if( c !=sent[i++])
{
printf("Not palindrome");
return;
}
}
printf("Palindrome");
}
bool pop(StackNode **stackTop,char *c)
{
StackNode *pNew;
pNew = *stackTop;
if(pNew == NULL)
return false;
*c = pNew->data;
*stackTop = pNew->link;
printf("char poped %c\n",*c);
free(pNew);
return true;
}
As far as I know, there is no way to have an "infinite array" or an array with no limitations. However, if you use malloc you can produce a section of memory large enough that you won't need to worry about the limitations as much. I see that later on in the code you have used malloc, so I assume you know how it works. However, I would use something like this;
char * sent = malloc(sizeof(char) * 100);
if(sent == NULL){
printf("OUT OF MEMORY!");
return 1;
}
Where 100 is the buffer size you wish to have. I have used a size up to 10000 and had no problems at runtime, so that may be what you need.
In C, arrays are really pointers to statically allocated memory. It is pretty straightforward to create a pointer to an array, or any element in an array. For example, suppose we have you array char sent[20]. If we wanted to create a pointer that pointed to the exact same memory as sent, we can declare char *sentP = sent. We can now replace any use of sent with sentP. We can even create a pointer to the middle of sent: char *sentMidP = sent + 9. Now, sentMidP[0] is the same as sent[9] and sentMidP[-9] is the same as sent[0].
However, unlike sent, we can change where sentP and sentMidP point (think of sent as a constant pointer char * const, which you can't change). Thus, if you had another array char sent2[100]'. You can set the value ofsentPtosent2. What's cool about this is that you can do it *at runtime*, which effectively means that you can change the size ofsentP` depending on the size of your input.
However, there is no need to limit yourself to statically allocated input. C provides the malloc function (see here) to allocate memory at runtime. Thus, if you don't know the size of your sentence at compile time, but you will know it at runtime (say in a variable called sentenceLength), you can allocate `sentP' like the following.
char *sentP = malloc(sizeof(char) * (sentenceLength + 1)); // Plus one for the NUL termination byte in C strings
if (sentP == NULL) {
fprintf(stderr, "No more memory :(");
exit(EXIT_FAILURE);
}
Note how we now have to handle out-of-memory errors. In general, dynamic allocation introduces more overhead, because there is a possibility that we run out of memory, a requirement that we ensure we only access what was allocated, and a need to release the memory with free once we're done.
When you're done with the sentP pointer, be sure to free it with:
free(sentP);
That's it! You can use the sentP pointer we made in your code, and everything should work great. Good luck!
I'm trying to assign input to a number of structures with an array of pointers, pointing to each allocated structure. I've been attempting to fill one structure and printing it, but keep getting errors and can't find out why. Any ideas?
Thanks for the help.
/* Structure declaration */
struct personCatalog {
char name[50];
char address[50];
char cityState[50];
char zipCode[7];
} ;
//function to fill structures
void getPerson (struct personCatalog *ArrayOfPointers[]);
int main(int argc, const char * argv[])
{
struct personCatalog *pointerArray[51];
getPerson(pointerArray);
}
void getPerson (struct personCatalog *ArrayOfPointers[]){
struct personCatalog *tempPointer;
char stringCollector[512];
int maxNumberOfPeople = 51;
int num = 0;
while ((gets(stringCollector) != NULL) && (num < maxNumberOfPeople)) {
tempPointer = (struct personCatalog *) malloc(sizeof(struct personCatalog));
strcpy(tempPointer->name, stringCollector);
gets(tempPointer->address);
gets(tempPointer->cityState);
gets(tempPointer->zipCode);
ArrayOfPointers[num] = tempPointer;
num++;
printf("%s", ArrayOfPointers[num]->name);
printf("%s", ArrayOfPointers[num]->address);
printf("%s", ArrayOfPointers[num]->cityState);
printf("%s", ArrayOfPointers[num]->zipCode);
}
ArrayOfPointers[num] = '\0';
}
Corrected it a little bit, try it out, but more work to do....
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Structure declaration */
struct personCatalog {
char name[50];
char address[50];
char cityState[50];
char zipCode[7];
} ;
const int maxNumberOfPeople = 3; // was 51;
//function to fill structures
void getPerson (struct personCatalog *ArrayOfPointers[]);
int main(int argc, const char * argv[]) {
struct personCatalog *pointerArray[maxNumberOfPeople];
getPerson(pointerArray);
}
void getPerson (struct personCatalog *ArrayOfPointers[]){
struct personCatalog *tempPointer;
char stringCollector[512];
int num = 0;
while ((num < maxNumberOfPeople) && (gets(stringCollector) != 0) ) {
tempPointer = (struct personCatalog *) malloc(sizeof(struct personCatalog));
strcpy(tempPointer->name, stringCollector);
gets(tempPointer->address);
gets(tempPointer->cityState);
gets(tempPointer->zipCode);
ArrayOfPointers[num] = tempPointer;
printf("name %s\n", ArrayOfPointers[num]->name);
printf("address %s\n", ArrayOfPointers[num]->address);
printf("cityState %s\n", ArrayOfPointers[num]->cityState);
printf("zipCode %s\n", ArrayOfPointers[num]->zipCode);
num++;
}
//ArrayOfPointers[num] = '\0'; this crashed at end of array
}
Interestingly enough the code works for me with the necessary includes added:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
However, this only holds for reasonable input - the code has a bit of room for improvement, but more on that later on.
The reason you don't see any output is that you are incrementing the index num after you assign the data to the struct, but before you print it - i.e. in the loop you are always dereferencing not yet assigned poiter, in other words garbage. It is only a question of time, when you try to dereference a null pointer (or anything not in your process' memory and segfault.
Now for the flaws:
malloc() always comes with two things: a check for return value and a corresponding free()! The free() is missing, but I understand that there are/will be some other parts of code that could take care of that once the data is not needed any-more. However, you are not checking whether it doesn't return NULL (i.e. failed to allocate memory). That would bring your program down immediately (SEGFAULT due to null pointer dereference).
gets() - I suggest reading the manpage for this function (if you are on Windows, look it up on the internet) - it doesn't guarantee any limits for reading data, hence you can easily overflow your buffer. Use fgets() instead. An alternative might be scanf() with width specifier to %s.
strcpy() - the same as for gets(). Use strncpy() instead, unless you are dead-sure that it won't smash your data. Moreover, you are copying char stringCollector[512] into char personCatalog.name[50] - don't do that. It's inconsistent and if you base your bounds checks on the size of of the former, you are bound to have problems (rather sooner than later).
Last but not the least: an off-by-one error (it really is sometimes hard to get this right).
struct personCatalog *pointerArray[51];
...
int maxNumberOfPeople = 51;
if (num < maxNumberOfPeople)) {
...
num++;
...
}
ArrayOfPointers[num] = '\0'
In the worst case, you are going to write behind ArrayOfPointers (to ArrayOfPointers[51] to be specific).
Use macros and decide whether you want to NULL-terminate the array:
#define MAXPEOPLE 50
struct personCatalog *pointerArray[MAXPEOPLE+1]; /* +1 for the NULL terminator */
if (num < MAXPEOPLE)) ...