I have a problem with a rather big piece of code. Knowing myself, it's some kind of a silly mistake, or, more likely, lack of understanding of pointers. I really need some help, so if someone could look at it I would be so grateful! I'm going to explain it now.
It's a program for my programming class. The teacher gave us a number (N) and a letter (X) in a txt file, and wants us to create a structure with three fields(int, char and float), and then four functions:
function #1 takes the number N as an argument and dynamically allocates memory for an array of pointers to N structures. then it assigns values to the fields in the structures - int and char are set to random values, and the float field is set to the number of the structure. the function returns the address of the array.
function #2 takes the size of the created array (the number of pointers in it) and a pointer to the array as arguments and deletes the array, freeing the memory.
function #3 takes the size of the created array and a pointer to the array as arguments, and then sorts the structures based on the int field, using bubble sort
function #4 searches through the structures and counts how many times the letter (X) is repeated in the char fields of the structures.
Here's the code with comments and errors. Please, can someone explain what am I doing wrong? To be honest I'm almost out of time, but I'm willing to stay up all night to understand and fix this.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
struct Foo {
int fieldint;
char fieldchar;
float fieldfloat;
};
Foo *initialize(int N);
int sort(int N, Foo *tablica);
int count(int N, Foo *tablica, char*X);
int deleting(int N, Foo **tablica);
int main () {
//this reads the number N and the letter to find from the .txt file:
FILE *file = fopen("inlab01.txt", "r");
int number;
char letter[1];
if (file == NULL) {
printf("Error opening file");
exit(-1);
}
while (fscanf(file, "%d%s", &number, letter) != EOF);
fclose(file);
//creating the array
//again, it's supposed to be an array of pointers to N structures:
Foo *arr[number];
*arr = initialize(number);
//sorting:
sort(number, *arr); //the program crashes at this function
//counting how many times the given letter appears:
//count(number, *arr, letter);
//we're supposed to print the first 20 of the structures
//this loop prints one structure and then the program crashes
for(int i=0;i<20;i++) {
printf("Structure %d:\nfield int:%d\nfield char:%c\nfield float:\f\n\n", i+1, arr[i]->fieldint, arr[i]->fieldchar, arr[i]->fieldfloat);
}
//deleting:
deleting(number, arr);
getch();
return 0;
}
Foo *initialize(int N) {
Foo **array;
array = (Foo **)malloc(sizeof(Foo) * N);
srand( time( NULL ) );
for(int i=0; i<N; i++) {
array[i] = (Foo*)malloc(sizeof(Foo));
array[i] -> fieldint = rand(); //random number
array[i] -> fieldchar = ( char )( rand() % 24 ) + 65; //random letter
array[i] -> fieldfloat=i;
}
return *array;
}
int sort(int N, Foo *array) {
int temp;
for (int i=0;i<N;i++){
for (int j=N-1;j>=j;j--) {
if(array[j].fieldint < array[j-1].fieldint) {
temp = array[j-1].fieldint;
array[j-1].fieldint = array[j].fieldint;
array[j].fieldint = temp;
}
}
}
return 0;
}
int count(int N, Foo *array, char*X){
int counter = 0;
for(int i=0;i<N;i++) {
if (array[i].fieldchar == 'X') {
counter = counter+1;
}
}
return counter;
}
int deleting(int N, Foo **array) {
for (int i=0;i<N;i++) {
free(array[i]);
}
free(array);
return 0;
}
The whole thing compiles, but then the program crashes instead of doing anything, really.
Please help.
struct Foo
{
int fieldint;
char fieldchar;
float fieldfloat;
};
Foo **array;
array = (Foo **)malloc(sizeof(Foo) * N);
You are compiling this code in C++. You want to use a C compiler, and you have to change the code to the following:
struct Foo **array;
You would use struct Foo everywhere, and you don't need that cast. Or declare the structure with typedef
Secondly, Foo **array is for allocating a 2-dimensional array. The way you are allocating 2-D array is wrong. Besides, you only need a 1-dimensional array Foo arr[number]
for (int j=N-1;j>=j;j--)
Note you have an error in your sort function (j >= j) is always true. Fix the sort function, avoid allocating a 2-D array and you are done.
int sort(int N, struct Foo *array)
{
int temp, i, j;
for (i = 0; i< N; i++) {
for (j = i + 1; j < N; j++) {
if (array[i].fieldint > array[j].fieldint) {
temp = array[i].fieldint;
array[i].fieldint = array[j].fieldint;
array[j].fieldint = temp;
}
}
}
return 0;
}
int main()
{
srand((unsigned)time(NULL));
int number = 3;
struct Foo arr[number];
int i;
for (i = 0; i < number; i++) {
arr[i].fieldint = rand(); //random number
arr[i].fieldchar = 'A' + (char)(rand() % 26); //random letter
arr[i].fieldfloat = (float)i;
}
sort(number, arr);
for (i = 0; i < number; i++)
printf("Structure %d:\nfield int:%d\nfield char:%c\nfield float:%f\n\n",
i + 1, arr[i].fieldint, arr[i].fieldchar, arr[i].fieldfloat);
getch();
return 0;
}
Note that your sort function swaps fieldint but Foo has other members, you probably want to swap all members if your goal is to swap the object.
Related
How can I return an array from a function, I am trying to perform (3*3)*(3*1) matrix multiplication using this translation function and how can i get an array out of it.
#include <stdio.h>
#include <math.h>
int* translation(int x, int y, int tx, int ty) {
static int res[3][1] = {0}, xy[3][1] = {{x},{y},{1}};
int tm[3][3] = {{1,0, tx}, {0,1,ty}, {0,0,1}};
for (int i = 0; i<3; i++) {
for (int j = 0; j<3; j++) {
res[i][0] += tm[i][j]*xy[j][0];
}
}
return res;
}
int main()
{
int *arr[3][1];
arr = translation(5, 5);
printf("%d %d %d", arr[0][0], arr[0][1], arr[0][2]);
return 0;
}
"How can I return an array from a function"
You can't.
The language has no such concept.
You'll have to return something including the length to give the user of the function the information. In C the idiomatic approach is to supply a pointer to the function and to get a value (via that pointer) in return:
size_t no_idea;
void function(void *data, &no_idea);
As a user of this function you'd have to read no_idea before judging.
you question is missing a lot of information like what you want to do with your code, the variable named xy isn't defined anywhere in your code, and so on...
but for clarification, if your result matrix is of unknown size, you can wrap your array into a struct, if you don't know what is the struct, you can refer to this small tutorial about struct in c, so your struct maybe look like something like this:
typedef struct Array_t{
size_t arrSize_x;
size_t arrSize_y;
int **arr;
}Array_t;
where arr is your matrix of unknown size which will be created dynamically and arrSize_x, arrSize_y are your matrix dimensions.
so in order to create a matrix of unknow size at compile time , you should create it dynamically in the heap memory using functions like calloc or malloc, although in C99, it allowed created arrays statically of unknown size during compile time but it's not the case with struct as the struct once defined, your array is created and you cannot do something like this:
typedef struct Array_t{
size_t arrSize_x;
size_t arrSize_y;
int arr[arrSize_x][arrSize_y];
}Array_t;
but if the size of the array is known you can do something like this:
typedef struct Array_t{
int arr[3][1];
}Array_t;
to create a dynamic array, you will find in the next example code something like this:
// rows are stored in heap memory and initiated with zeros
res.arr = (int**) calloc(res.arrSize_x, sizeof(int));
// columns are also stored in heap memory and initiated with zeros
for (int i = 0; i < res.arrSize_x; ++i) {
res.arr[i] = (int *) calloc(res.arrSize_y, sizeof(int));
}
where res.arr is a pointer pointing to an array of pointers and the next diagram may simplify my explanation where the next graph expresses the created matrix in heap memory for arr of size 3 x 1:
while if the size is known, so the explanation diagram may look like this:
and when you return, you can either return by value or by reference, but if you are going to return a struct by reference then you should declare it as static.
so you can do something like this (for clarification purposes, size of matrix is unknown):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Array_t{
size_t arrSize_x;
size_t arrSize_y;
int **arr;
}Array_t;
Array_t translation(int x, int y, int tx, int ty) {
// create a struct holding the array
Array_t res;
res.arrSize_x = 3;
res.arrSize_y = 1;
// rows are stored in heap memory and initiated with zeros
res.arr = (int**) calloc(res.arrSize_x, sizeof(int));
// columns are also stored in heap memory and initiated with zeros
for (int i = 0; i < res.arrSize_x; ++i) {
res.arr[i] = (int *) calloc(res.arrSize_y, sizeof(int));
}
res.arr[0][0] = 1;
res.arr[1][0] = 2;
res.arr[2][0] = 3;
return res;
}
int main()
{
Array_t array;
// 1, 2, 3, 4 are dummy parameters
array = translation(1, 2, 3, 4);
printf("elements are :\n");
for (int i = 0; i < array.arrSize_x; ++i) {
for (int j = 0; j < array.arrSize_y; ++j) {
printf("%d\t", array.arr[i][j]);
}
printf("\n");
}
return 0;
}
and this is the output:
elements are :
1
2
3
but if size of matrix is known then you can do something like this (for clarification purposes, size of matrix is known):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Array_t{
int arr[3][1];
}Array_t;
Array_t translation(int x, int y, int tx, int ty) {
// create a struct holding the array
Array_t res;
res.arr[0][0] = 1;
res.arr[1][0] = 2;
res.arr[2][0] = 3;
return res;
}
int main()
{
Array_t array;
// 1, 2, 3, 4 are dummy parameters
array = translation(1, 2, 3, 4);
printf("elements are :\n");
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 1; ++j) {
printf("%d\t", array.arr[i][j]);
}
printf("\n");
}
return 0;
}
and this is the ouput:
elements are :
1
2
3
I am writing this C/C++ program that is suppose to find the mean, median, and mode of a varied size array. Although, I keep getting a Segmentation Fault regardless of the input. What is wrong with my code? Any suggestions always appreciated! :)
Here is the code:
#include <stdio.h>
//#include <string.h>
//#include <math.h>
#include <stdlib.h>
Prototypes:
void sort(double*[],int);
static int min(double,double[],int);
double mean(double[],int);
double median(double[],int);
double mode(double[],int);
int numberOf(double,double[],int);
Main Function:
int main() {
int i;
scanf(" %d ",&i); //10
double arr[i]; //array that contains all the values and will be sortted
for (int j=0; j<i; j++) { //64630 11735 14216 99233 14470 4978 73429 38120 51135 67060
scanf(" %lf ",&arr[j]);
}
printf("%.1lf\n%.1lf\n%.0lf",mean(arr,i),median(arr,i),mode(arr,i));
return 0;
}
Sort Function:
The end result should update the array arr from the call in the Median Function. Changes the used values in the original array to -1 until that is the entire array.
void sort(double* arr[],int l) {
double arr2[l];
for (int i=0; i<l; i++) {
int j;
if (i)
j = min(arr2[i-1], *arr, l);
else
j = min(0, *arr, l);
arr2[i] = *arr[j];
*arr[j] = -1;
}
for (int i=0; i<l; i++) {
*arr[i] = arr2[i];
}
}
Min Function (helper function for the Sort Function):
Finds the minimum value amongst the array elements that is greater than or equal to minLookingTo
Returns the position the value is in.
static int min(double minLookingTo,double arr[],int l) {
int minP;
double minA = minLookingTo;
for (int i=0; i<l; i++) {
if (arr[i] == -1)
continue;
if (minLookingTo<=arr[i] && arr[i]<=minA) {
minP = i;
minA = arr[i];
}
}
return minP;
}
Mean Function:
Returns the mean of the inputted array with the length l
double mean(double arr[],int l){
double total = 0;
for (int i=0; i<l; i++) {
total += arr[i];
}
return total/l;
}
Median Function:
Uses the Sort Function. Assuming that works, returns the median.
double median(double arr[],int l){
sort(&arr,l);
double d = arr[(l/2)+1];
double dd = arr[(l/2)];
if (l%2!=0)
return d;
return (d+dd)/2;
}
Mode Function:
Uses the NumberOf Function to determine the array element with the maximum amount of repeats. Returns the lowest value of the highest (equal) repeats.
double mode(double arr[],int l){
int maxA;
int maxP;
for (int i=0;i<l;i++) {
int j = numberOf(arr[i],arr,l);
if (j>maxA) {
maxA = j;
maxP = i;
}
else if (j==maxA && arr[maxP]>arr[i])
maxP = i;
}
double d = arr[maxP];
return d;
}
NumberOf Function:
Helper function for the Mode Function. Returns the amount of elements with the looking value.
int numberOf(double looking,double arr[],int l) {
int amount = 0;
for (int i=0; i<l; i++)
if (looking == arr[i])
amount++;
return amount;
}
I tracked your segmentation fault to your sort() routine called by median(). Rather than fix sort(), I substituted qsort() from the library to convince myself that's the problem:
// Median Function:
// Uses the Sort Function. Assuming that works, returns the median.
int comparator(const void *p, const void *q) {
double a = *((double *) p);
double b = *((double *) q);
return (a > b) - (a < b); // compare idiom
}
double median(double array[], int length) {
// sort(array, length);
qsort(array, length, sizeof(double), &comparator);
double d = array[length / 2];
if (length % 2 != 0) {
return d;
}
double dd = array[(length / 2) - 1];
return (d + dd) / 2;
}
For the example list of numbers provided, after correcting the rest of the code, this returns a median of 44627.5
Other fixes:
You're missing a final newline here:
printf("%.1lf\n%.1lf\n%.0lf",mean(arr,i),median(arr,i),mode(arr,i));
You should probably initialize the variables in mode():
double mode(double array[], int length) {
int maxA = INT_MIN;
int maxP = -1;
for (int i = 0; i < length; i++) {
int j = numberOf(array[i], array, length);
if (j > maxA) {
maxA = j;
maxP = i;
} else if (j == maxA && array[maxP] > array[i]) {
maxP = i;
}
}
return array[maxP];
}
Your code has a series of errors. Some of them:
You donĀ“t need (in this case) to use spaces in scanf. This is causing a reading error.
You don't need to pass an array address to a function in order to alter its values. Arrays are always passed by reference. So change your function from void sort(double*[],int); to void sort(double[],int);, make the necessary corrections inside the function and call it using sort(arr,l); instead of sort(&arr,l);
Your min() function declares an uninitialized variable minP, so this variable contains garbage from your memory. The for() loop isn't entering none of the both if() conditions, so your function ends and returns the still uninitialized variable minP. This random value is then used to access an index in your array: j = min(0, arr, l); min returns an random number and then arr2[i] = arr[j]; accessing forbidden memory region, which is causing your segmentation fault error. The same problem is occurring with the variables maxP and maxA in the mode() function.
You must always be careful when accessing your arrays to not go beyond its bounds and always be sure that variables will be initialized when using them. And as others have commented, I also highly recommend you to learn how to debug your programs, since this will help you to analyze its execution and trace bugs.
I tried to write a program in C that reverses all the numbers in an array, but it actually doesn't reverse anything, so I get unchanged numbers back. I guess I got something wrong with the pointers.
Here is my code:
#include <stdio.h>
void reverse(int *n) {
int number = *n, number2 = 0;
while (number!=0) {
number2 *= 10;
number2 += number % 10;
number /= 10;
}
*n = number2;
}
void ReverseDigits(int *p, int n) {
int i = 0;
while (i < n) {
reverse(&p);
p++;
i++;
}
}
int main() {
int array[3] = {123, 456, 789}, i = 0;
while (i < 3) {
ReverseDigits(array, 3);
i++;
}
return 0;
}
In ReverseDigits the variable p is an int pointer. When you do &p you'll get a pointer to int pointer. But your reverse function just expects an int pointer so your call of reverseis wrong. Simply do
reverse(p); // insteand of reverse(&p)
In main you shall not call ReverseDigits in a loop as the function already loops the array (i.e. the number of elements passed). So skip the while and simply do:
int main() {
int array[3] = {123, 456, 789};
ReverseDigits(array, 3);
return 0;
}
It seems to me that your reverse() function is "both baffling, and necessarily wrong." (Hey, don't take that personally...)
How could such a function possibly work, without being told, not only where the (array) is, but how long it is? You seem to be missing a parameter here.
Once you've settled that problem in your design, the task of "reversing" an array is simply a process of "swapping" the first-and-last elements in an algorithm that goes something like this: (pseudocode!)
function reverse( array[], array_size) {
int i = 0;
int j = array_size - 1; // since zero-based
while (i < j) { // no need to use "<=" here"
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
}
Okay, so I am calling function fill_arrays like this:
fill_arrays(&data1, &data2, &size1, &size2);
fill_arrays looks like this:
void fill_arrays(int **data1, int **data2, int *size1, int *size2){
*size1 = get_size(*size1, 1);
*size2 = get_size(*size2, 2);
*data1 = malloc(*size1 * sizeof(int *));
*data2 = malloc(*size2 * sizeof(int *));
input_data(&data1, *size1, 1);
}
In input_data function I would like to assign some numbers to an array:
void input_data(int **data, int size, int index){
*data[5] = 5;
}
The problem is, I am completely lost with pointers... Maybe you can tell me how should I call function input_data in order to be able to assign some numbers to data array?
Assuming that input_data should set all array values to a known value, you could write
void input_data(int *data, int size, int value){
for (int i=0; i<size; i++) {
data[i] = value;
}
}
calling this like
input_data(*data1, *size1, 5); // set all elements of data1 to 5
The key point here is that you can use (*data1)[index] to access a particular array element and can pass your arrays as int* arguments.
I stumbled upon this question while doing a homework assignment and the answer doesn't strike me as entirely satisfactory, so I'll try to improve upon it.
Here is a small program that will establish an array of a user-defined size, fill it arbitrarily, and print it.
#include <stdio.h>
#include <stdlib.h>
void fill_array(int *array, int n)
{
int i;
for (i = 0; i < n; i++)
{
// fill array like [1, 2, 3, 4...]
array[i] = i+1;
}
}
void print_array(int *array, int n)
{
int i;
printf("[");
for (i = 0; i < n; i++)
{
if (i == (n-1))
printf("%d]\n", array[i]);
else
printf("%d, ", array[i]);
}
}
int main()
{
int n;
printf("Please enter a size for your array>");
scanf("%d", &n);
// dynamically allocate memory for integer array of size n
array = (int*) malloc (n * (sizeof(int)));
fill_array(array, n);
print_array(array, n);
return 0;
}
I hope this helps anyone who is learning C for the first time, or coming back to it after years away from the tried and true language, like me.
It seems you should also add int *array = NULL in order to get it working.
Situation
I was trying to implement a more interesting mergesort that creates a random length array with random values and then randomizes them, but after debugging and compiling it segfaults. I don't know why it segfaults, but I'm sure it's related to memory allocation.
Question
Why does this code cause a segfault?
Code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Declare some stuff up front
int array_size(int *array);
int print_array(int *array);
//Some decade old main function coming at you
int main() {
//Concerned with the integrity of my rand
srand( (unsigned)time( NULL ));
//A global, random length array between 1 and 100?
int *array;
array = malloc(sizeof(*array) * ((rand() % 100) + 1));
init_array(*array);
getchar();
return 0;
}
int init_array(int *array) {
//Base case
array[0] = 1;
//random values for i in array
int i;
for(i = 1; i <= array_size(array); i++) {
array[i] = rand() % array_size(array) + 1;
}
//randomize the random values in the random length array
for (i = 0; i < (array_size(array) - 1); i++)
{
unsigned int swapA = (rand() % array_size(array)) + 1;
int a = array[swapA];
array[swapA] = array[i];
array[i] = a;
}
//output random array, then mergeSort the array
print_array(array);
sort_array(array);
return 0;
}
//Get my array.Length
int array_size(int *array) {
return sizeof(array)/sizeof(array[0]);
}
//Output array
int print_array(int *array) {
int i;
for(i = 0; i < (array_size(array) + 1); i++) {
printf("%d\n", array[i]);
}
return 0;
}
//merge the array after sorting
void merge_array(int *array, int low, int split, int high) {
int sorted[high-low+1];
int a = 0;
int b = low;
int c = split + 1;
//iterate from beginning to middle and from middle to end in parallel
while(b <= split && c <= high)
{
if(array[b] < array[c])
{
sorted[a++] = array[b++];
}
else
{
sorted[a++] = array[c++];
}
}
while(b <= split) sorted[a++] = array[b++];
while(c <= high) sorted[a++] = array[c++];
int i;
for(i = 0; i < a; i++) {
array[i+low] = sorted[i];
}
print_array(array); //Print sorted array
}
//Sort the array
int sort_array(int *array, int low, int high) {
int split = ( low + high ) / 2;
if( low < high ) {
sort_array(array, low, split);
sort_array(array, split + 1, high);
merge_array(array, low, split, high);
}
}
return sizeof(array)/sizeof(array[0]);
The above statement evaluates to 1 (assuming sizeof(int *) = sizeof(int), as pointed out by H2CO3).
Try something like this,
int main() {
//Concerned with the integrity of my rand
srand( (unsigned)time( NULL ));
//A global, random length array between 1 and 100?
int *array;
int number_of_elements = (rand() % 100) + 1;
array = malloc(sizeof(*array) * num_of_elements);
init_array(*array, num_of_elements);
getchar();
return 0;
}
Pass the number of elements as arguments to init_array instead of calculating it every time.
This seems to be the problem:
//Get my array.Length
int array_size(int *array) {
return sizeof(array)/sizeof(array[0]);
}
You essentially return sizeof(int*)/sizeof(int), which is not what you want. This whole thing appears because arrays decay into pointers when passed to functions.
You should read the Arrays and Pointers section in the comp.lang.c FAQ for edification.
What happens when you run your program with /WALL? What warnings are being spat out? Why?
What happens when you step through your program with a debugger attached? What is the value of each variable at each line? Why?
There are several problems with your code:
You don't check the result of malloc to see if it returned NULL.
You are passing the dereference of array to init_array, i.e. you are sending the first int of the array to init_array which then promptly dereferences it. Since malloc returns garbage data, you're dereferencing a random number inside of init_array.
array_size is not magic. If you do not track the size of your arrays in C, you cannot retrospectively find out how big you wanted them to be. You need to remember the size of the array and pass it to init_array.