accessing values in a struct array - c

I am passing in an array into a function straightflush. I use a counting loop so i can get to all of the elements but for some reason, even tho the counter i increases, i get the value and suit for the first element of the array. Therefore, only my spadesCount increases as it always shows 4 for the value and spade for the suit.
struct card{
int value;
char suit;
};
int straightflush(struct card hand[], int n)
{
int clubsCount = 0;
int diamondsCount = 0;
int heartCount = 0;
int spadesCount =0;
int i;
for(i=0; i<n; i++)
{
if (hand[i].suit == 'c')
{
clubsCount++;
}
else if (hand[i].suit == 'd')
{
diamondsCount++;
}
else if (hand[i].suit == 'h')
{
heartCount++;
}
else{
spadesCount++;
}
}
return 0;
}
here is my main:
int main(){
struct card hand1[] = {{4,'s'}, {9,'s'},{12,'c'},{11,'s'},{8,'s'},
{6,'d'}, {3,'d'},{7,'s'},{10,'s'},{12,'d'}};
printf ("%d\n", straightflush(hand1, 10));
}

I just run your code and the four count variables have correct values. I think it's because you are returning 0 at the end of your straightflush function, the output is always 0.

You can use a debugger or add the following line before the return statement in straightflush() to prove that your counts are actually accurate.
printf("%d %d %d %d\n", clubsCount, diamondsCount, heartCount, spadesCount);
Your return value has nothing to do with the values you read thus the printf statement in your main() function is not printing the count of any thing, it is just printing 0 no matter what.
If you want the counts accessible outside of striaghtflush() you need to either use global variables for those counts (a generally shunned idea) or pass some values in by reference. An example of this would be:
#include <stdio.h>
#include <stdlib.h>
void editValues( int *numDiamonds, int *numClubs, int *numHearts, int *numSpades ){
*numDiamonds = 3;
*numClubs = 5;
*numHearts = 7;
*numSpades = 11;
}
int main(int argc,char**argv)
{
int numD=0, numC=1, numH=2, numS=3;
printf("%d %d %d %d\n", numD, numC, numH, numS);
editValues(&numD, &numC, &numH, &numS);
printf("%d %d %d %d\n", numD, numC, numH, numS);
return 0;
}

Related

Changing the value of a variable with pointers not working

Basically I have a function called MinSubTab that is supposed to calculate the sum of the array passed and also to change the value passed in the first argument from inside the function without using return. This is done with pointers. Anyway, I think it'd be easier if I just showed you the code so here it is:
maintab.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "tab.h"
int main(){
int *reftab;
int min;
reftab = (int *)malloc(sizeof(int) * NMAX);
InitTab(reftab,NMAX);
printf("\n Total: %d et min: %d", MinSumTab(&min, reftab, NMAX), min);
free(reftab);
return 0;
}
tab.c
void InitTab(int *tab, int size){
srand(time(NULL));
for (int i=0; i<size; i++){
*(tab+i) = rand() % 10;
}
}
int MinSumTab(int *min, int *tab, int size){
int total=0;
int minimum = NMAX;
int temp = *min;
for (int i=0; i<size; i++){
total += *(tab+i);
}
for (int i=0; i<size; i++){
if(*(tab+i)<minimum){
minimum = *(tab+i);
}
}
*min = minimum;
return total;
}
So the expected result here is that the sum is printed (which it is) and the minimum value of the array is printed (which it is not). Every single time the min variable equals 8 and I've no idea how to actually change the value of min from within that function.
Please help as my brain has no more capacity for rational thought, it's been 1.5 hrs and no solution in sight. Thanks
Looks like a small mistake:
You initialize minimum with NMAX, which I assume is 8 (the size of the array). 99.9% of the random numbers will be bigger. So 8 is chosen as the minimum.
What you really want is to initialize it with RAND_MAX – the maximum value rand() can return.
In C order of evaluation and argument passing is undefined.
You can of course the order yourself but it only to feed your curiosity.
#include <stdio.h>
volatile char *message[] = {
"fisrt", "second", "third", "fourth"
};
int print(size_t x)
{
printf("%s\n", message[x]);
return x;
}
int main()
{
printf("%d %d %d %d\n", print(0), print(1), print(2), print(3));
return 0;
}
Note. There is one exception from this rule.
Logical operators are evaluated form the left to the right.
if( x != NULL && *x == 5)is safe because x will not be dereferenced if it is NULL

Segmentation fault when trying to add elements of an array

