I'm trying to separate my code more neatly by using functions. An issue I've been having is passing variables through different functions. If I leave all my code in my working function it will run no problem. It's when I create another function and pass variables to that function, that's when I get the issues.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(void)
{
workings();
output();
}
void workings()
{
int x;
int i;
double total = 0;
double squareRoot;
double overall;
scanf("%d", &x);
int* array = malloc(x * sizeof(int));
if (!array) {
printf("There isn't enough memory \n");
return;
}
int j = 0;
while (j < x) {
scanf("%d", &array[j]);
total += array[j] * array[j];
j++;
}
squareRoot = sqrt(total);
}
void output(int x, double overall, double squareRoot, int* array)
{
int k = 0;
while (k < x) {
overall = array[k] / squareRoot;
printf("%.3f ", overall);
k++;
}
}
You must pass arguments to functions which require them.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void workings(int *x_out, double *squareRoot_out, int** array_out);
void output(int x, double squareRoot, int* array);
int main(void)
{
int x;
double squareRoot;
int* array;
workings(&x, &squareRoot, &array);
output(x, squareRoot, array);
}
void workings(int *x_out, double *squareRoot_out, int** array_out)
{
int x;
double total = 0;
double squareRoot;
scanf("%d", &x);
int* array = malloc(x * sizeof(int));
if (!array) {
printf("There isn't enough memory \n");
return;
}
int j = 0;
while (j < x) {
scanf("%d", &array[j]);
total += array[j] * array[j];
j++;
}
squareRoot = sqrt(total);
/* pass data for later use to callee */
*x_out = x;
*squareRoot_out = squareRoot;
*array_out = array;
}
void output(int x, double squareRoot, int* array)
{
double overall;
int k = 0;
while (k < x) {
overall = array[k] / squareRoot;
printf("%.3f ", overall);
k++;
}
}
Changes I made are:
Add prorotype declaretions of functions to be used before main() (where the functions are used).
This is for safety: compilers cannot check arguments before knowing declaretions nor definitions of functions.
Add arguments to workings() in order to export data used in the function.
Use the arguments to export data.
Remove variables overall and i in workings() because they weren't used.
Remove overall parameter from output() function and declare it as local variable because the input is not used.
Modify main() function to allocate memory for passing data and pass data between functions.
Related
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
In the below code I am trying to scanf() a vector with dynamic dimension (entered by the user) using a secondary function. I am not getting any errors or warnings, but the vector is not getting printed from main(). Any ideas on what I am missing? Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
void save_vector(int dim, float *u);
int main()
{
float *v = 0;
int i, dim;
setlocale(LC_CTYPE, "spanish");
printf("Please enter the vector dimension:\n");
scanf("%d", &dim);
save_vector(dim, v);
for (i = 0; i < dim; ++i)
{
printf("%f\n", v[i]);
}
return 0;
}
void save_vector(int dim, float *u)
{
int i;
u = (float *)calloc(dim, sizeof(float));
for (i = 0; i < dim; ++i)
{
scanf("%f", &u[i]);
}
}
As you know when you want to make the changes permanent to a variable passed in a function argument you need to pass a pointer to it.
In this case you want to change a pointer so you need to pass a pointer to that pointer.
I would suggest a simpler approach which is to return the pointer instead of passing it by argument:
Live demo
int main()
{
float *v;
int dim;
printf("Please enter the vector dimension:\n");
scanf("%d", &dim);
v = save_vector(dim); // assign the variable allocated in the function
for (int i = 0; i < dim; ++i)
{
printf("%f\n", v[i]);
}
return 0;
}
float* save_vector(int dim) //pointer to float return type
{
int i;
float *u;
u = calloc(dim, sizeof *u);
if(u == NULL) {
exit(EXIT_FAILURE);
}
for (i = 0; i < dim; ++i)
{
scanf("%f", &u[i]);
}
return u; //return allocated array
}
If you really want to use a double pointer you can use something like this:
Live demo
int main() {
float *v;
int dim;
printf("Please enter the vector dimension:\n");
scanf("%d", &dim);
alloc_vector(dim, &v); //allocate vector
save_vector(v, dim); //having enough memory assing the values
print_vector(v, dim); //print the vector
return EXIT_SUCCESS;
}
void alloc_vector(int dim, float **u) { //double pointer argument
*u = calloc(dim, sizeof **u)); //allocate memory for the array
if(*u == NULL) { //allocation error check
exit(EXIT_FAILURE);
}
}
void save_vector(float *u, int dim) {
for (int i = 0; i < dim; ++i) {
scanf("%f", &u[i]);
}
}
void print_vector(float *u, int dim){
for (int i = 0; i < dim; ++i)
{
printf("%f\n", u[i]);
}
}
For n=3 and a={1,2,3},b={4,5,6} its supposed to calculate 1*4+2*5+3*6.
I don't understand why does it work because p is a pointer and p=produs(a,b,n) means that the address of p becomes the value returned by produs.
#include <stdio.h>
#include <conio.h>
void citire(int *x,int *n)
{
for(int i=1; i<=*n; i++)
scanf("%d",&x[i]);
}
int produs(int *a,int*b,int n)
{
int produs=0;
for(int i=1;i<=n;i++)
produs=a[i]*b[i]+produs;
return produs;
}
int main()
{
int n;
int*p;
scanf("%d",&n);
int *a=(int*)malloc(n*sizeof(int));
int *b=(int*)malloc(n*sizeof(int));
citire(a,&n);
citire(b,&n);
p=produs(a,b,n);
printf("%d",p);
return 0;
}
When you do:
size_t size = 10;
int* x = calloc(size, sizeof(int));
You get an array x with 10 items in it, indexed 0..9, not 1..10. Here calloc is used to make it abundantly clear what's being requested instead of doing multiplication that can be mysterious or obtuse.
As such, to iterate:
for (int i = 0; i < size; ++i) {
x[i] ...
}
You have a number of off-by-one errors in your code due to assuming arrays are 1..N and not 0..(N-1).
Putting it all together and cleaning up your code yields:
#include <stdio.h>
#include <stdlib.h>
void citire(int *x, size_t s)
{
for(int i=0; i < s; i++)
scanf("%d", &x[i]);
}
int produs(int *a, int* b, size_t s)
{
int produs = 0;
for(int i = 0; i < s; i++)
produs = a[i] * b[i] + produs;
return produs;
}
int main()
{
int n;
scanf("%d",&n);
int* a = calloc(n, sizeof(int));
int* b = calloc(n, sizeof(int));
citire(a, n);
citire(b, n);
// produs() returns int, not int*
int p = produs(a,b,n);
printf("%d", p);
return 0;
}
You're using pointers in places where pointers don't belong. In C passing a pointer to a single value means "this is mutable", but you don't change those values, so no pointer is necessary nor advised.
Try and use size_t as the "size of thing" type. That's what's used throughout C and it's an unsigned value as negative indexes or array lengths don't make any sense.
i defined a matrix into a function. how do i return that matrix for print it when i call it with another function. i mean...
#include<stdio.h>
#include<conio.h>
#include<time.h>
void main() {
int m,n;
printf("type 2 numbers:");
scanf("%i %i",&m,&n);
declaration(m,n);\\HERE IS THE PROBLEM
printing(matrix,m,n);
getch();
}
void declaration(int a,int b) {
srand(time(NULL));
int i,j,matrix[a][b];
for(i=0;i<a;i++){
for(j=0;j<b;j++){
matrix[i][j]=1+rand()%7;
}
}
}
void printing(int c[100][100],int a,int b) {
int i,j;
for(i=0;i<a;i++){
for(j=0;j<b;j++){
printf("%i\t",c[i][j]);
}
printf("\n");
}
}
Define it like:
typedef struct {
int rows;
int cols;
int *data;
} int_matrix_entity, *int_matrix;
int_matrix int_matrix_create(int rows, int cols, bool rand)
{
int_matrix mt;
int i;
if ((mt = malloc(sizeof(int_matrix_entity))) == NULL)
{
return NULL;
}
if ((mt->data = malloc(sizeof(int) * cols * rows)) == NULL)
{
free(mt);
return NULL;
}
if (rand)
{
srand(time(NULL));
for (i = 0; i < cols * rows; i++)
{
mt->data[i] = 1 + rand() % 7;
}
}
else
{
memset(mt->data, 0, sizeof(int) * cols * rows);
}
return mt;
}
void int_matrix_printf(int_matrix mt)
{
int i;
int j;
for (i = 0; i < mt->rows; i++)
{
for (j = 0; j < mt->cols; j++)
{
printf("%5d ", mt[i * cols + j]);
}
printf("\n");
}
}
You have a few points that require a bit more attention;
1 ) read warning and error messages given by your compiler
2 ) again, read warning messages given by your compiler
3 ) use indentation to make your code more readable.
4 ) Always return from main(), that's a good practice
The code below does what you want to achieve; have a look at it and keep on reading...
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
// You either have to declare your functions
// or implement them before main()
void declaration(int a,int b, int m[a][b]);
void printing(int a,int b, int m[a][b]);
int main(){ // always return from main()
int m,n;
printf("type 2 numbers:");
scanf("%i %i",&m,&n);
int matrix[m][n];
declaration(m, n, matrix);
printing(m, n, matrix);
return 0;
}
void declaration(int a,int b, int m[a][b]){
srand(time(NULL));
int i,j;
for(i=0;i<a;i++){
for(j=0;j<b;j++){
m[i][j]=1+rand()%7;
}
}
}
void printing(int a,int b, int m[a][b]){
int i,j;
for(i=0;i<a;i++){
for(j=0;j<b;j++){
printf("%i\t",m[i][j]);
}
printf("\n");
}
}
You need a way to transfer data from one function to another. You cannot simply declare an auto variable in one function and pass it to another as you did in the code below
declaration(m,n);
printing(matrix,m,n); /* where does matrix[][] come from? */
remember, C is a strongly typed language which means you have to declare your variables before using them. This applies to your functions as well. You either have to give your function declarations before main() (or more specifically, before using them), or implement them.
Look into your header files (i.e. .h files) and you will see lots of function declarations.
Since you use variable length arrays, make sure your compiler is at least capable of compiling code confirming C99 standard.
Some extras;
Normally, C passes arguments by value and you have to use a pointer if you want the value of your variable get changed within the function. If you have a close look at the code snippet I gave, I simply used an int m[a][b].In C, the name of an array is a pointer to its first element, hence you can change the value of array elements when actually array's name is passed to your function as an argument.
For further reading, you may want to look at
variable scope
global variables (you can define matrix[][] as a global variable and change the value of matrix elements)
declaration vs definition in C
Another simple way to do it is use double pointer to create 2-dimensional array. Keep it simple.
#include <stdio.h>
#include <stdlib.h>
int** create_matrix(int rows, int cols) {
int **matrix = malloc(rows*(sizeof(int *)));
for(int i = 0; i < rows; i++) {
matrix[i] = malloc(cols*sizeof(int));
}
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
matrix[i][j] = 1 + rand()%7;
}
}
return matrix;
}
void printing(int** matrix, int rows, int cols) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void) {
int rows, cols;
rows = 3, cols = 3;
int** matrix = create_matrix(rows, cols);
printing(matrix, rows, cols);
free(matrix);
return 0;
}
I'm working on a small program for school and can't get my array of doubles to sum properly. The specific error I'm getting is
warning C4244: 'return': conversion from 'double' to 'int', possible loss of data
on the line where sum is returned. And the sum displayed is gibberish.
The code is intended to:
fill an array of doubles with user input,
print the doubles on the screen in a column,
add up all the doubles in the array, and
print the sum onto the screen.
Code
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MAX_SIZE 15
void FillArray(double a[], int *i);
void PrintArray(double a[], int i);
SumArray(double a[], int *i);
int main()
{
double input[15];
int input_size;
double sum;
FillArray(input, &input_size);
PrintArray(input, input_size);
sum = SumArray(input, &input_size);
printf("The sum is %f\n", sum);
return 0;
}
void FillArray(double a[], int *i)
{
int k;
printf("Filling an array of doubles\n");
printf("How many doubles do you want to enter (<15)\n");
scanf(" %d", i);
for (k = 0; k <*i; k++)
{
printf("Enter double:\n");
scanf("%lf", &a[k]);
}
}
void PrintArray(double a[], int i)
{
int k;
printf("Printing an array of integers:\n");
for (k = 0; k<i; k++)
{
printf("%f\n", a[k]);
}
printf("\n");
}
SumArray(double a[], int *i)
{
int k;
double sum = 0;
for (k = 0; k<*i; k++);
{
sum +=a[k];
}
return (sum) ;
}
You need to specify double SumArray(...) instead of merely SumArray(...) where you declare and define the function. If you do not specify a return type, int is assumed. Specifically:
void FillArray(double a[], int *i);
void PrintArray(double a[], int i);
double SumArray(double a[], int *i);
/*^^^^^^-- add return type*/
int main()
and
double SumArray(double a[], const int numElements)
/*^^^^^^- same deal*/ /* also ^^^^^ ^^^^^^^^^^^ */
{
int k;
double sum = 0.0; /* Edit 3: 0.0 rather than 0 for clarity */
for (k = 0; k < numElements; ++k) /* no ; here! --- Edit 3: ++k for speed and good practice */
{ /* ^^^^^^^^^^^ */
sum +=a[k];
}
return (sum) ;
}
Edit Also, you can use const int numElements instead of int *i in SumArray. You don't need to modify the value inside SumArray, so you don't need the * and you can specify const. And it's a good practice to give your variables descriptive names, e.g., numElements instead of i. That will help you understand your own code when you have to maintain it later! (Ask me how I know. ;) )
To use this, you also need to change the call in main to remove the &:
sum = SumArray(input, input_size);
/* ^ no & here */
Edit 2 As #BLUEPIXY pointed out, the trailing ; on the for loop was misplaced. As a result, the {} block ran once, after the loop had completed. That would be a significant cause of the "gibberish" you saw: the effect was to set k=numElements and then set sum=a[numElements], which was a non-existent element. So the sum was being set to whatever random memory contents happened to be after a.
I am tryin to take input from the user and store it into an array and print it out: i have 2 functions:
/* Read a vector with n elements: allocate space, read elements,
return pointer */
double *read_vector(int n){
double *vec = malloc(n * sizeof(double));
int i;
for (i = 0; i < n; i++)
vec[i] = n;
return vec;
}
and the print function is:
void print_vector(int n, double *vec){
int i;
for (i = 0; i < n; i++) {
printf("%d\n", vec[i]);
}
}
the main function is:
#include <stdio.h>
#include <stdlib.h>
double *read_vector(int n);
void print_vector(int n, double *vec);
void free_vector(double *vec);
int main(){
int n;
double *vector;
/* Vector */
printf("Vector\n");
printf("Enter number of entries: ");
scanf("%d", &n);
printf("Enter %d reals: ", n);
vector = read_vector(n);
printf("Your Vector\n");
print_vector(n,vector);
free_vector(vector);
}
when i run this, it does not let me enter any numbers, it just skips it and prints out 0's. How do i fix this?
Try the code below. You're almost certainly either not compiling with warnings, or ignoring the warnings. All warnings mean something, and to a beginner they all matter. With gcc use the -Wall option, or even -pedantic.
As halfelf pointed out, you need a scanf in your read loop but it needs to be a pointer (&vec[i]). Always return something at the end of main. Also check the return value of malloc, it could fail and return a null pointer.
#include <stdio.h>
#include <stdlib.h>
double *read_vector(int n)
{
double *vec = malloc(n * sizeof(double));
int i;
for (i = 0; i < n; i++) {
printf("Enter number %i of %i: ", i + 1, n);
scanf("%lf", &vec[i]);
}
return vec;
}
void print_vector(int n, double *vec)
{
int i;
for (i = 0; i < n; i++) {
printf("%f\n", vec[i]);
}
}
void free_vector(double *vec)
{
free(vec);
}
int main()
{
int n;
double *vector;
printf("Vector\n");
printf("Enter number of entries: ");
scanf("%i", &n);
vector = read_vector(n);
printf("Your Vector\n");
print_vector(n, vector);
free_vector(vector);
return 0;
}
In the read_vector(int n) function's for loop:
for (i=0; i<n; i++)
vec[i] = n; // this should be scanf("%lf",vec+i) to read input from stdin
and notice your { and } there. If there's only one line in the loop, { and } is not necessary, OR you have to use a pair of them. The return clause must be out of the loop.
Btw, add return 0 at the end of your main function.
simple..you forgot to write scanf..!
double *read_vector(int n)
{
double *vec = malloc(n * sizeof(double));
int i;
for (i = 0; i < n; i++)
scanf("%d",&vec[i]);
return vec;
}