Excel / C - get input with array* - c

I'm working on a simple XLL addin and trying to get the input with a regular double* (not FP or OPER) because from what I understand, Excel should work with regular C data types. I can't get it to work, after many modifications, now it only returns the value in my last cell. What am I doing wrong?\
static AddIn xai_array_try(
"?xll_array_try", XLL_DOUBLE XLL_DOUBLE_,
"ARRAY.TRY", "Array",
"STL", "Test Sum Array."
);
double WINAPI xll_array_try(const double *arr) {
#pragma XLLEXPORT
int i;
double sum = 0;
int size = 3;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
return sum;
}
If I would get it as a FP or OPER, would I be able then to pass it to a function that takes input as array?

figured it out according to this
my addin output was wrong, and my function input was wrong.
static AddIn xai_array_try(
"?xll_array_try", XLL_DOUBLE "O%",
"ARRAY.TRY", "Array",
"STL", "Test Sum Array."
);
double WINAPI xll_array_try(int *rows, int *columns, double *arr) {
#pragma XLLEXPORT
int i;
double sum = 0;
int size = *rows * *columns;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
return sum;
}

Related

Mean function using values from double array displaying wrong values

Very new to C, anyways been coding a program where you enter pairs of doubles which are stored in separate arrays. I have created a function to get the mean of the numbers but when I call it inside main the values are different. Any ideas?
MEAN FUNCTION:
mean(double *arr)
{
double sum = 0.0;
double meanValue = 0.0;
int i;
for (i = 0; i < arr[i]; i++)
{
sum += arr[i];
meanValue = sum / i;
}
printf("\nmean: %.3lf", meanValue);
}
MAIN:
double num1[1001];
mean(num1);
And, I am getting the num1 and num2 values using:
for (k = 0; (scanf_s("%lf,%lf", &num1[k], &num2[k] ) == 2); k++)
The function needs to know how many of the array elements it should process.
mean(double *arr, int size)
{
double sum = 0.0;
double meanValue = 0.0;
int i;
for (i = 0; i < size; i++)
{
sum += arr[i];
}
meanValue = size > 0 ? sum / size : 0;
printf("\nmean: %.3lf", meanValue);
}
The size is the value of k after the input loop is done, so you call it:
mean(num1, k);
Your function needs to pieces of information:
the pointer to the data array;
the size of the array (number of elements).
However, the way you are computing the mean is subjected to bad numeric conditioning (floating point overflow). Here I suggest using the Incremental Averaging instead. Please consider this code:
double mean(double *arr, int num)
{
double res = arr[0];
for (int i = 1; i < num; ++i)
res += (arr[i] - res) / (i+1.0);
return res;
}
Note that I'm assuming you are using a C99 compliant compiler for the integer declaration inside the for loop.

How to handle unknown type of numbers in C? [duplicate]

