#include <stdio.h>
struct mychar{
char value;
struct mychar *nextPtr;
};
typedef struct mychar Mychar;
typedef Mychar *MycharPtr;
void insert(MycharPtr *, char );
void printlist(MycharPtr);
int main(){
MycharPtr startPtr = NULL;
char b = 'b';
insert(&startPtr, b);
printlist(startPtr);
}
void insert(MycharPtr *sPtr, char newvalue){
MycharPtr newlinkPtr;
if (*sPtr == NULL){
newlinkPtr->value = newvalue;
newlinkPtr->nextPtr = NULL;
}
*sPtr = newlinkPtr;
}
void printlist(MycharPtr currentPtr){
printf("%c", currentPtr->value);
}
I'm just starting by only adding one char. If I can't even do that, I can't go on doing else.
It gives me segmentation fault, but I don't really know why.
Also, I still don't get the reason why in insert call I should write & but in printlist call I shouldn't write &.
You haven't actually allocated memory for newlinkPtr. So you're just dereferencing and attempting to write to an uninitialized pointer, resulting in undefined behaviour.
In insert, you can modify it to:
MycharPtr newlinkPtr = malloc(sizeof *newlinkPtr);
if (!newlinkPtr) {
perror("malloc");
return;
}
...
This also, sort of, illustrates why typedef'ing a struct pointer could mislead and considered a bad practice. I'd suggest avoiding it.
Related
The following code below runs without a seg fault
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *data;
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
head->data = "test";
printf("data: %s\n", head->data);
return 0;
}
when I switch the code to so
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *data;
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
strncpy(head->data, "test", 512);
printf("data: %s\n", head->data);
return 0;
}
I receive a seg fault and am forced to switch my node property data to be of type char data[512]. Why is this required? I thought arrays are inherently pointers, so this behavior is not making sense to me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char data[512];
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
strncpy(head->data, "test", 512);
printf("data: %s\n", head->data);
return 0;
}
I expected that both pointers and arrays could be assigned string values in the same way.
In this statement
head->data = "test";
the string literal having the array type char[5] is implicitly converted to pointer to its first element and this pointer is assigned to the pointer head->data.
In this statement
strncpy(head->data, "test", 512);
you are using an uninitialized pointer head->data and trying to copy the whole string literal to the memory pointed to by that pointer with an indeterminate value. That invokes undefined behavior.
I thought arrays are inherently pointers, so this behavior is not
making sense to me.
Arrays are not pointers. They can be implicitly converted to pointers to their first elements in most situations but this does not mean that arrays are pointers.
Consider the simple demonstration program below.
#include <stdio.h>
int main( void )
{
char data[512];
char *p = data;
printf( "sizeof( data ) = %zu\n", sizeof( data ) );
printf( "sizeof( p ) = %zu\n", sizeof( p ) );
}
Its output might look like
sizeof( data ) = 512
sizeof( p ) = 8
In the second snippet (the one that crashes), you allocate memory for the node struct, which includes the pointer data. However, this pointer is never initialized, and it points to some arbitrary memory address (or just NULL), meaning that writing to it is undefined behavior, and indeed likely to just segfault.
For it to point to a valid memory address, you'll have to explicitly allocate it:
struct node *head = malloc(sizeof(struct node));
head->data = malloc(sizeof(char) * 512 /* or some other size, of course */);
Why is this required? I thought arrays are inherently pointers, so this behavior is not making sense to me.
Pointers are just pointers and the only memory they occupy is the memory required to store an address. If you want a pointer to point at dynamically allocated memory, you need to allocate it yourself.
Example:
struct node {
char *data;
struct node *next;
};
struct node *create_node(const char *str) {
struct node *nn = malloc(sizeof *nn);
if(nn) {
nn->data = strdup(str); // allocate strlen(str)+1 bytes and copy the string
if(nn->data) { // strdup was successful
nn->next = NULL;
} else { // strdup failed
free(nn);
nn = NULL;
}
}
return nn;
}
void destroy_node(struct node *n) {
free(n->data);
free(n);
}
I thought arrays are inherently pointers
Array Vs pointer:
An array might decay to a pointer in expressions and function parameters, and array accesses might be rewritten by the compiler as pointer accesses, but they are not interchangeable. An array name is an address, and a pointer is the address of an address.
Why is this required?
Declaring a pointer only allocates memory for the pointer.
You can initialise a pointer in two ways:
Either with a string literal:
ptr = "abcd";
Originally, ptr was
indeterminate. But this changes
what it was pointing to such that
it now points to a string literal.
The compiler will store the
address of the first element of
the string literal in ptr.
If you were to do the same with an
array:
char s[] = "String";
and then try to change its value:
s = "String2";
/* error: assignment to expression
with array type */
It wouldn't compile, because
arrays, unlike pointers, are not
modifiable lvalues.
You can't change its value.
Or allocate memory for it and then
write to it.
errno = 0;
ptr = malloc (size);
if (!ptr) {
errno = ENOMEM;
perror ("malloc ()");
deal with error here...
}
Now you can use strcpy () to
copy to it.
I'm trying to implement stack using linked list implementation. Its giving me "Segmentation Error". Please help me finding the error. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct NODE {
char word;
struct NODE *next;
};
struct STACK {
struct NODE *head;
int size;
};
void pushStack(struct STACK *stack, char s);
void makeStack(struct STACK *stack, char *s);
void printStack(struct STACK *stack);
int main(){
char *s;
fgets(s,100,stdin);
struct STACK stack;
stack.head = NULL;
makeStack(&stack,s);
printStack(&stack);
return 0;
}
void pushStack(struct STACK *stack, char s){
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
strcpy(temp,s);
for(int i=0; i<MAX; i++){
if(temp[i]=='\0') break;
pushStack(stack,temp[i]);
}
}
void printStack(struct STACK *stack){
struct NODE *trav = stack->head;
while (trav != NULL){
printf("%c", trav->word);
trav = trav->next;
}
}
MAX=100 is the limit I'm taking for string input. I haven't also added increasing the size because I'm just ignoring the increment of size for now. Before I could perfect the implementation
In main the s pointer is not initialized and it points nowhere.
int main(){
char *s; // <<< this is wrong, you want 'char s[100]' instead
fgets(s,100,stdin);
...
However the safest option is this:
int main(){
char s[100]; // declare array of 100 chars
fgets(s, sizeof(s), stdin); // sizeof(s) is the actual size of s (100 here)
...
This is wrong too: you store the pointer to the local variable temp, but that variables ceases to exist once you return from the pushStask function.
void pushStack(struct STACK* stack, char s) {
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
Instead you need to create a new struct NODE like this:
void pushStack(struct STACK* stack, char s) {
struct NODE* temp = malloc(sizeof *temp);
temp->word = s;
temp->next = stack->head;
stack->head = temp;
}
Instead of malloc(sizeof *temp) you could write sizeof(struct NODE), it's the same, but it's less fool proof because you could mistakenly write sizeof(struct STACK) which would compile fine, but the size of the allocated memory would be wrong.
Another problem: you don't assign the size field of the struct STACK, this is not a problem now, but it might become a problem later.
There are several drawbacks in your implementation of a stack.
The first one is that you are using a pointer with an indeterminate value to read a string
char *s;
fgets(s,100,stdin);
So the call of fgets invokes undefined behavior.
Moreover there is used a magic number 100.
You need to allocate a character array and use it to read a string.
#define MAX 100
//...
char s[MAX];
fgets( s, MAX, stdin );
Pay attention to that the name word for an object of the type char is confusing
struct NODE {
char word;
struct NODE *next;
};
You could define the structure like for example
struct NODE {
char c;
struct NODE *next;
};
or
struct NODE {
char item;
struct NODE *next;
};
Instead of separating the declaration and the initialization as you did
struct STACK stack;
stack.head = NULL;
forgetting to initialize the data member size (that by the way should have an unsigned integer type as for example size_t) you could just write for example
struct STACK stack = { NULL, 0 };
or
struct STACK stack = { .head = NULL, .size = 0 };
In the declaration of the function makeStack the second parameter should have the qualifier const because the passed string is not being changed within the function. And as a memory allocation in general can fail the function should report whether all characters of the string were pushed successfully. So the function declaration should look like
int makeStack( struct STACK *stack, const char *s );
It does not make a sense to declare a local array temp within the function
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
//...
using the index variable i is redundant. Also the function fgets can append the new line character '\n' to the input string that you should not push on stack.
The function can be defined the following way
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
if ( *s != '\n' )
{
success = pushStack( stack, *s );
}
}
return success;
}
Another approach is to remove the new line character from the input string before passing it to the function makeStack.
For example
s[ strcspn( s, "\n" ) ] = '\0';
makeStack( &stack, s );
If it is the user that is responsible whether to push the new line character on stack or not then the function makeStack can be simplified
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
success = pushStack( stack, *s );
}
return success;
}
Correspondingly the function pushStack also should be redefined.
For starters it shall dynamically allocate a new node. Otherwise you will try to add nodes that are local to the function and will not be alive after exiting the function that again results in undefined behavior.
The function pushStack can be defined the following way.
int pushStack( struct STACK *stack, char c )
{
struct NODE *temp = malloc( sizeof( struct NODE ) );
int success = temp != NULL;
if ( success )
{
temp->word = c;
temp->next = stack->head;
stack->head = temp;
++stack->size;
}
return success;
}
The parameter of the function printStack should have the qualifier const because the stack itself within the function is not being changed.
The function can be defined at least the following way
void printStack( const struct STACK *stack )
{
for ( const struct NODE *trav = stack->head; trav != NULL; trav = trav->next )
{
printf( "%c", trav->word );
}
}
I have these structures in C:
typedef struct Game{
char* name;
char* team_1;
char* team_2;
int score[2];
} *pGame;
typedef struct Team{
char *name;
int victories;
} *pTeam;
typedef struct node_game{
pGame game;
struct node_game *next;
} *link_game;
typedef struct node_team{
pTeam team;
struct link_team *next;
} *link_team;
typedef struct head{
link_game game_list;
link_team team_list;
} *pHead;
And these functions to go with it:
void initialize(pHead* heads,int m){
int i;
heads = (pHead*)malloc(m*sizeof(pHead));
for (i = 0; i < m; i++)
heads[i] = NULL;
}
//this function is to allocate dynamic memory for a string
char* str_dup(char* buffer){
char* str;
str = (char*) malloc(sizeof(char)*(strlen(buffer)+1));
strcpy(str,buffer);
return str;
}
void add_team(pHead* heads, char* name){
char* name_dup;
link_team new_team = (link_team) malloc(sizeof(struct node_team));
name_dup = str_dup(name);
new_team->team->name = name_dup; //this line gives me segmentation fault
}
int main(){
pHead* heads;
initialize(heads,M);
add_team(heads, "manchester");
return 0;
}
Why is it that the last line of add_team gives me segmentation fault? I've looked at this with the VSC debugger and it seems it should go well. My problem is most likely that I'm not allocating memory when I should, but I can't see where. (also, the function will do more stuff, but it gives me segmentation fault already there).
At the time you do this:
new_team->team->name = name_dup;
You allocated memory for new_team, but not for new_team->team. This means that new_team->team->name dereferences an uninitialized pointer invoking undefined behavior.
You need to allocate space for it first:
link_team new_team = malloc(sizeof(struct node_team));
new_team->team = malloc(sizeof(struct Team));
Or you can change team from a struct Team * to a struct Team and access it directly. You probably want to do the same for game in struct node_game.
When working with a basic example like this, I am getting a segmentation fault. I believe it's due to the size of the data not being fixed. How can I have variable length data attached to a struct?
struct Node {
char * data;
struct Node* next;
};
void compareWord(struct Node** head_ref, char * new_data) {
if (strcmp((*head_ref)->data, new_data) > 0) {
head_ref->data = new_data;
}
}
int main(int argc, char* argv[]) {
struct Node* head = NULL;
head->data = "abc";
char buf[] = "hello";
compareWord(&head, buf);
return 0;
}
How can I have variable length data attached to a struct?
Answer is - No, you cannot. The reason is the size of the struct should be known at compile time.
The reason for segmentation fault is, your program is accessing head pointer before allocating memory to it:
struct Node* head = NULL;
head->data = "abc";
Allocate memory before using head:
struct Node* head = NULL;
head = malloc (sizeof(struct Node));
if (NULL == head)
exit(EXIT_FAILURE);
head->data = "abc";
Make sure to free allocated memory once you have done with it.
There is something known as Flexible Array Member(FAM) introduced in C99 standard. It may be of your interest.
I'm trying to improve my knowledge of C.
As an exercise I wrote a stack data structure. Everything works fine if I push N items and then pop N items. The problem occurs when I try to push an item again as the last removed item is still in memory (I think this is a problem).
When I allocate memory for the new path struct, the last removed string is still at the address which was freed after popping a data.
So when a new string is pushed, the last removed and new string are joined.
Can someone please check the following code and tell me what I'm doing wrong. Other comments are also welcome. Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 1000
struct path {
char curPath[N];
struct path *Next;
};
struct MyStack {
struct path *head;
int size;
};
int push(struct MyStack *, char *);
char * pop(struct MyStack *, char *);
int main() {
char path[N];
struct MyStack stack;
stack.head = NULL;
stack.size = 0;
push(&stack, "aaaaaaaaaaaa");
push(&stack, "bbbbbbbbbbbb");
pop(&stack, path);
printf("%s\n", path);
// output is:
// bbbbbbbbbbbb
path[0] = '\0';
push(&stack, "cccccccccccc");
pop(&stack, path);
printf("%s\n", path);
// output should be:
// cccccccccccc
// but it is not
// it is:
// bbbbbbbbbbbbcccccccccccc
return 0;
}
int push(struct MyStack *stack, char *path) {
if (strlen(path) > N) {
return -1;
}
struct path *p = (struct path*)malloc(sizeof(struct path));
if (p == NULL) {
return -1;
}
strcat((*p).curPath, path);
(*p).Next = (*stack).head;
(*stack).head = p;
(*stack).size++;
return 0;
}
char * pop(struct MyStack *stack, char *path) {
if ((*stack).size == 0) {
printf("can't pop from empty stack");
return NULL;
}
struct path *p;
p = (*stack).head;
(*stack).head = (*p).Next;
strcat(path, (*p).curPath);
free(p);
p = NULL;
(*stack).size--;
return path;
}
You are using strcat() in your pop() function. That appends the string that is at stack->head to your char path[]. If you want to replace the string, use strcpy() rather than strcat().
Besides that, though, there are other oddities in your code. You are returning an int from push() and a char* from pop() but you're not assigning those variables to anything in main(), so why are they not void functions?
malloc() does not fill the allocated memory with zeros, so here
struct path *p = (struct path*)malloc(sizeof(struct path));
// ...
strcat((*p).curPath, path);
you append the given string to whatever happens to be in (*p).curPath.
(This could cause a segmentation violation easily.)
Using strcpy() or (perhaps better strlcpy()) should solve the problem.