C - Calculating statistical values from command line using multithreaded programing - c

I'm a beginner working on a C practice program that can calculate various statistical values for a list of numbers read in from the command line. But when trying to compile my code in Linux, I get a handful of errors that I'm not sure how to interpret, and was wondering if I could get some help from those more familiar with the C language than myself. I've included both my code and the errors below.
My code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int *values;
int size;
double avg=0.0;
int minValue=0;
int maxValue=0;
void *runAvg(void *param);
void *runMin(void *param);
void *runMax(void *param);
int main (int argc, char *argv[]){
if(argc != 2){
fprintf(stderr, "usage: %s <integer value>\n", argv[0]);
}
int i;
for(i=1; i < argc; i++){
values=&(atoi(argv[i]));
size++;
}
pthread_t avgPt[size];
pthread_t minPt[size];
pthread_t maxPt[size];
pthread_attr_t attr;
//create threads
pthread_create(&avgPt, &attr, runAvg, values);
pthread_create(&minPt, &attr, runMin, values);
pthread_create(&maxPt, &attr, runMax, values);
//wait for threads to exit
pthread_join(avgPt, NULL);
pthread_join(minPt, NULL);
pthread_join(maxPt, NULL);
//print results of threads
printf("\n Average: %f \n",avg);
printf("\n Minimum: %d \n",minValue);
printf("\n Maximum: %d \n",maxValue);
}
void *runAvg(void *param){
int sum=0;
int i=0;
int *values;
values=(int*)param;
for(i=0;i<size; i++) sum += values[i];
avg = sum / (double)size;
pthread_exit(0);
}
void *runMin(void *param){
int i=0;
int *values;
values=(int*)param;
minValue = values[0];
for(i=0;i<size;i++){
if(values[i]<minValue){
minValue=values[i];
}
}
pthread_exit(0);
}
void *runMax(void *param){
int i=0;
int *values;
values=(int*)param;
maxValue=values[0];
for(i=0;i<size;i++){
if(values[i] > maxValue){
maxValue = values[i];
}
}
pthread_exit(0);
}
My compile errors:
423assign.c:20: error: lvalue required as unary ‘&’ operand
423assign.c:30: warning: passing argument 1 of ‘pthread_create’ from
incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘pthread_t * __restrict__’
but argument is of type ‘pthread_t (*)[(unsigned int)(size)]’
423assign.c:31: warning: passing argument 1 of ‘pthread_create’ from
incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘pthread_t * __restrict__’
but argument is of type ‘pthread_t (*)[(unsigned int)(size)]’
423assign.c:32: warning: passing argument 1 of ‘pthread_create’ from
incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘pthread_t * __restrict__’
but argument is of type ‘pthread_t (*)[(unsigned int)(size)]’
423assign.c:34: warning: passing argument 1 of ‘pthread_join’ makes
integer from pointer without a cast
/usr/include/pthread.h:244: note: expected ‘pthread_t’ but argument is
of type ‘pthread_t *’
423assign.c:35: warning: passing argument 1 of ‘pthread_join’ makes
integer from pointer without a cast
/usr/include/pthread.h:244: note: expected ‘pthread_t’ but argument is
of type ‘pthread_t *’
423assign.c:36: warning: passing argument 1 of ‘pthread_join’ makes
integer from pointer without a cast
/usr/include/pthread.h:244: note: expected ‘pthread_t’ but argument is
of type ‘pthread_t *’

