Single Linked List that implements push and pop - seg fault - c

I'm looking over some old code to write a program (in C) that creates push and pop methods similar to a stack for a singly linked list. I'm currently getting a segmentation fault and can't figure out the issue.
The input for any pushes will be single characters, here's an input example:
push ;
push g
push .
pop
push -
Code (commented out some things that were causing errors):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node
{
char data;
struct node* next;
}*top = NULL;
void push(char c);
char pop();
int main(int argc, char *argv[])
{
char* p1;
char p2;
FILE *fp = NULL;
fp = fopen(argv[2], "r");
loop:
while (!feof(fp))
{
fscanf(fp,"%s", &p1);
while (strcmp(&p1,"push") == 0)
{
fscanf(fp,"%s", &p2);
printf("%s\n", &p2);
// push(&p2);
fscanf(fp,"%s", &p1);
if (strcmp(&p1,"pop") == 0)
{
//pop();
fscanf(fp,"%s", &p1);
}
}
while (strcmp(&p1,"pop") == 0)
{
//pop();??
fscanf(fp,"%s",&p1);
if (strcmp(&p1,"push") == 0)
{
fscanf(fp,"%s",&p2);
printf("%s\n",&p2);
// push(&p2);
}
goto loop;
}
}
fclose(fp);
return 0;
}
void push(char c)
{
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = c;
temp->next = top;
top = temp;
}
char pop()
{
struct node *temp = top;
char data = temp->data;
top = top->next;
free(temp);
return data;
}
Current Warnings:
stack.c: In function âmainâ:
stack.c:24:3: warning: format â%sâ expects argument of type âchar *â, but argument 3 has type âchar **â [-Wformat]
stack.c:26:3: warning: passing argument 1 of âstrcmpâ from incompatible pointer type [enabled by default]
/usr/include/string.h:143:12: note: expected âconst char *â but argument is of type âchar **â
stack.c:31:4: warning: format â%sâ expects argument of type âchar *â, but argument 3 has type âchar **â [-Wformat]
stack.c:32:4: warning: passing argument 1 of âstrcmpâ from incompatible pointer type [enabled by default]
/usr/include/string.h:143:12: note: expected âconst char *â but argument is of type âchar **â
stack.c:35:5: warning: format â%sâ expects argument of type âchar *â, but argument 3 has type âchar **â [-Wformat]
stack.c:39:3: warning: passing argument 1 of âstrcmpâ from incompatible pointer type [enabled by default]
/usr/include/string.h:143:12: note: expected âconst char *â but argument is of type âchar **â
stack.c:42:4: warning: format â%sâ expects argument of type âchar *â, but argument 3 has type âchar **â [-Wformat]
stack.c:43:4: warning: passing argument 1 of âstrcmpâ from incompatible pointer type [enabled by default]
/usr/include/string.h:143:12: note: expected âconst char *â but argument is of type âchar **â

The warnings already tell you, what to do. The pointers the functions expect char*, and the pointer you pass &p1 aka char** are of different type. To fix this you must use p1 instead of &p1.
But you have another issue, you use p1 before it is initialized. This leads to segmentation faults too, because the pointer points nowhere and the functions printf or strcmp try to access the content there.
This means in the case of fscanf, you must allocate memory, where the content can be stored, see malloc. Same goes for p2, of course.

first of all p1 hav't any memory to point to. secondly you are passing &p1 to fscanf but fscanf expects it to be char * and &p1 has char ** since you have deplared it to be char *p1 and char *p2.what i ll suggest is you do the coding from scratch instead of coping the code coz this code has many intax errors.and probably your segmentation fault is because of the fscanf() itself coz you are passing argument of wring type.

Related

My compiler returned "assignment to 'int *' from incompatible pointer type 'char *' [-Wincompatible-pointer-types]" when I ran my C program

#include <stdio.h>
int main()
{
char grade = 'A';
int *p = &grade;
printf("The address where the grade is stored: %p\n", p);
printf("Grade: %c\n", grade);
return 0;
}
I get this error each time I compile the code on VScode but never on code blocks.
warning: incompatible pointer types initializing 'int *' with an
expression of type 'char *' [-Wincompatible-pointer-types]
int *p = &grade;
^ ~~~~~~
1 warning generated.
 ./main
The address where the grade is stored: 0x7ffc3bb0ee2b
Grade: A"
The warning tells you exactly what it is. It says:
incompatible pointer types initializing 'int *' with an expression of type 'char *'
This means that p is of type int *, that &grade is of type char *, and that these two pointers are not compatible. The solution is to change the declaration of p to:
char *p = &grade;
One more thing. Usually you can safely do implicit conversions to and from any pointer to void *, but not when passed as argument to a variadic function. If you want to print the address, use this:
printf("%p", (void *)p);
But only cast when needed. Never do it just to get rid of warnings. Here is an answer I wrote about that: https://stackoverflow.com/a/62563330/6699433
As an alternative, you could use a void pointer directly:
void *p = &grade;
printf("%p", p);
But then you would need to cast if you want to dereference it. For example:
char c = *(char*)p;
That cast is not necessary if p is declared as char *.