This question already has answers here:
How to achieve function overloading in C?
(14 answers)
Create a C function that accepts parameters of different data types
(6 answers)
Closed 5 years ago.
I need to write a method to calculate the average of an unknown type of numbers (double, float, int...). I tried to do something like this, but it works for double type only:
double average(void *arr, int length, int bytes) {
int i;
double sum = 0;
double num;
for (i = 0; i < length; i++) {
memcpy(&num, (char *) arr, bytes);
sum += num;
arr = (char *) arr + bytes;
}
return sum / length;
}
Any suggestions?
You can't sum the array values if you don't know what type they are. Relying on the bytes parameter alone is not enough, since int and float are commonly the same size in many compilers, but they are very different types. You lose type information when operating with void*.
If you must use void*, the only way to solve this is to pass in a parameter that specifies what type the array actually holds, and then cast the void* accordingly.
I suggest writing a separate function for each type, eg:
enum dataType {dtInt, dtFloat, dtDouble};
double averageInt(int *arr, int length)
{
double sum = 0;
for (int i = 0; i < length; ++i)
sum += arr[i];
return sum / length;
}
double averageFloat(float *arr, int length)
{
double sum = 0;
for (int i = 0; i < length; ++i)
sum += arr[i];
return sum / length;
}
double averageDouble(double *arr, int length)
{
double sum = 0;
for (int i = 0; i < length; ++i)
sum += arr[i];
return sum / length;
}
double average(void *arr, int length, enum dataType arrType)
{
switch (arrType)
{
case dtInt: return averageInt((int*)arr, length);
case dtFloat: return averageFloat((float*)arr, length);
case dtDouble: return averageDouble((double*)arr, length);
}
return 0;
}
Alternatively:
enum dataType {dtInt, dtFloat, dtDouble};
double sumInt(int *arr, int length)
{
double sum = 0;
for (int i = 0; i < length; ++i)
sum += arr[i];
return sum;
}
double sumFloat(float *arr, int length)
{
double sum = 0;
for (int i = 0; i < length; ++i)
sum += arr[i];
return sum;
}
double sumDouble(double *arr, int length)
{
double sum = 0;
for (int i = 0; i < length; ++i)
sum += arr[i];
return sum;
}
double average(void *arr, int length, enum dataType arrType)
{
double sum;
switch (arrType)
{
case dtInt: sum = sumInt((int*)arr, length); break;
case dtFloat: sum = sumFloat((float*)arr, length); break;
case dtDouble: sum = sumDouble((double*)arr, length); break;
default: sum = 0; break;
}
return sum / length;
}

a value of type "void *" cannot be assigned to an entity of type "int **" last

I'm making a program which dynamically creating 2d array.but it's showing the error which I mentioned on the title. I'm using Visual Studio 2015.
// last.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <time.h>
#include "stdlib.h"
double selectionSort(int * number, int number_count);
void print2d(int ** array, int rows, int cols);
void twodarray();
void main(int argc, char* argv[])
{
int num_count = 10000;
int num[10000];
for (int i = 0; i < num_count; i++)
{
num[i] = rand();
}
double sortTime = selectionSort(num, num_count);
printf("Total Runtime is: %.0f milliseconds. \n", sortTime * 1000);
twodarray();
getchar();
}
double selectionSort(int * number, int number_count)
{
clock_t start, end;
double duration;
int min;
start = clock();
for (int i = 0; i < number_count - 1; i++)
{
min = i;
for (int j = i + 1; j < number_count; j++)
{
if (number[min] > number[j])
{
min = j;
}
}
if (min != i)
{
int temp = number[min];
number[min] = number[i];
number[i] = temp;
}
}
end = clock();
return duration = (double)(end - start) / CLOCKS_PER_SEC;
}
void print2d(int ** array, int rows, int cols)
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0, j < cols; j++;)
{
printf("%10d ", array[i][j]);
}
puts("");
}
}
void twodarray()
{
int **twod;
int rows = 10;
twod = malloc(rows * sizeof(int));
int i,cols = 10;
for (i = 0; i < rows; i++)
{
twod[i] = malloc(cols*sizeof(int));
print2d(twod, rows, cols);
}
for (i = 0; rows; i++)
{
free(twod[i]);
free(twod);
}
}
In c++ you need to cast when assigining a void * pointer to another type of pointer. But in c++ you should not use malloc(), instead use
int **twod = new int *[rows];
If you didn't mean to write a c++ program, rename the file. Change the extension from .cpp to .c.
Your allocation is wrong too, as pointed out by #KeineLust here.
This is wrong:
int **twod;
int rows = 10;
twod = malloc(rows * sizeof(int));
You need to reserve space for n pointers to int, not for n ints, change to
twod = malloc(rows * sizeof(int *));
And here:
for (j = 0, j < cols; j++;)
^ ^
Use a semicolon instead of a comma and also remove the last semicolon.
Another problem:
for (i = 0; rows; i++)
{
free(twod[i]);
free(twod); /* Don't free twod in the loop, one malloc -> one free */
}
And as pointed out by Nicat and Iharob, it seems that you are mixing C and C++, use the proper extension (.c)

Code Bug: Segmentation Fault [EVERYTIME]

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.

Importing functions from other c file without a header