Your thread functions were okay.
One issue was not allocating an int array to contain the values from atoi.
Also, your pthread_t variables should not be arrays. And your attr value is never initialized and not used.
Here's a cleaned up version with the bugs annotated and fixed [please pardon the gratuitous style cleanup]:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int *values;
int size;
double avg = 0.0;
int minValue = 0;
int maxValue = 0;
void *runAvg(void *param);
void *runMin(void *param);
void *runMax(void *param);
int
main(int argc, char **argv)
{
// NOTE/BUG: this should be "< 2" and not "!= 2"
if (argc < 2) {
fprintf(stderr, "usage: %s <integer value>\n", argv[0]);
exit(1);
}
int i;
--argc;
++argv;
// NOTE/BUG: we must allocate an int array of sufficient size
values = calloc(argc,sizeof(int));
for (i = 0; i < argc; i++) {
values[i] = atoi(argv[i]);
size++;
}
// NOTE/BUG: these should _not_ be arrays
pthread_t avgPt;
pthread_t minPt;
pthread_t maxPt;
// NOTE/BUG: this is unitialized and it's not set to anything, so the
// pthread_create 2nd argument can [and should be] NULL
#if 0
pthread_attr_t attr;
#endif
// create threads
#if 0
pthread_create(&avgPt, &attr, runAvg, values);
pthread_create(&minPt, &attr, runMin, values);
pthread_create(&maxPt, &attr, runMax, values);
#else
pthread_create(&avgPt, NULL, runAvg, values);
pthread_create(&minPt, NULL, runMin, values);
pthread_create(&maxPt, NULL, runMax, values);
#endif
// wait for threads to exit
pthread_join(avgPt, NULL);
pthread_join(minPt, NULL);
pthread_join(maxPt, NULL);
// print results of threads
printf("\n Average: %f \n", avg);
printf("\n Minimum: %d \n", minValue);
printf("\n Maximum: %d \n", maxValue);
}
void *
runAvg(void *param)
{
int sum = 0;
int i = 0;
int *values;
values = param;
for (i = 0; i < size; i++)
sum += values[i];
avg = sum / (double) size;
return (void *) 0;
}
void *
runMin(void *param)
{
int i = 0;
int *values;
values = param;
minValue = values[0];
for (i = 0; i < size; i++) {
if (values[i] < minValue)
minValue = values[i];
}
return (void *) 0;
}
void *
runMax(void *param)
{
int i = 0;
int *values;
values = param;
maxValue = values[0];
for (i = 0; i < size; i++) {
if (values[i] > maxValue)
maxValue = values[i];
}
return (void *) 0;
}

Related

Incorrect local variable value after pthread_join

