My C Program has stopped working - c

I am trying to do my homework here, which is writing a program, that shows the distances to (0,0) of a certain number of points. However for some reason(s) as soon as my program starts, windows says that it has stopped working. I tried it with two different compilers, and they don't give me any error messages.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct point {
int x;
int y;
};
struct point getPoint();
void printPoint(struct point);
double distanceToO(struct point p);
void createArray(struct point, int);
int main() {
int number, i;
struct point coord[number];
printf("Type the number of points you want to create: ");
scanf("%d", &number);
printf("\n\n");
for(i=0;i<number;i++)
coord[i]=getPoint();
printf("\n\t\tPoint\tDistance to (0,0)\n");
for(i=0;i<number;i++) {
printPoint(coord[i]);
printf("\t%0.2lf", distanceToO(coord[i]));
}
system("pause");
return 0;
}
struct point getPoint() {
struct point p;
printf("Type the x and the y-value for a point with a space in between: ");
scanf("%d %d", &p.x, &p.y);
return p;
}
void printPoint(struct point p){
printf("\n\t\t(%d,%d)",p.x,p.y);
}
double distanceToO(struct point p) {
return sqrt((0-p.x)*(0-p.x)+(0-p.y)*(0-p.y));
}
That is what's to do in detail:
Write a Program, that first asks how many points should be created, and then asks the user for the x and y values of the points.
Then the Program should give out a table, showing the Point and the distance to (0,0).
The following functions have to be created/used:
"point getpoint()" - which asks to enter the coordinates
"void printpoint(point p)" - which prints the coordinates of the points
"double distanceToO(point p)" - returns the distance to (0,0)
Create a structure point, that has two members the x-coordinate and the y-coordinate of a point.
Can somebody give me a hint on what's wrong?

int number, i;
struct point coord[number];
number has not been initialized, and you are using it to declare the size of the coord array. You will be generating an array of effectively random size on the stack, which may well cause a crash.

The variable number is uninitialized when used to specify the number of elements in the array coord. The array is then accessed and it is not known how many elements are in they array. Read a valid value into number before using it and check that a valid value has definitely been read:
/* scanf() returns number of assignments made. */
if (scanf("%d", &number) == 1)
{
}
Always check the result of input operations to ensure subsequent code is processing variables with valid values.

int number;
struct point coord[number];
I don't see where number is initialized. If you really want to use VLA, you should declare coord afterwards:
int number;
scanf("%d", &number);
struct point coord[number];
Otherwise, since number has an automatic storage duration, its value will be undefined.

I'm pretty surprised you don't get a warning/error on this:
int number, i;
struct point coord[number];
You allocate an array of struct point with a size equal to an unitialized variable.
Note that if you use Visual Studio, it doesn't fully support C99 standard either so it's not allowed to have statements before declarations, as in:
int number;
number = some_number;
struct point coord; // Error, you have a statement above

Related

Using function to pass the user input via pointers not working

I'm trying to get the input from the user input, and pass to the program main using pointer. It seems that the value isn't going through even tho I tried some alternatives.
For example, if i input 0.0001, when I return to the main function it outputs 0.0000
#include <stdio.h>
void inputFloat(float *n);
int main() {
float *number;
printf("Insert number: ");
inputFloat(number);
printf("%1.4f", *number);
return 0;
}
void inputFloat(float *n){
float num;
while (scanf("%f", &num) != 1 || num < 0) {
scanf("%*[^\n]%*c");
printf("insert positive: ");
}
printf("%1.4f\n", num);
n = &num;
}
Thanks in advance for any tip or correction.
The main problem here is that you forget that in C arguments are passed by value, and that includes pointers.
The argument variable n in the inputFloat function is local to the inputFloat function, all modifications (like assignments) to it will be lost once the function returns.
What I believe you are trying to to is emulating pass by reference, which indeed is done by using pointers. But then you pass a pointer to a normal variable using the address-of operator &:
float number; // Not a pointer
inputFloat(&number); // Pass a pointer to the variable number
To use this pointer, and to set the value of the original variable it points to, you need to dereference the pointer:
void inputFloat(float *n)
{
// ...
*n = num; // Copy the value of num to the location where n is pointing
}