Cast from (void**) to (int*) and viceversa

I did a function f which takes as input a (void*), convert it to a (int*) and print the value.
#include <stdlib.h>
#include <stdio.h>
void f(void* p)
{
int *pi = (int*)p;
printf("%d\n", *pi);
}
int main()
{
int x = 1;
int *px = &x;
void *pv = (void*)px;
f(pv);
return 0;
}
Is it possible to implement a function:
void f2(void** pp);
such that it performs the "same" operations of the function f? My goal is to learn how to convert a (int*) to a (void**) and viceversa.
EDIT: error and warning of #tadman code (I did a mistake)
fvv.c: In function ‘f2’:
fvv.c:10:12: warning: initialization of ‘int *’ from incompatible pointer type ‘int **’ [-Wincompatible-pointer-types]
10 | int *pi = (int**)p;
| ^
fvv.c:12:17: error: invalid type argument of unary ‘*’ (have ‘int’)
12 | printf("%d\n", **pi);
|
EDIT2
fvv.c: In function ‘main’:
fvv.c:19:5: warning: passing argument 1 of ‘f2’ from incompatible pointer type [-Wincompatible-pointer-types]
19 | f2(&px);
| ^~~
| |
| int **
fvv.c:7:16: note: expected ‘void **’ but argument is of type ‘int **’
7 | void f2(void** p)
You can take any level of indirection you want, up to the blatantly, utterly absurd (void*******), but I'm not sure why this would be useful:
void f2(void** p)
{
// Note you must maintain the same level of indirection
int **pi = (int**)p;
// Since this is a ** pointer, it requires ** to fully de-reference
printf("%d\n", **pi);
}
To call this you need a pointer to a pointer:
int x = 1;
int *px = &x;
f2((void**) &px);
In C terms a pointer to a pointer is often interpreted to mean one of the two following things:
A two dimensional array
A mutable pointer argument
Neither of those apply here.
That being said, in C there's not a lot of rules as to what you can and can't convert. If you want to do it, C isn't going to get in your way, even if the resulting code makes no sense or will crash immediately when executed.
You can convert int* to void** and back again, C won't care, but you should have a really good reason for doing such a thing. Normally arbitrary pointers are almost always specified as void*, and as this can be recast into whatever you want, it's sufficient.
For example, you can specify void* as an argument when that pointer is actually int**, something you'll see quite often, as in thread_create taking a void* arg argument. That's not limited to mere pointers, you can cast to your heart's content.

C - Trouble passing array reference to pointer argument in function