I am trying to sum up 1000 elements integer array(where each element is 1) with pthread library by splitting the array in to segments of size 10. So effectively, 100 threads are being used to do that. The results of this parallel operation is as expected (1000). But interestingly, the sequential sum which I calculated before creating the threads is being set to zero after my first call to pthread_join(). Not sure if I am missing something here. Can someone spot the bug here?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SEGMENT_SIZE 10
#define NUM_THREADS 100
int *array = NULL;
void* segment_sum(void *args)
{
int index = (int)args;
int sum = 0;
for (int i = index * SEGMENT_SIZE; i < (index + 1) * SEGMENT_SIZE; i++) {
sum += array[i];
}
return (void *)sum;
}
int main()
{
pthread_t thread[NUM_THREADS];
int res = 0;
int seq_res = 0;
int par_res = 0;
array = calloc(1, sizeof(int) * NUM_THREADS * SEGMENT_SIZE);
for (int i = 0; i < NUM_THREADS * SEGMENT_SIZE; i++) {
array[i] = 1;
seq_res += 1;
}
for (int i = 0; i < NUM_THREADS; i++) {
res = pthread_create(&thread[i], NULL, segment_sum, (void *)i);
if (res != 0) {
printf("\nError creating new thread");
}
}
printf("\nindex = %d", seq_res); // the sequential sum here is 1000
for (int i = 0; i < NUM_THREADS; i++) {
int sum = 0;
res = pthread_join(thread[i], (void **)&sum);
if (res != 0) {
printf("\nError creating new thread");
}
printf("\nindex = %d", seq_res); // Here it is becoming zero!!!
par_res += sum;
}
printf("\nmultithreaded sum: %d single threaded sum: %d\n", par_res, seq_res);
}
When you compile your program, try as much as possible to eliminate
the warnings as they often point out non portable behaviors or hidden
errors. Here the compilation points out the following:
pte.c: In function 'segment_sum':
pte.c:11:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
11 | int index = (int)args;
| ^
pte.c:18:16: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
18 | return (void *)sum;
| ^
pte.c: In function 'main':
pte.c:36:69: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
36 | res = pthread_create(&thread[i], NULL, segment_sum, (void *)i);
| ^
The parameter passed to the threads is a cast of a pointer into an "int". It is
advised to pass the address of an "int". Hence, you can define a per-thread
context:
struct thd_ctx {
pthread_t thread;
int index;
int sum;
};
pthread_join() is passed the address of a pointer which will get the address
of the memory location into which the thread stored its result. The thread must
return the address of this memory location, not the value stored into it.
Moreover, the thread should not return the address of an automatic variable
(i.e. in its stack) as it is unspecified. The result must be the address
of a global variable (or "something" visible from the joining thread) returned either directly or through pthread_exit(). In this enhancement of the program, we use the address of the "sum" field in the thread's context:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#define SEGMENT_SIZE 10
#define NUM_THREADS 100
int *array = NULL;
struct thd_ctx {
pthread_t thread;
int index;
int sum;
};
void *segment_sum(void *args)
{
int i;
struct thd_ctx *ctx = (struct thd_ctx *)args;
ctx->sum = 0;
for (i = ctx->index * SEGMENT_SIZE; i < (ctx->index + 1) * SEGMENT_SIZE; i++) {
ctx->sum += array[i];
}
return (void *)&(ctx->sum);
}
int main(void)
{
struct thd_ctx thd_ctx[NUM_THREADS];
int res = 0;
int seq_res = 0;
int par_res = 0;
int i;
array = calloc(1, sizeof(int) * NUM_THREADS * SEGMENT_SIZE);
if (!array) {
fprintf(stderr, "calloc(): error %d\n", errno);
return 1;
}
for (i = 0; i < NUM_THREADS * SEGMENT_SIZE; i++) {
array[i] = 1;
seq_res += 1;
}
for (i = 0; i < NUM_THREADS; i++) {
thd_ctx[i].index = i;
res = pthread_create(&(thd_ctx[i].thread), NULL, segment_sum, (void *)&(thd_ctx[i]));
if (res != 0) {
fprintf(stderr, "Error %d creating new thread#%d\n", res, i);
free(array);
return 1;
}
}
printf("Index = %d\n", seq_res); // the sequential sum here is 1000
for (i = 0; i < NUM_THREADS; i++) {
int *sum = 0;
res = pthread_join(thd_ctx[i].thread, (void **)&(sum));
if (res != 0) {
printf("Error %d joining thread#%d", res, i);
free(array);
return 1;
}
par_res += *sum;
printf("sum = %d\n", par_res);
}
printf("\nMultithreaded sum: %d single threaded sum: %d\n", par_res, seq_res);
free(array);
return 0;
}

My Producer/Consumer C-Code is not giving any real output