Adding pointers to an array of pointers

I'm trying to make a program that for a given int value keeps the amount of dividers:
int amount_of_dividers and a list of those dividers: int* dividers
This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
int amount;
int* dividers;
} Divide;
int main(){
Divide ** tt;
read_dividers(tt,5);
}
/* the functions "amount_of_dividers(int g)" and "dividers_of(int g, int amount)"
used in void read_divider are working properly, they are not needed for this question */
void read_divider(Divide *g){
scanf("%d",&(g->value));
g->amount = amount_of_dividers(g->value);
g->dividers = dividers_of(g->value,g->amount);
}
/* assuming that read_divider works, what causes read_dividerS to crash? */
void read_dividers(Divide ** t, int amount){
int i = 0;
t = malloc(amount*sizeof(Divide*));
for(i = 0;i<amount;i++){
read_divider(t[i]);
}
}
Read_dividers uses an array of pointers **t where i'm trying to fill each element of this array with a pointer to a Divide g variable.
EDIT: input in this case in main() : "read_dividers(tt,5)" means the user gives 5 int's, which get converted to 5 Divide structs.
What happens instead is the program crashes after I give in the second int
If any more information is missing, don't hesitate to ask!
You are passing an uninitialized t[i] to read_divider. t is supposed to be pointer to pointer to Divide, not pointer to Divide, you may have just got lucky on your first pass, but I suspect it failed on the very first call.

Getting different output for the same program when compiled in Dev-c++ and gcc 4.8.2