I'm trying to create a function that returns as its result the sum of the elements in the array. When I try to run the program, I get a segmentation fault. Could someone please point me in the right direction? Thank you!
int arraySum (int array[], int numberOfElements) {
int result = 0;
for (int i = 0; i < numberOfElements; i++)
{
result += array[i];
}
return result;
}
int main (void) {
int numberOfElements;
int *array = NULL;
printf("How many elements would you like in your array: ");
scanf("%i", &numberOfElements);
printf("\nPlease list the values of the elements in the array: ");
for (int i = 0; i < numberOfElements; i++)
{
scanf("%i", &array[i]);
}
int result = arraySum(array, numberOfElements);
return result;
}
The problem you have is, that in C you need to manually allocate the memory if you are using a pointer instead of say a fixed-size array.
This is usually done by calling malloc, which will return a void-pointer (void*), which you need to cast to the desired type (in your case (int*)) before assigning it.
It is also important to note, that, when using malloc, you need to specify the amount of Bytes you want to allocate. This means that you can't just call it with the number of integers you want to store inside, but rather have to multiply that number with the amount of Bytes that one integer occupies (which depends on the Hardware and Operating System you use, hence you should use sizeof(int) for that purpose, which evaluates to that size at compile time).
I modified your code with a working example of how it could be done:
#include <stdio.h>
#include <stdlib.h>
int arraySum (int array[], int numberOfElements) {
int result = 0;
int i;
for (i = 0; i < numberOfElements; i++) {
result += array[i];
}
return result;
}
int main(int argc, char **argv) {
int numberOfElements;
int *array = NULL;
printf("How many elements would you like in your array: ");
scanf("%i", &numberOfElements);
array = (int*) malloc(numberOfElements * sizeof(int));
printf("\nPlease list the values of the elements in the array: ");
int i;
for (i = 0; i < numberOfElements; i++) {
scanf("%i", &array[i]);
}
int result = arraySum(array, numberOfElements);
printf("\n\nThe result is: %d\n", result);
return 0;
}
You are also trying to return the result in your main function, but the return value of main in C is used to signal whether your program terminated without errors (signalled by a return value of 0) or didn't encounter any issues (any value other than 0).
You need to allocate memory. It is not enough to just declare a pointer. You do it like this: array=malloc(numberOfElements*sizeof(*array));
Also, although it is possible to return result from the main function, you should not do that. The return value from main is usually used for error checking. Change the end of your program to
printf("Sum: %d\n", result);
return 0;
Returning 0 usually means that no error occurred.

How to implement a running variable in a recursive function

At the moment I am coding a program in which I need a variable count that increments every time I call the function. In my case I have a recursive function and want to know how many iterations the program does.
I simplified the code by computing the factorial of a number.
My first approach does not work and ends up with warning messages:
#include <stdio.h>
int factorial(unsigned int i, int *count)
{
*count += 1;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, &count);
}
int main()
{
int i = 10;
int count = 0;
printf("%d Iterations, Factorial of %d is %d\n", count, i, factorial(i, &count));
return 0;
}
warning: passing argument 2 of ‘factorial’ from incompatible pointer type
My second approach does not work either but also does not ends up with any warning messages.
#include <stdio.h>
int factorial(unsigned int i, int count)
{
count += 1;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, count);
}
int main()
{
int i = 10;
int count = 0;
printf("%d Iterations, Factorial of %d is %d\n", count, i, factorial(i, count));
return 0;
}
How can I make it run? Any ideas? I use Ubuntu and gcc.
There is no need for static variables, as other solutions suggest. The following is correct:
int factorial(unsigned int i, int *count)
{
*count += 1;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, count);
}
int main(void)
{
int i = 10;
int count = 0;
printf("%d Iterations, Factorial of %d is %d\n", count, i, factorial(i, &count));
return 0;
}
One note: as the order of parameter evaluation in the printf statement is not guaranteed, as I understand it the value of count in the call to printf may either be zero (it is passed before factorial was called) or may be 10 (the value after factorial was called). Therefore, main could better be written as:
int main(void)
{
int i = 10;
int count = 0;
int fact= factorial(i, &count);
printf("%d Iterations, Factorial of %d is %d\n", count, i, fact);
return 0;
}
6.5.2.2 Function calls: 10 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
In your first case, factorial() function, count is of type int *. So, while calling the function recursively (in the return statement), do not pass address of count, just pass the count itself.
That said, as count is to be modified in the function call of factorial(), don't pass both of them (the variable and the function call which modifies the variable) in the same argument list as there is no sequence point in the elements passed as argument list, so you'll end up invoking undefined behavior.
Declare the count variable as static inside the factorial function itself.
static int count = 0;
There are two ways of solving this problem.
Declare a static variable in the recursive function to count the no of times it is called.
e.g.
int factorial(unsigned int i, int *count)
{
static int count2;
*count = ++count2;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, count);
}
int main()
{
int i = 10;
int count = 0, fact;
fact = factorial(i, &count);
printf("%d Iterations, Factorial of %d is %d\n", count, i, fact);
return 0;
}
Have count as a pointer to integer, which can then be updated in each function to find the number of iterations.
e.g.
int factorial(unsigned int i, int *count)
{
(*count)++;
// Remaining lines the same as first solution.
}
The second solution will only work in some special types of recursive functions where the first function calls the second and the second calls the third, etc. It will not work for example in a recursive fibbonaci sequence algorithm.
The first solution is a more general one, and will work for all conditions.