I've recently changed my OS from Windows to NitruxOS, and I'm currently struggling a bit with compiling my code.
I tried compiling with:
gcc main.c -Wall -pedantic -std=c99 -D_XOPEN_SOURCE=700 -pthread
but I'm not getting any real output; only the following warning:
*main.c: In function ‘main’: main.c:29:44: warning: ISO C forbids passing argument 3 of ‘pthread_create’ between function pointer and ‘void *’ [-Wpedantic] 29 | pthread_create(&producer[i], NULL, (void*)producer, (void*)&num[i]);
| ^~~~~~~~~~~~~~~ In file included from main.c:4: /usr/include/pthread.h:200:15: note: expected ‘void * (*)(void *)’ but argument is of type ‘void *’ 200 | void *(*__start_routine) (void *),
| ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~ main.c:34:44: warning: ISO C forbids passing argument 3 of ‘pthread_create’ between function pointer and ‘void *’ [-Wpedantic] 34 | pthread_create(&consumer[i], NULL, (void*)consumer, (void *)&num[i]);
| ^~~~~~~~~~~~~~~ In file included from main.c:4: /usr/include/pthread.h:200:15: note: expected ‘void * (*)(void *)’ but argument is of type ‘void *’ 200 | void *(*__start_routine) (void *),*
My code is as follows:
#include <stdlib.h>
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#define max 10
#define bufferlen 10
sem_t voll;
sem_t leer;
int input = 0;
int output = 0;
int buffer[bufferlen];
pthread_mutex_t mutex;
int main()
{
pthread_t producer[bufferlen], consumer[bufferlen];
pthread_mutex_init(&mutex, NULL);
sem_init(&voll, 0, 0);
sem_init(&leer, 0, bufferlen);
int num[max] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(int i = 0; i < 10; i++)
{
pthread_create(&producer[i], NULL, (void*)producer, (void*)&num[i]);
}
for(int i = 0; i < 10; i++)
{
pthread_create(&consumer[i], NULL, (void*)consumer, (void *)&num[i]);
}
for(int i = 0; i < 10; i++)
{
pthread_join(producer[i], NULL);
}
for(int i = 0; i < 10; i++)
{
pthread_join(consumer[i], NULL);
}
pthread_mutex_destroy(&mutex);
sem_destroy(&leer);
sem_destroy(&voll);
return 0;
}
void *producer(void *pptr)
{
int item = 0;
for (int i = 0; i < max; i++)
{
sem_wait(&leer);
pthread_mutex_lock(&mutex);
buffer[input] = item;
printf("Der Producer No. %d hat %d an Stelle %d eingefügt\n", *((int*)pptr), buffer[input], input);
input = (input + 1) % bufferlen;
pthread_mutex_unlock(&mutex);
sem_post(&voll);
}
return NULL;
}
void *consumer(void *cptr)
{
for(int i = 0; i < max; i++)
{
sem_wait(&voll);
pthread_mutex_lock(&mutex);
int item = buffer[output];
printf("Der Consumer No. %d hat %d von Stelle %d entfernt\n", *((int*)cptr), item, output);
output = (output + 1) % bufferlen;
pthread_mutex_unlock(&mutex);
sem_post(&leer);
}
return NULL;
}

how to return an array from a pthread