My assignment is to create a program that essentially tests the library I created in another c file. My issue is how I go about calling the library without the header. The library program is:
/*
Program: statlib.c
A Statistical library consisting of the following
seven functions: mean, variance, standard deviation,
sort, minimum value median, and max value.
*/
#include <math.h>
/* Calculates the mean value of the data in the list */
double mean(int totnum, double data[]) {
double meanval, sum;
int i;
sum = 0.0;
for(i=0; i<totnum; i++) {
sum += data[i];
}
meanval = sum/totnum;
return meanval;
}
// Calculate the variance of the data in the list
double variance(int totnum, double data[]) {
double meanval, sum, var;
int i;
meanval = mean(totnum, data);
sum = 0.0;
for(i=0; i<totnum; i++){
sum += (data[i] - meanval)*(data[i] - meanval);
}
var = sum/(totnum-1);
return var;
}
/* Calculate the standard deviation of data in the list */
double stdDeviation(int totnum, double data[]) {
double var, std;
var = variance(totnum, data);
std = sqrt(var);
return std;
}
/* Sorts the array data in ascending order. */
void sort(int totnum, double data[]) {
int i, j;
double temp;
/* find the smallest value in the reaming part of the array
in each iteratio staring with data[i]. */
for(i = 0; i < totnum-1; i++) {
/* compare with data[i] with data[j], swap their values */
for(j = i+1; j < totnum; j++) {
/* when data[i] > data[j], swap their values */
if(data[i] > data[j]) {
temp = data[i];
data[i] = temp;
}
}
}
}
/* Calculates the min value of an array. */
double minValue(int totnum, double data[]) {
double minval;
int i;
/* start at the intial value */
minval = data[0];
for(i = 1; i < totnum; i++) {
if(data[i] < minval) {
minval = data[i];
}
return minval;
}
}
/* Calculate the median of an array. Must be sorted first using the sort
function.*/
double median(int totnum, double data[]) {
double medianval;
if(totnum % 2) {
medianval = data[totnum/2];
}
else {
medianval = (data[totnum/2 -1] + data[totnum/2]/2.0);
}
return medianval;
}
/* Returns the maximum value of an array. */
double maxValue(int totnum, double data[]) {
double maxval;
int i;
maxval = data[0];
for(i = 1; i < totnum; i++) {
if(data[i] > maxval) {
maxval = data[i];
}
}
return maxval;
}
The program that I'm using to test the first program is:
/*
Program: teststatlib.c
This program tests my statlib.c program in order to
verify whether or not it is in working order.
*/
#include <stdio.h>
/* add code from statlib.c */
#pragma importf <statlib.c>
/* Declare extern functions so that the can be used */
extern double mean(int totnum, double data[]);
//extern double variance(int totnum, double data[]);
//extern double stdDeviation(int totnum, double data[]);
//extern void sort(int totnum, double data[]);
//extern double minValue(int totnum, double data[]);
//extern double median(int totnum, double data[]);
//extern double maxValue(int totnum, double data[]);
int main() {
int input[] = {30,90,100,84,72,40,34,91,80,62};
int totnum = sizeof(input)/sizeof(double);
printf("The unsorted array is %d.", input);
printf("The mean is ");
mean(totnum, input);
}
I find your question confusing because you didn't state your problem very well. In fact you never asked a question. Maybe I can still be a little helpful.
A few things that you can fix:
sizeof(input) not sizeof(input[])
the second to last print line does not do what you want. If you remove the [] then it will compile and print the address of the array (which is not what I think you want). You probably want to print each element of the array and you should consider doing it in a for loop. What you have looks very python-esk, but is not how we do things in c.
in your last line, you call mean() as if you expect it print something. I think you want to combine the last two lines to printf("The mean is %f\n", mean(totnum,input));
input needs to be declared as an array of type double. (also, you'll need to change sizeof(int) to sizeof(double) in the line below that)
I managed to compile and run your program in linux with the command gcc teststatlib.c statlib.c. I don't recognize #pragma importf <statlib.c> and that makes me suspect you might be using a development environment that I'm not familiar with.

Resources