C: on calculating the array length with the integer type pointer parameter

I wrote a short code which calculates mean value from an integer array. I first created a header file named mean.h which is as follows.
#ifndef MEAN_H
#define MEAN_H
double mean(int *inputs) {
int i = 0;
int len;
while((inputs[i]) != '\0') {
++i;
}
len = i;
for(i=0; i<len; i++) {
printf("%d ", *(inputs+i));
}
printf("\n");
int sum = 0;
printf("input length: %d\n", len);
for(i=0; i<len; i++) {
sum += *(inputs+i);
}
double mean = sum / len;
return mean;
}
#endif
Then, in order to check if the code is working fine, I created another code named test.c.
#include <stdio.h>
#include "mean.h"
int main(int argc, char **argv) {
int arr[5] = {94, 28, 54, 72, 89};
double meanVal = mean(arr);
int arrlen = sizeof(arr) / sizeof(arr[0]);
printf("Input length: %d\n", arrlen);
printf("Inputs: ");
int i;
for(i=0; i<5; i++) {
printf("%d ", *(arr+i));
}
printf("\n");
printf("Mean: %lf\n", meanVal);
return 0;
}
When I compiled and ran the code, it showed a really strange result like this..
94 28 54 72 89 32767 2123416711 352349365 1594502056 32767 -1876691539 32767 -1876691539 32767
input length: 14
Input length: 5
Inputs: 94 28 54 72 89
Mean: 22644032.000000
The first five elements were printed out with no problem, but I still cannot figure out where the other next 9 elements came from. I believe that probably it's this code snippet that's not proper.
while((inputs[i]) != '\0') {
++i;
}
In this case, how should I modify this in order to calculate the array length with the pointer variable parameter?
It's been pointed out in the comments that C arrays are not automatically null terminated. You have to do it yourself.
Unfortunately, this technique won't work for what you're doing. In an array of integers, null is indistinguishable from 0. Your mean function will not be able to take the mean of anything with a 0 in it. Instead it will think the list is done.
There's alternative techniques to deal with this. First is to have the caller pass in the length of the array. This is how main works. int main(int argc, char *argv[]). As you can imagine, this is inconvenient and error prone.
A better one is to use an array of floats or doubles. These allow some special values such as INFINITY and NAN (not a number). You can use NAN as your array terminator and isnan to check for it.
for( i = 0; !isnan(inputs[i]); i++ ) {
printf("%.2lf ", inputs[i]);
}
printf("\n");
Beyond that, you'd declare a struct which can remember its length.
struct {
int *array;
size_t length;
};
Then you'd have to remember to keep that length always up to date. Rather than going down that rabbit hole, it's better to use a pre-existing C library which provides this such as Gnome Lib. It provides all sorts of missing pieces for C including arrays that remember their size and can grow automatically.
#include <stdio.h>
#include <glib.h>
double mean(GArray *nums) {
int i = 0;
int sum = 0;
for( i = 0; i < nums->len; i++) {
sum += g_array_index(nums, int, i);
}
return sum / nums->len;
}
int main(int argc, char **argv) {
int _nums[] = {94, 28, 54, 72, 89};
GArray *nums = g_array_new(FALSE, FALSE, sizeof(int));
g_array_append_vals(nums, _nums, 5);
double meanVal = mean(nums);
int i;
for( i = 0; i < nums->len; i++ ) {
printf("%d ", g_array_index(nums, int, i));
}
printf("\n");
printf("Mean: %.2lf\n", meanVal);
g_array_free(nums, TRUE);
return 0;
}

My rand() function didn't work

