I'm fairly new to c and I'm trying to understand and grasp malloc. My program takes an integer x input, then loops until x is met while also taking other integer inputs. I then do various calculations. However I'm getting a segmentation fault and I don't understand why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(void)
{
calculations();
}
void calculations()
{
int i;
int x;
int 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 c = 0;
while (c < x) {
scanf("%d", &array[i]);
total = array[i] * array[i];
c++;
}
squareRoot = sqrt(total);
array = realloc(array, x * sizeof(int));
int b = 0;
while (b < x) {
overall = array[i] / squareRoot;
printf("%.3f ", overall);
b++;
}
}
The problem is with
scanf("%d", &array[i])
where, the value of i is indeterminate.
To elaborate, i is an uninitialized local variable and unless initialized explicitly, the contents remain indeterminate. Attempt to use that value, in this scenario, would lead to invokes undefined behavior.
Even if you initialize i, you never operated on i, so all the changes will be overwritten on a fixed index. You got to take care of this case, too.
Solution: Looking at the code, it appears, you may want to use
scanf("%d", &array[c]);
instead.
Related
Isn't i in scanf and in sum useless? It doesn't change anything, even when I print &ptr it doesn't show me any difference in memory values.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = (int *)malloc(n * sizeof(int));
// if memory cannot be allocated
if (ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}
printf("Enter elements: ");
for (int i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum = sum + *(ptr + i);
}
printf("Sum = %d", sum);
// deallocating the memory
free(ptr);
return 0;
}
The 'i' isn't supposed to change the pointer. It is used to access the i'th element of the array that PTR points to. Without the I it would scan for the same element in this array, the first element
If you don't use 'i' in both sum and scanf, there won't be any effect on sum because it will take input in the first index of the dynamic memory and overwrite it. This 'i' is helping to store inputs in the dynamic memory.
'i' isn't a useless value, it is used to offset the pointer to access the correct element of the dynamic array.
It is the same as using
for (int i = 0; i < n; ++i) {
scanf("%d", &ptr[i]);
sum = sum + ptr[i];
}
The purpose of the index i in the for is twofold:
ensure n numbers are read and cumulated in sum.
store each converted number into a separate entry in the array pointed to by ptr.
Given what the program does, it is not required to store the numbers into an array, or even necessary to allocate this array.
Here is a simpler version:
#include <stdio.h>
int main() {
int n, v, sum = 0;
printf("Enter number of elements: ");
if (scanf("%d", &n) != 1)
return 1;
printf("Enter elements: ");
for (int i = 0; i < n; i++) {
if (scanf("%d", &v) != 1) {
printf("input error\n");
break;
}
sum = sum + v;
}
printf("Sum = %d\n", sum);
return 0;
}
"What does int i do inside of the for loop?"
i is used for the pointer offset to access subsequent int objects of the dynamically allocated memory.
It works as:
(value of ptr [address of pointed object by ptr] + (i * sizeof(pointed object by ptr))).
Maybe take a look at this Stack Overflow question.
Note: The purpose is just to dereference and modify pointed to objects, not the pointer itself. ptr won´t get changed because of this pointer arithmetics.
"It doesn't change anything, even when I print &ptr it doesn't show me any difference in memory values."
Probably it doesn´t show different values because you print the address of the pointer itself, which doesn´t change by using offsets to the pointer.
I say "probably" because I don´t see how you actually print the address of ptr in particular. Maybe you even have some kind of kind of undefined behavior.
My prog doesn't reach outArray function. it stops after loop of fillArray function. Why this happens. It looks strangely, cause it's simple void function and shouldn't return anything. This should continue run commands in main. And that stops as usual program without any problems and bugs
#include <stdio.h>
#define N 100
int enterNofArray();
void fillArray(int n, float arr[N]);
void outArray(int n, float arr[N]);
int main()
{
float arr[N], sum = 0.0, average;
int n;
//input
n = enterNofArray();
//compute
fillArray(n, &arr[N]);
//output
outArray(n, &arr[N]);
return 0;
}
int enterNofArray()
{
int n;
printf("Enter amount of array...\n");
scanf("%d", &n);
while (n < 1 || n > N)
{
printf("Incorrect!!\n");
printf("Enter in range 1 - 100...\n");
scanf("%d", &n);
}
return n;
}
void fillArray(int n, float arr[N])
{
int num;
for(int i = 0; i < n; i++)
{
printf("Enter number for array[%d times left]...\n", n - i);
scanf("%d", &num);
arr[i] = num;
}
}
void outArray(int n, float arr[N])
{
for(int i = 0; i < n; i++)
{
printf("%f ", arr[i]);
}
}
&arr[N] refers to the memory location (or lvalue) that contains the N-th (out of index!!!) element in the array.
That code invokes Undefined Behavior (UB).
So, you weren't actually passing the whole array to your functions, you were just attempting to pass the N-th element of that array... Read more about that expression here.
Change this:
fillArray(n, &arr[N]);
outArray(n, &arr[N]);
to this:
fillArray(n, arr);
outArray(n, arr);
Live Demo
The problem was that with your code n was corrupted, containing garbage value after the call to fillArray function. As a result, when outArray function was called, n had a garbage value, which resulted in an uncontrolled for-loop that ended in looping far further than the limits of your array, eventually accessing memory that you didn't own, thus causing a Segmentation Fault.
Not the cause of your problem, but I suggest you do scanf("%f", &num); in your fillArray function (after declaring num as a float of course), since you want to populate an array of floats.
Because you're send double pointer when you do this:
fillArray(n, &arr[N]);
outArray(n, &arr[N]);
Looks like:
fillArray(n, **arr);
outArray(n, **arr);
This happends so much when you work with Structures.
This a dot_product function of 2 vectors of the same length.
I don't understand how to build the array because how the machine will know which input goes to which input (for example i want a={1,2,3} but the input of 123 will come a[0]= 123)...
How do I make end of array[index] input and how do I make end of the whole array.
#include <stdio.h>
#include <stdlib.h>
#define MAXINPUT 100
int dot_product(int v[], int u[], int n)
{
int result = 0;
int i;
for (i=0; i < n; i++)
result += v[i]*u[i];
return result;
}
int main(){
int v1[MAXINPUT];
int v2[MAXINPUT];
int count = 0
int i,print;
printf(" first vector:");
for(i=0;i<MAXINPUT;i++){
scanf("%d", &v1[i]);
count +=1;
}
printf(" second vector:");
for(i=0;i<MAXINPUT;i++)
scanf("%d", &v2[i]);
print = dot_product(v1, v2, count);
printf("v1*v2:%d",print);
return 0;
}
The first problem I observe here is with
count +=1;
where count is an uninitialized automatic local variable, which makes it's initial value indeterminate. Attempt to use that value invokes undefined behavior.
You should be initializing count to 0.
That said, here, you're depending on the user to input the second array with exact same dimension of that of the first one. In case that does not happen, your program will blow up, as you did not initialize the arrays, again.
I am a student trying to learn c coming from c++. I wrote the following code and it compiles fine; however, when I execute it I get an endless loop when calling the print function. I looked over the code and it seems to be valid to me, so why is it printing an endless loop?
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
int score;
};
void generate(struct student *students, int n)
{
int randomId = rand () % n + 1;
int randomTestScore = rand() % 100 + 1;
students->id = randomId;
students->score = randomTestScore;
}
void sort(struct student *students, int n)
{
/*using insertion sort*/
for (unsigned int i = 1; i < n; ++i)
{
int next = students[i].score;
int j = i;
while(j > 0 && students[j-1].score > next)
{
students[j].score = students[j-1].score;
j--;
}
students[j].score = next;
}
}
void print(struct student *students, int n)
{
for (unsigned int i = 0; i < n; i++)
{
printf("Student at position No: %d Test Score: %d\n", i+1, students[i].score);
}
}
int main()
{
/*user enters num of students to create scores for*/
int num_students;
printf("Enter Num of students\n");
scanf("%d", num_students);
/*allocate memory for the amount of students user wants*/
struct student *userStudents = malloc(num_students*sizeof(struct student));
printf("Randomly filling students IDs & Test Scores...\n");
for (unsigned int i = 0; i < num_students; ++i)
{
generate(&userStudents[i], num_students);
}
printf("Array of students before sorting:\n");
print(userStudents, num_students);
printf("\nNow, sorting students by test scores...\n\n");
sort(userStudents, num_students);
printf("Array of students after sorting:\n");
print(userStudents, num_students);
return 0;
}
To use scanf() correctly it needs to alter the passed variable in place, and since there is no pass by refrence in c, you need to pass the address of the variable, so scanf() is able to modify it though a pointer, hence you need to use the & operator, but that is not enough.
The scanf() family of functions, return a value that must be checked before you can access the scanned values, you should never ignore that value, under any circumstances you should check for it.
What your code is doing is called undefined behavior, it's interpreting the passed integer as if it was a pointer, which is undefined behavior.
To prevent that you can activate compiler warnings, many compilers know what kind of parameter the *f functions expect, i.e. the functions which take a string as a format to be parsed and to allow the function to correctly grab the rest of the parameters passed via variable arguments to it.
The correct way to call scanf() in your program is
if (scanf("%d", &num_students) != 1)
return 1;
that is, from main() and hence it's ending the program, because you can't continue after that condition was true, in that case what actually happens is that num_students is not initialized, that would once again cause undefined behavior.
Change the call to scanf to:
/*
* correct way of calling scanf, passing the address of the wanted variable
*/
scanf("%d", &num_students);
^
This elliminates segmentation faults and makes the code runs OK on my machine.
I had a previous hint that you'd need to change your declaration of userStudents to a pointer to pointers, however I was incorrect. You are clearly correctly allocating enough contiguous memory to hold all of your structs pointed by *userStudents.
This program takes the first number in a file and indicates how many numbers are going to be after it, then does various other things with the numbers that follow.
It seems like scanf is causing an infinite loop when trying to read from the file. WHen I run the program not even the check at 1 works
Here is the code:
#include <stdio.h>
int main(void) {
int N, a, n;
int x=0;
int t=0;
printf("1"); //Check
scanf("%d", &N);
printf("2"); //Check
int nums[N];
int i;
printf("%d", &N); //Check
for (i=0; i<N; i++)
{
scanf("%d", &nums[i]);
t+=nums[i];
if (nums[i] > x) x=nums[i];
if (i=0 || nums[i] < n) n = nums[i];
}
a = t/N;
printf("Number Processed: \t%d\n", &N);
printf("Maximum: \t%d\n", &x);
printf("Minimum: \t%d\n", &n);
printf("Total: \t%d\n", &t);
printf("Average: \t%d\n", &a);
}
The way i run the program is
gcc -lab16
./a.out <in1
where in1 is text and has the numbers
7
6
-30
90
3903
-934
443
445
Thanks for your time.
if (i=0 || nums[i] < n) n = nums[i];
you are assigning i = 0, so the loop never realy advances! You probably wanted i == 0. This is causing the infinite loop.
Other issue: int nums[N]; - if you want an array of dynamic [determined in run-time] size, you will probably need to malloc() it.
Update: note that int nums[N] is valid in C99, so if your assigment is assuming C99 you should not worry about this issue. Otherwise - malloc() will be needed:
int* nums = (int*) malloc(sizeof(int) * N)
And don't forget to free(nums) before the program ends, or you will get memory leak.
if (i=0 || nums[i] < n) n = nums[i];
This is the culprit. You are making an assignment i=0 when you should do a comparison : i==0
Your loop goes to infinity because everytime you are i to 0.
Moreover, the code you gave us, gave me an error, because you were creating new variables during runtime.
#include <stdio.h>
#include "stdlib.h"
int main(void) {
int N, a, n;
int x=0;
int t=0;
int i;
int *nums;
printf("1"); //Check
scanf("%d", &N);
printf("2"); //Check
nums = malloc(N*sizeof(int));
....
There are numerous problems with this code.
You mistook assignment for comparison:
i=0
sets i to zero. You probably meant
i==0
which checks whether i is equal to zero.
You should check the value returned by scanf(). When data read by scanf() doesn't fit the format you specified it leaves the data in the buffer and the next call to scanf() sees the same data again.
The reason that the first printf() doesn't print anything is most likely that you are not printing any newline. Note that on some output devices like terminals output is line-buffered.
You are passing a pointer to a variable to printf(), but your format specifies %d. You probably meant the variable itself, not a pointer to it.
Also, if you need an array of length dependent on a value known only at runtime, you need to allocate it on the heap, e.g. using malloc().