I'm having trouble passing an integer array as a reference, and then modifying the original array.
#include <stdio.h>
// sets the 2 element of i to 5
void setToFive(int *i[10]){
*i[2] = 5;
printf("hello\n");
}
int main(){
int i[10];
setToFive(&i);
// confirm i[2] == 5
printf("%d\n", i[2]);
}
Compiler complains about invalid type
[vinessa#komputilo ch1]$ gcc test.c
test.c: In function ‘setToFive’:
test.c:5:5: error: invalid type argument of unary ‘*’ (have ‘int’)
5 | *i[2] = 5;
| ^~~~~
test.c: In function ‘main’:
test.c:11:15: warning: passing argument 1 of ‘setToFive’ from incompatible pointer type [-Wincompatible-pointer-types]
11 | setToFive(&i);
| ^~
| |
| int (*)[10]
test.c:4:21: note: expected ‘int *’ but argument is of type ‘int (*)[10]’
4 | void setToFive(int *i){
| ~~~~~^
segmentation fault
[vinessa#komputilo ch1]$ ./a.out
Segmentation fault (core dumped)
Have been banging head at problem for hours, please help.
Here you are
#include <stdio.h>
// sets the 2 element of i to 5
void setToFive(int *i){
i[2] = 5;
printf("hello\n");
}
int main(){
int i[10];
setToFive(i);
printf("%d\n", i[2]);
}
If you want to change elements of an array then just pass it by value. In this case the array designator is implicitly converted to pointer to its first element. Using the pointer and the pointer arithmetic you can change any element of the array.
In fact in this case you are passing elements of the array by reference indirectly through a pointer to them.
Pay attention to that these function declarations
void setToFive(int i[100]);
void setToFive(int i[10]);
void setToFive(int i[1]);
void setToFive(int i[]);
are equivalent and declare the same one function declaration of which the compiler adjusts to the following declaration
void setToFive(int *i);
That is as a result the function deals with a pointer.
As for the expression used as an argument in this function call
setToFive(&i);
then it has the type int ( * )[10] because the pointed array is declared like
int i[10];
It is not the same as the type of the parameter int *i[10] that as I already wrote is adjusted by the compiler to the type int **.
You are passing an array of pointers to integers, not an array of integers. You can just remove the various * declarations and operators, and just pass a simple array as the argument (the array argument will decay to a pointer):
#include <stdio.h>
// sets the 2 element of i to 5
void setToFive(int i[10])
{
i[2] = 5;
printf("hello\n");
}
int main()
{
int i[10];
setToFive(i);
// confirm i[2] == 5
printf("%d\n", i[2]);
return 0;
}

Pass a char pointer array to a function in C?

I have the following code:
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(n *sizeof *array);
/*Some code to assign array values*/
test(a, array);
return 0;
}
int test(char s1, char **s2){
if(strcmp(s1, s2[0]) != 0)
return 1;
return 0;
}
I'm trying to pass char and char pointer array to a function, but the above code results in the following errors and warnings:
temp.c: In function ‘main’:
temp.c:6:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
temp.c:6:13: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
temp.c:10:5: warning: implicit declaration of function ‘test’ [-Wimplicit-function-declaration]
temp.c: At top level:
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
temp.c: In function ‘test’:
temp.c:16:5: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
I'm trying to understand what the problem is.
First of all, you should include the necessary header files. For strcmp you need <string.h>, for malloc <malloc.h>. Also you need to at least declare test before main. If you do this you'll notice the following error:
temp.c: In function ‘test’:
temp.c:20:5: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
/usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
This indicates that test() should have a char * as first argument. All in all your code should look like this:
#include <string.h> /* for strcmp */
#include <malloc.h> /* for malloc */
int test(char*,char**); /* added declaration */
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(sizeof(*array));
array[0] = malloc(n * sizeof(**array));
/*Some code to assign array values*/
test(a, array);
free(*array); /* free the not longer needed memory */
free(array);
return 0;
}
int test(char * s1, char **s2){ /* changed to char* */
if(strcmp(s1, s2[0]) != 0) /* have a look at the comment after the code */
return 1;
return 0;
}
Edit
Please notice that strcmp works with null-terminated byte strings. If neither s1 nor s2 contain a null byte the call in test will result in a segmentation fault:
[1] 14940 segmentation fault (core dumped) ./a.out
Either make sure that both contain a null byte '\0', or use strncmp and change the signature of test:
int test(char * s1, char **s2, unsigned count){
if(strncmp(s1, s2[0], count) != 0)
return 1;
return 0;
}
/* don' forget to change the declaration to
int test(char*,char**,unsigned)
and call it with test(a,array,min(sizeof(a),n))
*/
Also your allocation of memory is wrong. array is a char**. You allocate memory for *array which is itself a char*. You never allocate memory for this specific pointer, you're missing array[0] = malloc(n*sizeof(**array)):
array = malloc(sizeof(*array));
*array = malloc(n * sizeof(**array));
Error 1
temp.c:6:13: warning: incompatible implicit declaration of
built-in function ‘malloc’ [enabled by default]
Did you mean this?
array = malloc(n * sizeof(*array));
Error 2
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t
match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
You are passing the address of the first element of an array a:
test(a, array);
So the function signature should be:
int test(char* s1, char** s2)
You have several problems. The first is that the prototype is wrong. The data type for a decays to a char pointer when passing to a function, so you need:
int test (char* s1, char** s2) { ... }
However, even when you fix this, the test declaration isn't in scope when you first use it. You should either provide a prototype:
int test (char* s1, char** s2);
before main, or simply move the whole definition (function) to before main.
In addition, don't forget to #include the string.h and stdlib.h headers so that the prototypes for strcmp and malloc are available as well.
When you pass an array of char to your function, the argument decays to a pointer. Change your function arguments to
int test(char* s1, char **s2);
^
^
and your code should at least compile

atoi from string to Integer using char pointer

Here is the code I have written which splits a string in c and then I want to return the first integer value pointed by the char pointer.
#include<stdio.h>
void main(){
int month[12]={0};
char buf[]="1853 was the year";
char *ptr;
ptr = strtok(buf," ");
printf("%s\n",ptr);
int value = atoi(*ptr);
printf("%s",value);
}
EDIT:It gives me segmentation fault.
The problem is it is printing 1853 as the year, But I want to convert this into integer format.How can i retrieve that value as an integer using the pointer?
you are here trying to use an integer as a string:
printf("%s",value);
you should do
printf("%d",value);
Edit: yes, and also do int value = atoi(ptr); as added in another answer.
main should also be int, not void.
Also, what compiler are you using? With gcc 4.6 I got these errors and warnings when trying to compile your code (after adding some includes):
ptrbla.C:5:11: error: ‘::main’ must return ‘int’
ptrbla.C: In function ‘int main()’:
ptrbla.C:11:30: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
/usr/include/stdlib.h:148:12: error: initializing argument 1 of ‘int atoi(const char*)’ [-fpermissive]
ptrbla.C:12:26: warning: format ‘%s’ expects argument of type ‘char*’, but argument 2 has type ‘int’ [-Wformat]
I'd think you could get at least some of these from most compilers.
int value = atoi(ptr);
No need to dereference, atoi() expects a const char*, not a char.
printf("%d",value);
And you print an integer using %d or %i. %s is for string only.
BTW, maybe you would like to use strtol instead
char buf[]="1853 was the year";
char* next;
long year = strtol(buf, &next, 10);
printf("'%ld' ~ '%s'\n", year, next);
// 'year' is 1853
// 'next' is " was the year"
Use:
int value = atoi(ptr);
atoi should get a character pointer, which is what ptr is. *ptr is the first character - 1 in this case, and anyway isn't a pointer, so it's unusable for atoi.

Resources