this is my function: i need that every number that get random will be: one bigger than 50, one even, and one not even. i complied just with gcc and i'm using c99. It compiled well, but it when it print three random numbers it's print 0,0,and real random number. I want it to print for me three real numbers. thanks for who trying to help!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define HIGH_NUMBER 100
int isValidNumbers(int num1,int num2, int num3);
int main(void)
{
srand (time(NULL));
int num1 = 0;
int num2 = 0;
int num3 = 0;
num1,num2,num3 =isValidNumbers(num1,num2,num3);
printf("%d %d %d\n",num1,num2,num3);
system("PAUSE");
return 0;
}
int isValidNumbers(int num1,int num2, int num3)
{
int i=1,ans = 0;
do
{
srand (time(NULL));
num1 = rand()%HIGH_NUMBER;
num2 = rand()%HIGH_NUMBER;
num3 = rand()%HIGH_NUMBER;
if ((num1%2==0||num2%2||num3%2==0)&&(num1%2==1||num2%2==1||num3%2==1)&&(num1>50||num2>50||num3>50))
{
return num1,num2,num3;
i--;
printf("%d %d %d",num1,num2,num3);
}
}
while (i);
}
Your function does not set the calling variables as you hoped for. You can't return more than one function value - and it makes no difference that you gave the same names to the variables in main and in the function - they are different variables, and as you wrote it, main just passes copies of those variable values.
Instead I pass pointers to those variables in this example. I also removed the return value of the function, since it now always returns valid values as your spec.
I removed srand within the function. It should be called once only, especially as I call the function 3 times in this example to show different results. If left in the function, all 3 calls would probably give the same result (unless a one-second timer boundary is bridged).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define HIGH_NUMBER 100
void ValidNumbers(int *num1, int *num2, int *num3); // pointer arguments
int main(void)
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
int tries;
srand ((unsigned)time(NULL)); // call once
for(tries=0; tries<3; tries++) {
ValidNumbers(&num1, &num2, &num3);
printf("%-2d %-2d %-2d\n", num1, num2, num3);
}
return 0;
}
void ValidNumbers(int *num1, int *num2, int *num3)
{
do {
*num1 = rand() % HIGH_NUMBER; // write through pointer of passed var
} while (*num1 <= 50); // number > 50
do {
*num2 = rand() % HIGH_NUMBER;
} while (*num2 % 2 != 0); // even number
do {
*num3 = rand() % HIGH_NUMBER;
} while (*num3 % 2 == 0); // odd number
}
Program output:
79 16 79
95 2 37
73 28 93
Returning multiple values is not allowed in C. So
return num1,num2,num3;
this will not work.
You can use a struct with 3 numbers and return that instead. You can go through this for an example of how do go about it.
Also note that the statement inside if after the return statement will never get executed, and are thus useless..
return num1,num2,num3;
i--; // <-- this will never get executed
printf("%d %d %d",num1,num2,num3); // <-- this will never get executed
There are two ways in C to return multiple parameters
One is mentioned above using 1 struct to hold all the return values inside struct.
Another is using pointer/address to hold the values.
I revised the script to show both ways. I will add a positive comment for HelloWorld, you guys are too harsh, it is an important concepts in c:
#include <stdlib.h>
#include <stdio.h>
#define HIGH_NUMBER 100
typedef struct Random Random;
Random *isValidNumbers(int *num1,int *num2, int *num3);
struct Random{
int a;
int b;
int c;
};
int main(void)
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
/* pr to use as parameter, rr used as a return struct , just for demoo purpuse*/
Random *p;
p = isValidNumbers(&num1,&num2,&num3);
printf("%d %d %d main return random numbers\n",num1,num2,num3);
printf("%d %d %d main return from struct \n",p->a,p->b,p->c);
return 0;
}
Random *isValidNumbers(int *num1,int *num2, int *num3)
{
struct Random *r = malloc(sizeof(Random));
int i=1,ans = 0;
do
{
srand (time(NULL));
*num1 = rand()%HIGH_NUMBER;
*num2 = rand()%HIGH_NUMBER;
*num3 = rand()%HIGH_NUMBER;
r->a = *num1;
r->b = *num2;
r->c = *num3;
if ((*num1%2==0||*num2%2||*num3%2==0)&&(*num1%2==1||*num2%2==1||*num3%2==1)&&(*num1>50||*num2>50||*num3>50))
{
i--;
printf("%d %d %d inside isValidNumber\n",*num1,*num2,*num3);
break;
}
}
while (i);
return r;
}
Results:
cmake28 ..
make
[gliang#www build]$ ./src/random
99 99 44 inside isValidNumber
99 99 44 main return random numbers
99 99 44 main return from struct

Resources