I've been trying to get an array of ints back from a thread. I think I'm really close. The errors I'm getting are about dereferencing a void pointer and invalid use of a void expression here
assn3.c:29:29: error: dereferencing ‘void *’ pointer [-Werror]
printf(" %d", (int)answer[j]);
^
assn3.c:29:18: error: invalid use of void expression
printf(" %d", (int)answer[j]);
I've tried changing the return type of my functions to int* but it didn't seem to like that. What am I missing here?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *getFactors(void *param);
int main(int argc, char *argv[])
{
for(int i = argc; i > 0; i--)
{
void *answer;
pthread_t tid;
pthread_attr_t attr;
if (atoi(argv[i])<0)
{
fprintf(stderr, "%d must be > 0\n", atoi(argv[i]));
return -1;
}
pthread_attr_init(&attr);
pthread_create(&tid, &attr, getFactors, argv[i]);
pthread_join(tid, &answer);
printf("%d", atoi(argv[i]));
printf(":");
for(int j = 0; j < sizeof(answer); j++)
{
printf(" %d", (int)answer[j]);
}
printf("\n");
}
}
And the thread function
void *getFactors(void *param)
{
int a[10];
int n = atoi(param);
int i = 0;
while (n%2 == 0)
{
a[i] = 2;
n/=2;
i++;
}
int f=3;
while (f * f <= n)
{
if (n % f == 0)
{
a[i]=f;
n /= f;
i++;
}
else
{
f += 2;
}
}
if (n<1)
{
a[i]=n;
i++;
}
int* buffer = (int*) malloc(i);
buffer = a;
return (void *) buffer;
pthread_exit(0);
}
void *answer;
...
int * answer_beeing_an_int_arr = answer;
printf(" %d", answer_beeing_an_int_arr[j]);
This is what you want. But you find that:
printf(" %d", (int)answer[j]);
does not work. Why you ask? It's because the cast (int) has lower precedence than the array subscript [j], and also you don't tell the compiler that answer is a pointer to ints, only that it should first get the value, then cast to int. You want this:
printf(" %d", ((int*)answer)[j]);
You want to tell the compiler, that the answer is a pointer to int. Then you want to add to that that pointer sizeof(int) * j bytes and dereference it.
And remember to free(answer).
Now to your code:
buffer = a;
is wrong. It assigns the pointer to another pointer. You want to copy the values behind the pointers, not pointers themselves. You need:
memcpy(buffer, a, sizeof(int) * i);
or
for (size_t j = 0; j < i; ++j) {
buffer[j] = a[j];
}
to copy array values.
... = malloc(i);
This will allocate i bytes. An int does not have 1 byte (CHAR_BIT bits, probably 8). It has more. It can be 2, can be more. sizeof(int) will tell you how many bytes an int has. So it has to be:
int *buffer = malloc(i * sizeof(int));
or as I like it:
int *buffer = malloc(i * sizeof(*buffer));
Also:
int* buffer = (int*) malloc(i);
...
return (void *) buffer;
No need to cast a pointer to void* and from void*. void* is a generic pointer, it's a pointer to nothing. Just:
int* buffer = malloc(i * sizeof(*buffer));
...
return buffer;
There are several things wrong here:
for(int j = 0; j < sizeof(answer); j++) // This will NOT tell you the #/elements in the array
pthread_join() is probably not the best way to pass back your integer buffer
And, of course, printf(" %d", (int)answer[j]); is a compile error :(
SUGGESTION:
Read through this tutorial, and restructure your code accordingly:
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
Or you can scan through this:
http://www.cs.kent.edu/~ruttan/sysprog/lectures/multi-thread/multi-thread.html
There are a few things you need to correct as pointed earlier.
As pointed, do not use a local variable as a return address. It will not be accessible when the thread returns. It is better to use a global variable and allocate memory dynamically. You can free it in the function which has created the thread.
For accessing variables which are changed by a thread, you can either pass it to the thread function using the fourth argument in pthread_create(3) and later access it. Or access it using pthread_join as a return value.
Might need to use a mutex or other synchronization primitives if multiple threads are accessing the variable.
One simple example of returning an array using pthread_join(3) is given below.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#define ARRAY_LEN 10
void *functionPthread(void *);
int *retArray;
int main()
{
int rc, i;
pthread_t th;
retArray = (int*) malloc(sizeof(int) *ARRAY_LEN);
if(rc = pthread_create(&th, NULL, &functionPthread, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc, errno);
}
pthread_join(th, (void**)&retArray);
for(i = 0; i < ARRAY_LEN; i++)
printf("%d ", retArray[i]);
printf("\n");
free(retArray);
return 0;
}
void *functionPthread(void *)
{
int i;
for(i = 0; i < ARRAY_LEN; i++)
retArray[i] = i;
return retArray;
}

Passing array pointer into function in C

I'm working in C, and I'm trying to pass in a pointer to an array that will hold my thread ids, but I cannot seem to get my types to match. What am I not understanding about passing pointers in C?
This is my function:
int createThreads(int numThreads, pthread_t **tidarray) {
pthread_t *tids = *tidarray;
int i;
for (i = 0; i < numThreads; i++) {
pthread_create(tids + i, NULL, someFunction, NULL);
}
return 0;
}
And this is my call:
pthread_t tids[numThreads];
createThreads(5, &tids);
When I compile this, I get a warning:
Passing argument 2 of 'createThreads' from incompatible pointer type, and
Note: expected 'pthread_t **' but argument is of type 'pthread_t (*) [(long unsigned int)(numThreads)]'
#include <stdio.h>
#include <pthread.h>
// dummy function for threads , it just print its argument
void * someFunction(void *data){
printf("Thread %d\n",(int)data);
}
int createThreads(int numThreads, pthread_t *tidarray) {
int i;
for (i = 0; i < numThreads; i++) {
//pass the pointer of the first element + the offset i
pthread_create(tidarray+i, NULL, someFunction, (void*)i);
}
return 0;
}
int main(){
pthread_t tids[5]={0};// initialize all to zero
createThreads(5, tids);
getchar();// give time to threads to do their job
// proof-of-concept, the array has been filled by threads ID
for(int i=0;i<5;i++)
printf("Thread (%d) ID = %u\n",i,tids[i]);
return 0;
}
You don't need the & address of operator, just pass it as it is because it's converted to a pointer automatically, so
createThreads(5, tids);
is what you need, and then your createThreads() function
int createThreads(int numThreads, pthread_t *tids)
{
int i;
for (i = 0; i < numThreads; i++)
{
pthread_create(tids + i, NULL, someFunction, NULL);
}
return 0;
}

Problems passing struct pointers and "conflicting types" errors

I am writing a program that permutes a list of names based on a given input. Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 19 //names no longer than 19 chars
#define MAXPEOPLE 10
struct genderinfo {
char** winning;
char** names;
int** scores;
};
char** allocnames(int num);
int** allocratings(int num, int num2);
void inputdata(int numpeople, struct genderinfo *male, struct genderinfo *female, FILE* fp);
void permute(int permuteset[], int k, int numpeople, struct genderinfo *male, struct genderinfo *female, int *maxLindex);
void swap(int permuteset[],int i, int j);
void compare(int permuteset[], struct genderinfo *male, struct genderinfo *female, int *maxLindex, int numpeople);
///write free functions for struct arrays
int main () {
FILE* fp = fopen("matching.txt", "r");
struct genderinfo male;
struct genderinfo female;
//loop variables
int numdates, i, j, k;
//other variables
int numpeople, maxLindex = 0, difference;
fscanf(fp, "%d", &numdates);
for(i=1; i <= numdates; i++) {
fscanf(fp, "%d", &numpeople);
//printf("%d possible couples\n", numpeople);
//allocate memory for arrays of names
male.names = allocnames(numpeople);
female.names = allocnames(numpeople);
male.winning = allocnames(numpeople);
female.winning = allocnames(numpeople);
//allocate memory for score arrays
male.scores = allocratings(numpeople, numpeople);
female.scores = allocratings(numpeople, numpeople);
int permuteset[numpeople];
//fill permute set with 0-k, these will serve as array indexes to compare against malenames array
//format used will be malenames[i][permuteset[i]] femalenames[permuteset[i]][i] to index the scores
for(k=0; k<numpeople; k++)
permuteset[k] = k;
inputdata(numpeople, &male, &female, fp);
permute(permuteset, 0, numpeople, &male, &female &maxLindex);
printf("Matching #%d: Maximum Score = %d\n\n", i, maxLindex);
for (j=0; j<numpeople; j++){
printf("%s %s\n", male.winning[j], female.winning[j]);
}
printf("\n\n");
}
return 0;
}
char** allocnames(int num) {
int i;
char** names = (char**)malloc(num*sizeof(char*));
for(i=0; i < num; i++)
names[i] = (char*)malloc(MAX_LEN+1);
return names;
}
int** allocratings(int num, int num2) {
int i;
int** ratings = (int**)malloc(num*sizeof(int*));
for(i=0; i < num; i++)
ratings[i] = (int*)malloc(num2*sizeof(int));
return ratings;
}
void inputdata(int numpeople, struct genderinfo *male, struct genderinfo *female, FILE* fp) {
int i, j;
for (i=0; i < numpeople; i++) {
fscanf(fp, "%s", male->names[i]);
//printf("%s ", malenames[i]);
}
for (i=0; i < numpeople; i++) {
fscanf(fp, "%s", female->names[i]);
//printf("%s ", femalenames[i]);
}
for (i=0; i < numpeople; i++) {
for (j=0; j < numpeople; j++) {
fscanf(fp, "%d", &male->scores[i][j]);
//printf("%d ", malescores[i]);
}
}
for (i=0; i < numpeople; i++) {
for(j=0; j < numpeople; j++) {
fscanf(fp, "%d", &female->scores[i][j]);
//printf("%d ", femalescores[i][j]);
}
}
}
void permute(int permuteset[], int k, int numpeople, struct genderinfo *male, struct genderinfo *female, int *maxLindex) {
int i;
if (k == numpeople) {
compare(permuteset, &male, &female, &maxLindex, numpeople);
}
else {
// Loop through each possible starting letter for index k,
// the first index for which we have a choice.
for (i=k; i<numpeople; i++) {
// Place the character stored in index j in location k.
swap(permuteset, k, i);
// Print out all of the permutations with that character
// just chosen above fixed.
permute(permuteset, 0, numpeople, &male, &female &maxLindex);
// Put the original character that used to be there back
// in its place.
swap(permuteset, i, k);
} //end i for
} //end else
}
void swap(int permuteset[], int i, int j) {
int temp = permuteset[i];
permuteset[i] = permuteset[j];
permuteset[j] = temp;
}
//This function will take a permutation in and compare malescores[i] to
//femalescores[permuteset[i]]
//if malescores[i] > femalescores[permuteset[i]] scoresum += bla blah else if.... etc.
//copy malenames[i] and femalenames[permuteset[i]] into winning couples
//with if statements above
//malescores[i][permuteset[i]]
//femalescores[permuteset[i]][i]]
void compare(int permuteset[], struct genderinfo *male, struct genderinfo *female, int *maxLindex, int numpeople) {
int temp_maxLindex, i, j, minlike;
for(i=0; i<numpeople; i++){
if (male->scores[i][permuteset[i]] > female->scores[permuteset[i]][i])
minlike = female->scores[permuteset[i]][i];
else
minlike = male->scores[permuteset[i]][i];
temp_maxLindex += minlike;
if (temp_maxLindex > maxLindex) {
maxLindex = temp_maxLindex;
for(j=0; j<numpeople; j++){
strcpy(male->winning[j], male->names[i]);
strcpy(female->winning[j], female->names[permuteset[i]]);
} //j for
} //if
} //i for
}
I am getting these errors, one having to do with what im passing into my inputdata function, and a bunch of others about conflicting types?? I have been tinkering around with the code for a bit now and can't get anywhere. At this point I'm just trying to get the code to run so I can debug the algorithm and whatnot, any help is appreciated greatly.
D:\School\Summer 2012\CS1\Assignments\2\main.c||In function 'main':|
D:\School\Summer 2012\CS1\Assignments\2\main.c|61|error: invalid operands to binary & (have 'struct genderinfo *' and 'int')|
D:\School\Summer 2012\CS1\Assignments\2\main.c|61|error: too few arguments to function 'permute'|
D:\School\Summer 2012\CS1\Assignments\2\main.c|17|note: declared here|
D:\School\Summer 2012\CS1\Assignments\2\main.c|35|warning: unused variable 'difference' [-Wunused-variable]|
D:\School\Summer 2012\CS1\Assignments\2\main.c||In function 'permute':|
D:\School\Summer 2012\CS1\Assignments\2\main.c|139|warning: passing argument 2 of 'compare' from incompatible pointer type [enabled by default]|
D:\School\Summer 2012\CS1\Assignments\2\main.c|19|note: expected 'struct genderinfo *' but argument is of type 'struct genderinfo **'|
D:\School\Summer 2012\CS1\Assignments\2\main.c|139|warning: passing argument 3 of 'compare' from incompatible pointer type [enabled by default]|
D:\School\Summer 2012\CS1\Assignments\2\main.c|19|note: expected 'struct genderinfo *' but argument is of type 'struct genderinfo **'|
D:\School\Summer 2012\CS1\Assignments\2\main.c|139|warning: passing argument 4 of 'compare' from incompatible pointer type [enabled by default]|
D:\School\Summer 2012\CS1\Assignments\2\main.c|19|note: expected 'int *' but argument is of type 'int **'|
D:\School\Summer 2012\CS1\Assignments\2\main.c|153|error: invalid operands to binary & (have 'struct genderinfo **' and 'int *')|
D:\School\Summer 2012\CS1\Assignments\2\main.c|153|warning: passing argument 4 of 'permute' from incompatible pointer type [enabled by default]|
D:\School\Summer 2012\CS1\Assignments\2\main.c|133|note: expected 'struct genderinfo *' but argument is of type 'struct genderinfo **'|
D:\School\Summer 2012\CS1\Assignments\2\main.c|153|error: too few arguments to function 'permute'|
D:\School\Summer 2012\CS1\Assignments\2\main.c|133|note: declared here|
D:\School\Summer 2012\CS1\Assignments\2\main.c||In function 'compare':|
D:\School\Summer 2012\CS1\Assignments\2\main.c|194|warning: comparison between pointer and integer [enabled by default]|
D:\School\Summer 2012\CS1\Assignments\2\main.c|195|warning: assignment makes pointer from integer without a cast [enabled by default]|
||=== Build finished: 10 errors, 7 warnings ===|
--- permute.c.OLD 2012-06-14 22:48:06.760926525 +0200
+++ permute.c 2012-06-14 22:47:37.344810744 +0200
## -21,7 +21,7 ##
///write free functions for struct arrays
-int main () {
+int main (void) {
FILE* fp = fopen("matching.txt", "r");
## -32,7 +32,7 ##
int numdates, i, j, k;
//other variables
-int numpeople, maxLindex = 0, difference;
+int numpeople, maxLindex = 0; // difference;
fscanf(fp, "%d", &numdates);
## -58,7 +58,7 ##
permuteset[k] = k;
inputdata(numpeople, &male, &female, fp);
- permute(permuteset, 0, numpeople, &male, &female &maxLindex);
+ permute(permuteset, 0, numpeople, &male, &female, &maxLindex);
printf("Matching #%d: Maximum Score = %d\n\n", i, maxLindex);
## -136,7 +136,7 ##
if (k == numpeople) {
- compare(permuteset, &male, &female, &maxLindex, numpeople);
+ compare(permuteset, male, female, maxLindex, numpeople);
}
else {
## -150,7 +150,7 ##
// Print out all of the permutations with that character
// just chosen above fixed.
- permute(permuteset, 0, numpeople, &male, &female &maxLindex);
+ permute(permuteset, 0, numpeople, male, female, maxLindex);
// Put the original character that used to be there back
// in its place.
## -191,8 +191,8 ##
temp_maxLindex += minlike;
- if (temp_maxLindex > maxLindex) {
- maxLindex = temp_maxLindex;
+ if (temp_maxLindex > *maxLindex) {
+ *maxLindex = temp_maxLindex;
for(j=0; j<numpeople; j++){
Summary: missing kommaas, too many ampersands, missing asterixes.
I have not checked for semantic errors, I presume they are still present. (the unbounded recursive call in permute() looks suspect)
I also advise to remove the casts from malloc()s return value and use the idiom p = malloc N * sizeof *p); But that would increase the size of the diff even more.
I am only guessing here as the code that is causing the error is not given by you at time of posting this, but as the list of your parameters to these functions
void permute(int permuteset[], int k, int numpeople, char** winningmales, char** winningfemales, char** malenames, char** femalenames, int** malescores,
int** femalescores, int *maxLindex);
void compare(int permuteset[], char** winningmales, char** winningfemales, char** malenames, char** femalenames, int** malescores, int**femalescores,
int *maxLindex, int numpeople);
is very large and as you report an error between an int* and int** I wonder if you have accidentally got the order of your arguments wrong in the places that you call the above functions???
As I say this is only a guess but it might be worth investigating.

Resources