Why do i get segmentation fault 11? - c

Why do I get segmentation fault 11? I get it quite often, and I know this time it is about the function. If anyone can help, please do, the code is down below! I am trying to make a program, that WITH A FUNCTION, can rearrange an array in ascending order and then print it in main in reverse order.
#include "stdio.h"
void changxr(int *counter, int *arrsize, int *j, int *arr[]);
int main()
{
int a, i, j, counter;
int arrsize;
int arr[100];
printf("pick an arraysize: \n");
scanf("%d", &arrsize);
printf("type %d numbers \n", arrsize);
for (counter = 0; counter < arrsize; counter++)
{
scanf("%d", &arr[counter]);
}
for (int c = arrsize - 1; c >= 0; c--)
{
printf("%d ", arr[c]);
}
changxr(&counter, &arrsize, &j, &arr[&counter]);
for (counter = arrsize - 1; counter >= 0; counter--)
{
printf("%d ", arr[counter]);
}
}
void changxr(int *counter, int *arrsize, int *j, int *arr[])
{
int a;
for (*counter = 0; *counter < *arrsize; *counter++)
{
for (*j = *counter + 1; *j < *arrsize; *j++)
{
if (*arr[*counter] > *arr[*j])
{
a = *arr[*counter];
*arr[*counter] = *arr[*j];
*arr[*j] = a;
}
}
}
}
New code:
#include "stdio.h"
void changxr(int arrsize, int *arr[]);
int main()
{
int a, i, j, counter;
int arrsize;
int arr[100];
printf("pick an arraysize: \n");
scanf("%d", &arrsize);
printf("type %d numbers \n", arrsize);
for (counter = 0; counter < arrsize; counter++)
{
scanf("%d", &arr[counter]);
}
for (int c = arrsize - 1; c >= 0; c--)
{
printf("%d ", arr[c]);
}
changxr(arrsize, &arr[counter]);
for (counter = arrsize - 1; counter >= 0; counter--)
{
printf("%d ", arr[counter]);
}
}
void changxr(int arrsize, int *arr[])
{
int a, counter, j;
for (counter = 0; counter < arrsize; counter++)
{
for (j = counter + 1; j < arrsize; j++)
{
if (*arr[counter] > *arr[j])
{
a = *arr[counter];
*arr[counter] = *arr[j];
*arr[j] = a;
}
}
}
}
This is what I got from debugging:
"Program received signal SIGSEGV, Segmentation fault.
0x0000555555555355 in changxr (arrsize=3, arr=0x0) at main.c:33
33 for(j=counter+1; j<arrsize; j++) { if(*arr[counter]>*arr[j]){
(gdb) continue"

You do not need two levels of indirection (int *arr[], *arr[counter], *arr[j]). When arr is passed to a function, it will decay to a pointer-to-its-first-element, or more simply, an int *.
&arr[counter] is also an int *, but it is the address of the array element one past the elements you've initialized. This would start your sorting function in the incorrect place.
Your program segfaults because it attempts to use this value as an int ** (int *[]).
gcc -Wall highlights this clearly:
prog.c: In function ‘main’:
prog.c:24:22: warning: passing argument 2 of ‘changxr’ from incompatible pointer type [-Wincompatible-pointer-types]
24 | changxr(arrsize, &arr[counter]);
| ^~~~~~~~~~~~~
| |
| int *
prog.c:3:32: note: expected ‘int **’ but argument is of type ‘int *’
3 | void changxr(int arrsize, int *arr[]);
| ~~~~~^~~~~
Things to do:
Simply pass the array and the length of the array to your function.
Use a single level of indirection in your function definition, and when accessing the array.
Use a variable-length array.
Use an auxiliary function for printing.
Declare variables when you need them, in the correct scope.
You should also consider checking the return value of scanf is the expected number of successful conversions.
The refactored code:
#include <stdio.h>
void changxr(int *a, size_t length)
{
for (size_t i = 0; i < length; i++) {
for (size_t j = i + 1; j < length; j++) {
if (a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
void print_reverse(int *a, size_t length)
{
printf("[ ");
while (length--)
printf("%d ", a[length]);
printf("]\n");
}
int main(void)
{
size_t size;
printf("Pick an array length: ");
if (1 != scanf("%zu", &size) || size == 0) {
fprintf(stderr, "Invalid length input.\n");
return 1;
}
int array[size];
printf("Enter %zu numbers:\n", size);
for (size_t i = 0; i < size; i++) {
if (1 != scanf("%d", array + i)) {
fprintf(stderr, "Invalid integer input.\n");
return 1;
}
}
printf("Array (in reverse): ");
print_reverse(array, size);
changxr(array, size);
printf("Array, Sorted (in reverse): ");
print_reverse(array, size);
}

Related

why does the printf not showing

I need help. It doesnt display the printf in the mean function. I am doing a dynamic allocation in c and the add function works but the mean function does not display. There is no problem to the add function it works but the max does not. I am sorry I know this problem is simple but still cant get the answer. I am also getting a warning to the add function during the call in main.
This is my code:
typedef int* Statistician;
void add(Statistician answer, int *count, int *SIZE, int item);
|
[Note] expected 'Statistician' {aka 'int *'} but argument is of type 'int **'
int main() {
int SIZE;
Statistician *answer;
int count;
int item;
add(answer, count, SIZE, item);
|
//[Warning] passing argument 1 of 'add' from incompatible pointer type [-Wincompatible-pointer-types]
printf("\nThe mean is: %.2f", mean(answer, SIZE));
return 0;
}
This is the add function:
void add(Statistician answer, int *count, int *SIZE, int item) {
int i;
printf("Enter n: ");
scanf("%d", &item);
answer = (int*)malloc(item * sizeof(int));
if(item == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
for(i = 0; i < item; ++i) {
scanf("%d", &answer[i]);
}
printf("Elements of array are: ");
for(i = 0; i < item; i++) {
printf("%d ", answer[i]);
}
if(item == 10) {
int m;
printf("\nAppend array: ");
scanf("%d", &m);
answer = realloc(answer, m * sizeof(int));
for(i = item; i < item + m; i++) {
scanf("%d", &answer[i]);
}
item = item + m;
int temp, j;
for(i = 0; i < item; i++) {
for(j = 0; j <= i; j++) {
if(*(answer + i) < *(answer + j)) {
temp = *(answer + i);
*(answer + i) = *(answer + j);
*(answer + j) = temp;
}
}
}
printf("Final array: \n");
for(i = 0; i < item; ++i) {
printf("%d ", answer[i]);
}
}
}
}
This is the max function that doesnt display:
float mean(Statistician answer, int count) {
int mean =0;
int cnt = 0;
for(int i=0;i<count;i++){
mean = mean + answer[i];
cnt++;
}
mean = mean / cnt;
return mean;
}
I fully expected to find a duplicate but I didn't.
The first argument to add is declared to be int ** (via typedef) and you passed it a paramter of type int *. The compiler will let you do this with a warning, but it's almost always wrong. Don't do it.
If you're running 64 bit code, anything can happen after you stomp memory. 32 bit code is slightly more predictable but it's still going to end badly.
From your code, it looks like you want void add(Statistician *answer, Statistician answer; and add(&answer.
The deep learning of pointers is here. The thing you need to modify in the calling function is the thing whose address is passed to the called function. Allocating arrays with malloc almost always ends up being double pointers.

Warning messages for all of my functions using pointers. Expected 'int*' but argument is of type 'int (*)[10]'

The code works fine I'm just worried about the warning messages I'm getting, would there be a way to make them not appear? Is there any reason to be worried about them? Also farther down in the code I don't quite understand what I did or why it worked. It wasn't working before so I looked up what other people did with pointers and it works now
Warning passing argument 1 of 'readarray' from incompatible pointer type [-wincomp
readarray(&a);
^
note: expected 'int*' but argument is of type 'int(*)[10]'
void readarray (int*);
^
This is the warning message, I get it for each of my functions^^^^^^^^^^^^^^^^^^
I understand why it's having issues, I think, but I don't understand how I could change anything
#include <stdio.h>
#define n 10
void readarray (int*);
int findmaxvalue(int*);
void reversearray(int*, int*);
void printarray(int*);
int main(void)
{
int a[n], i, b[n];
for (i = 0; i < n; i++)
{
a[i] = 0;
}
for (i = 0; i < n; i++)
{
b[i] = 0;
}
readarray(&a);
findmaxvalue(&a);
reversearray(&a, &b);
printarray(&b);
return 0;
}
void readarray (int *a)
{
int *q;
q = a;
printf("Enter up to 10 numbers. Terminate by entering a 0\n");
Right here, why can't I use 'a' instead of 'a+n'
for(q = a; q < a+n; q++)
{
scanf("%d", q);
if (*q == 0)
break;
}
printf("\n");
}
int findmaxvalue(int *a)
{
int i, max;
max = a[0];
for (i = 1; i < n; i++)
{
if (a[i] > max)
max = a[i];
}
printf("The highest element in the array is: %d\n\n", max);
return max;
}
void reversearray(int *a, int *b)
{
int *i, *j, t;
for (i = a; i < a+n; i++)
{
for (j = i + 1; j < a+n; j++)
{
if (*j < *i)
{
t = *j;
*j = *i;
*i = t;
}
}
}
for (i = a + n - 1, j = b; i > a; i--, j++)
{
*j = *i;
}
}
void printarray(int *b)
{
int *q;
q = b;
printf("The reversed array in descending order is:\n");
for (q = b; q < b+n; q++)
{
printf("%d ", *q);
}
}
I think the error message is pretty self-describing.
In your code, a is an array type, having int [10]. You pass &a, which is of type pointer to an array of 10 ints, or, int (*)[10] which is not the same type as a pointer to int, i.e., int *. Hence the compiler screams.
As array type variables decay to the pointer to the first element of the array while passed as function arguments, you should call your function like
readarray(a);

How do I loop and print through an array of structs in c?

I am writing a function separate from main that reads in an array of structs and prints each array element's struct elements. My problem however is the condition statement for looping though this array to print each element. sizeof(a)/sizeof(a[]) just doesnt work in the function because it is equal to zero within the prototype. Is there something i am missing? I've tried pointer arithmetic and it does not work either.
void printNames( person a[]){
int i;
for(i = 0;i<sizeof(a)/sizeof(a[0]);i++)
printf("Name: %s | Age: %d\n", a[i].name, a[i].age);
}
int main(int argc, char *argv[]){
if (argc == 1 || argc%2 == 0){
printf("Invalid arguments.\n Usage: %s name1 age1 name2 age2 ...", argv[0]);
return 0;
}
printf("You have entered %d person(s) into the program.\n", argc/2);
person people[argc/2];
int i;
for (i = 0; i<argc/2;i++){
strcpy(people[i].name, argv[i*2+1]);
people[i].age = atoi(argv[i*2+2]);
if(people[i].age <= 0){
printf("Invalid age <= 0. Try again.");
return 0;
}
}
a becomes a pointer when passed as parameter to a function, so it cannot figure out the size of the array just from having this pointer, you have to inform the function about its size:
void printNames(person *a, size_t num)
{
int i;
for (i = 0; i < num; i++)
printf("Name: %s | Age: %d\n", a[i].name, a[i].age);
}
Then call printNames from main like this:
printNames(people, sizeof(people)/sizeof(*people));
In C, array parameters are decayed into pointers. So, the expression sizeof(a)/sizeof(a[0]) becomes sizeof(int *)/sizeof(int) which results in 1 (assuming the size of int and int * is 4) and hence the for loop within the printNames() is executed only once regardless of the size of the array.
Therefore, sizeof shouldn't be used to obtain the number of elements in these cases. Instead, we can pass an additional parameter for array size to printNames().
Consider the following C program:
#include<stdio.h>
void func(int array[])
{
int i;
int arraySize = sizeof(array)/sizeof(array[0]); /* arraySize <-- 1<-- 4/4 */
for (i = 0; i < arraySize; i++)
{
array[i] = i;
}
}
int main()
{
int i;
int array[4] = {0, 0 ,0, 0};
func(array);
for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
printf(" %d " ,arr[i]);
getchar();
return 0;
}
Output: 0 0 0 0 on a Intel Architecture-32 machine.
So the corrected program is:
#include<stdio.h>
void func(int array[], size_t arraySize)
{
int i;
for (i = 0; i < arraySize; i++)
{
array[i] = i;
}
}
int main()
{
int i;
int array[4] = {0, 0 ,0, 0};
func(array, 4);
for(i = 0; i < sizeof(array)/sizeof(array[0]); i++)
printf(" %d ", array[i]);
getchar();
return 0;
}

data types error - program to find the union of two arrays (c)

I am trying to write a program in C to create a union between two arrays, then output the total number of elements in the new array. I am getting the following errors when compiling my code (gcc).
test.c:44:11: error: expected ‘{’ before ‘(’ token
void union(int arrA[], int arrB[], int m, int n)
^
test.c:44:6: error: two or more data types in declaration specifiers
void union(int arrA[], int arrB[], int m, int n)
^
I've checked through for missing semicolons, etc. So unless I'm just missing it, I can't figure out where the issue is coming from. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n;
int m;
int i;
int k;
printf("Enter the size of array A: ");
scanf("%d",&n);
int arrA[n];
printf("Enter the element(s) of array A: ");
for(i=0;i<n;i++)
{
scanf("%d",&arrA[i]);
}
for(i=0; i<n; i++)
{
printf("%d",arrA[i]);
}
printf("\n");
printf("Enter the size of array B: ");
scanf("%d",&m);
int arrB[m];
printf("Enter the element(s) of array B: ");
for(i=0;i<m;i++)
{
scanf("%d",&arrB[i]);
}
for(i=0; i<m; i++)
{
printf("%d",arrB[i]);
}
printf("\n");
printf("%d\n",k);
return 0;
}
int union(int arrA[], int arrB[], int m, int n)
{
int i = 0;
int j = 0;
int k = 0;
int l = 0;
if(n > m)
{
n = l;
}
else
{
m = l;
}
int arrC[l];
while ((i < n) && (j < m))
{
if (arrA[i] < arrB[j])
{
arrC[k] = arrA[i];
i++;
k++;
}
else if (arrA[i] > arbB[j])
{
arrC[k] = arrB[j];
j++;
k++;
}
else
{
arrC[k] = arrA[i];
i++;
j++;
k++;
}
}
if (i == n)
{
while (j < m)
{
arrC[k] = arrB[j];
j++;
k++;
}
}
else
{
while (i < n)
{
arrC[k] = arrA[i];
i++;
k++;
}
}
return(k);
}
As pointed out by sawims in the comments, union is a reserved word and you had a typo on else if (arrA[i] > arbB[j]), changing the function's name and fixing the typo your code compiles.
http://ideone.com/ubB1eG

equating addresses of a 2d array and a 1d array in c

This prog is to accept an array of chars n compress them....(aaaabbbcc-->a4b3c2)....my prog is showing error at the point where im equating the addr of the 2d array to 1d array. This is my code:
/* size1 defined as 5 and size2 as 10.... (consts)*/
void compress(char data[SIZE1][SIZE2]);
int main()
{
char data[SIZE1][SIZE2];
printf("Enter a 5x10 matrix of characters:\n");
scanf("%c", &data);
compress(data[SIZE1][SIZE2]);
_getch();
return 0;
}
void compress(char data[SIZE1][SIZE2])
{
int hold[SIZE1*SIZE2];
int cnt = 0;
hold[SIZE1*SIZE2] = data[SIZE1][SIZE2];
for (int i = 0; i < (SIZE1*SIZE2); i++)
{
if (hold[i] == hold[i + 1])
{
cnt++;
continue;
}
else
{
printf("%c%d", hold[i], cnt);
}
}
}
This didn't work so I tried to use pointers:
void compress(char data[SIZE1][SIZE2])
{
int *hold[SIZE1*SIZE2];
int cnt = 0;
hold = data[SIZE1][SIZE2];
for (int i = 0; i < (SIZE1*SIZE2); i++)
{
if (*(hold+i) == *(hold+i+1))
{
cnt++;
}
else
{
printf("%c%d", *(hold+i), cnt);
}
}
}
I thought that the addrs of 2d arrays are stored linearly, hence they can be directly =to that of 1d.But the error says "'=':left operand must be an l-value".Im very new to pointers.Any help or corrections ....pls?
#include <stdio.h>
#define SIZE1 3
#define SIZE2 3
void compress(char data[SIZE1][SIZE2]);
int main(){
char data[SIZE1][SIZE2];
printf("Enter a %dx%d matrix of characters:\n", SIZE1, SIZE2);
for(int i=0;i<SIZE1;++i)
for(int j=0;j<SIZE2;++j)
scanf("%c", &data[i][j]);//aaaabbbcc
compress(data);
(void)getchar();
return 0;
}
void compress(char data[SIZE1][SIZE2]){
char *hold = &data[0][0];
int cnt = 1, size = SIZE1*SIZE2;
for (int i = 0; i < size; i++){
if (i < size -1 && hold[i] == hold[i + 1]){
cnt++;
//continue;
} else {
printf("%c%d", hold[i], cnt);//a4b3c2
cnt = 1;
}
}
}

Resources