#include<stdio.h>
#include<stdlib.h>
#define max 10
void init_graph(int arr[max][max],int v);
void create_graph(int arr[max][max],int v);
void print_graph(int arr[max][max],int v);
int main()
{
int v,n;
printf("Enter the number of vertices :");
scanf("%d",&v);
int arr[v][v];
init_graph(arr,v);
printf("v=%d after init\n",v);
create_graph(arr,v);
print_graph(arr,v);
return 0;
}
void create_graph(int arr[max][max],int v)
{
printf("v=%d \n",v);
int e;
printf("Enter the number of edges :");
scanf("%d",&e);
int i,src=0,dest=0;
for(i=0;i<e;i++)
{
printf("Enter Edge :%d",i+1);
scanf("%d %d",&src,&dest);
if(src<=-1 || src>=v)
{
printf("Invalid source vertex \n");
i--;
continue;
}
if(dest<=-1 || dest >=v)
{
printf("Invalid dest vertex \n");
i--;
continue;
}
//*(*(arr+src)+dest)=1;
//*(*(arr+dest)+src)=1;
arr[src][dest]=1;
arr[dest][src]=1;
}
}
void init_graph(int arr[max][max],int v)
{
int i,j;
for(i=0;i<v;i++)
{
for(j=0;j<v;j++)
{
//*(*(arr+i)+j)=0;
arr[i][j]=0;
}
}
printf("V=%d init_graph\n",v);
}
void print_graph(int arr[max][max],int v)
{
int i,j;
for(i=0;i<v;i++)
{
for(j=0;j<v;j++)
{
//printf("%d ",*(*(arr+i)+j));
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
When I compiled the above program in Dev-c++ and in gcc 4.8.2 I'm getting different output. Here I'm trying to represent a graph using adjacency matrix representation.
when v is passed as parameter to the init_graph(arr,v)(in the above program), even though I'm not returning any value from the function, the value of v is becoming zero after after the function has been called.
It is working properly in Dev-c++ but I'm getting the wrong answer when compiled in gcc.4.8.2.
Screenshot of the output in Dev-c++
here v is not becoming 0
Screenshot of the output in gcc 4.8.2
and here v is becoming 0.
You are calling the function:
void init_graph(int arr[10][10], int v);
However your code is:
int arr[v][v];
init_graph(arr,v);
This causes undefined behaviour if v is not 10. The C11 standard clause is 6.5.2.2/6:
If [...] the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined.
Arrays of dimension X are only compatible with arrays of dimension Y if X == Y. (Bear in mind that the innermost dimension is "lost" due to the array as function parameter syntax quirk, so the innermost dimension can differ without breaking compatibility).
To fix this you should include the size in the array dimension in the function prototype:
void init_graph(int v, int arr[v][v]);
and similarly for the other functions.
Due to the way "array" function parameters are "adjusted" to pointers in C, the create_graph function really accepts a pointer to an array of length max. It is equivalent to this:
void create_graph(int (*arr)[max], int v)
That means that when you each iteration over arr[i] in the loop takes a step of size 10 ints, to the next length 10 array. But you are passing (after array decay) a pointer to an array of length v. If v is not the same as max, that is already undefined behaviour (UB). In your case, this takes you out of bounds, (that would cause UB by itself in an otherwise well defined program.)
You can only call the function with a pointer to array of length max or with an array of arrays whose inner array length is max (the latter will decay to pointer to array.)
Note that the type of platform dependent behaviour you saw is often a sign thet there is UB in the code.
In main() you define your array to be of size [v][v], but init_graph() takes an array of size [max][max]. You need to make these the same. I suggest changing main() since all your other functions also use max as the array size.
What happens is that when v is 5, your [5][5] array is laid out as 25 consecutive ints. But the function thinks the array is size [][10], with row size of 10 ints. So the moment you write to any element past [2][4] (the 25th element), you are writing past the end of the array and clobbering your stack. This is because your array in main() was defined as a local variable and is therefore located on the stack. In your case, the stack also contained the value of v, and it got overwritten with a 0. The reason the other compiler worked is probably because it located v before the array in memory instead of after it, so with that compiler it didn't happen to clobber v.
According to the other answers, calling the function with an incorrect argument invokes "undefined behavior" but I find that to be a lazy explanation ("anything can happen"). I hate it when people say that because any compiled program is a known quantity any you can determine exactly what the "undefined" behavior actually is (just step through it with a debugger). Once you learn what is going on and where your variables are located, you will start to intuitively understand when memory is getting corrupted and what code could possibly be responsible for it.

A few c questions: static methods, arrays

I am working on a project in C and have stumbled upon a few questions that I hope you fine folks can help me with! The project is just manipulating coordinate points that the user creates via standard input. I've included the different files and their functions below;
//points.h
struct Point{
int x;
int y;
}
//reads points from stdinput into our points array
int pointReader(struct Point points[]);
///////////////
//points.c
void pointReader(struct Point points[]){
//points[] is originally empty array (filled with NULLS)
struct Point point;
char buffer[10];
printf("X Coordinate:");
fgets(buffer, 10, stdin);
point.x = (int)buffer;
printf("Y Coordinate:");
fgets(buffer, 10, stdin);
point.y = (int)buffer;
append(points, point);
}
static void append(struct Point points[], struct Point point){
int i;
for (i = 0; i < 10; i++){
if (points[i] == NULL){
points[i] = point;
}
Upon compilation, I am receiving the following errors and I'm not too sure why:
points.c:115:10: error: invalid storage class for function 'append'
points.c: In function 'append':
points.c:127:17: error: invalid operands to binary == (have 'struct Point' and 'void *')
Also, can I so easily 'toss' around the points[] array like I am attempting to do?
Thanks for any comments!
The first error is most likely because you haven't declared the function append before you call it. Add a function prototype before you call it. In other words, before the pointReader definition, add the following line:
static void append(struct Point points[], struct Point point);
The second error is because the values in the points array are not pointers, and can therefore not be treated like pointers (like comparing it to NULL). You have to use another method of checking if an entry in the array is used or not. For example using the x and y values of -1 or something similar.
You also have another problem, and that is that you can't convert a string to an integer by just casting. You have to use a function such as strtol for that:
point.x = (int) strtol(buffer, NULL, 10);

Declaring arrays in c language without initial size

Write a program to manipulate the temperature details as given below.
- Input the number of days to be calculated. – Main function
- Input temperature in Celsius – input function
- Convert the temperature from Celsius to Fahrenheit.- Separate function
- find the average temperature in Fahrenheit.
how can I make this program without initial size of array ??
#include<stdio.h>
#include<conio.h>
void input(int);
int temp[10];
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
void input(int d)
{
int x=0;
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
void conv()
{
int x=0;
for(x=0;x<d;x++)
{
temp[x]=1.8*temp[x]+32;
}
}
In C arrays and pointers are closely related. In fact, by design an array is just a syntax convention for accessing a pointer to an allocated memory. *(see note for more details below)
So in C the statement
anyarray[n]
is the same as
*(anyarray+n)
Using pointer arithmetic.
You don't really have to worry about the details to make it "work" as it is designed to be somewhat intuitive.
Just create a pointer, and allocate the memory and then access it like as an array.
Here is some examples --
int *temp = null; // this will be our array
// allocate space for 10 items
temp = malloc(sizeof(int)*10);
// reference the first element of temp
temp[0] = 70;
// free the memory when done
free(temp);
Remember -- if you access outside of the allocated area you will have unknown effects.
To be clear it is the indexing operator ([ ]) that is translated to pointer arithmetic. This is not an array in the modern sense of the
type. Whether (or not) the pointer involved points to (dynamically) allocated
memory is inconsequential to how this operator works. In a more modern language you would be able to operate on the array as an abstract type (to see how big it is, for example), you can't do this in C.
An array without an initial size is basically just a pointer. In order to dynamically set the size of the array, you need to use the malloc() or calloc() functions. These will allocate a specified amount of bytes of memory.
In your code above, declare temp as an int pointer
int *temp;
Then allocate space for it using malloc() or calloc(). The argument that these functions take is is the number of bytes of memory to allocate. In this case, you want enough space for d ints. So...
temp = malloc(d * sizeof(int));
malloc returns a pointer to the first byte in the block of memory that was just allocated. Regular arrays are simply pointers to the first byte in a sectioned off block of memory, which is exactly what temp is now. Thus, you can treat the temp pointer as an array! Like so:
temp[1] = 10;
int foo = temp[1];
printf("%d", foo);
Outputs
10
You will need to declare temp as an int pointer (instead of an int array). Then, you can use malloc in your main (after your first scanf):
temp = malloc(d * sizeof(int));
If your compiler supports c99, then simply use VLA(variable length array).Use like this:
void input(int);
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
int temp[d];
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
Now temp[] is defined inside main() after date input.
1-add #include<stdlib.h> at the top of your file. Then modify the conv() code as follows:
2- modify temp declaration as follows (global variable):
int *temp;
3- modify input(int d) function as follows (tested on Visual Studio 2010):
void input(int d)
{
int x=0;
temp=(int*)malloc(sizeof(int)*d);
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
Allocate the "array" dynamically on the heap after you read the size.
I didn't change anything else so you may see it clearly.
#include<stdio.h>
#include<conio.h>
#include <stdlib.h> //here
void input(int);
int *temp=0; //here
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
temp=malloc(d * sizeof(int)); //here
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
void input(int d)
{
int x=0;
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
void conv()
{
int x=0;
for(x=0;x<d;x++)
{
temp[x]=1.8*temp[x]+32;
}
}
Maybe it's late to answer but...
If you work with small embedded system you might not have malloc and free functions.
So you have to sacrifice memory for 366 * sizeof(your_type), define it statically and use as a circular buffer. Then you can always slice it by number of days you need to calculate an average value.
Of course this makes natural constrains. You can define it by yourself.

Resources