Array with No Upper Boundaries in C - c

I have been attempting to wrap my head around an idea that I am certain is possible, I just am not sure if I am going about it in the right way. My intention is to create an array and then fill it with as many values as the user wants. However my goal is to not use any defined value per se. I would like to be able to continue increasing it the amount of values it can contain indefinitely.
This is the test code I have been using to try and figure this out:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i;
int Up;
int Ary[0];
printf("Please enter the number of integers you want to input: ");
scanf("%d", &Up);
for(i = 0; i < Up; i++)
{
printf("Please enter a number: ");
Ary[i] = (int) malloc(sizeof(int));
scanf("%d", &Ary[i]);
}
for(i = 0; i < Up; i++)
{
printf("%d ", Ary[i]);
if(i % 10 == 0)
{
printf("\n");
}
}
return 0;
}
This may be a poor way of attempting to figure this out and I may also be doing this is a completely wrong way; However I get a segmentation fault sometimes. If I use small values such as only entering 4 or 5 values it works fine, however if I enter 10 values it gives me a segmentation fault. If I enter 50 values, it lets me enter all 50 but gives me a segmentation fault after printing out the 41st value.
The code itself is simply a means to an end. Ultimately what I would like to know is how I can set up an array of anything that can have values added to it indefinitely while retaining previous values using dynamic memory allocation?
PS. I hope this defines my question well enough, however if it does not I would like to refine my question so it is more clear. Please make a comment if this is unclear and why.

This isn't going to work:
int Ary[0];
You've made an array with no elements; the only valid use of such an array is to take its address, but you can't index into it as you have done.
Instead, you should make a pointer to what will later be allocated as an array:
int *Ary;
Then when you know how many integers you want:
Ary = malloc(Up * sizeof(int));
Now you can do Ary[index] for any index from 0 to (Up-1). If you later want to enlarge the array, you can use realloc() (many tutorials online for that).

You need to use dynamic allocation, what you are doing right now is static allocation, you need to learn how to use malloc and free.
So keep in mind that what you want to do is not "efficient" but can definitely be done as a learning exercise to learn how to make such a container.
What you need to do is allocate the amount of memory needed to contain the amount of values currently in your array +1 more value every time you want to "add" a new value to your array, for example: malloc(sizeof(int)*(<current_number_of_values>+1)).
I say "add" in quotes because what you will have to do is actually allocate memory for a brand new array every time and copy over your old values plus the new value the user enters and then free your old array to avoid memory leaks.
There are STL containers that do this internally but much more efficiently but I assume you are doing this to learn and not use your own containers for anything serious.

Related

C Array manipulation questions

So i have a few questions about reading into arrays(very new to c)
I have this code so far
int xZac[stCrt];
int xKonc[stCrt];
int yZac[stCrt];
int yKonc[stCrt];
for (int i=0; i < stCrt; i++) {
scanf("%d", &xZac[i]);
scanf("%d", &yZac[i]);
scanf("%d", &xKonc[i]);
scanf("%d", &yKonc[i]);
int c = xKonc[i]-xZac[i];
printf("%d", c);
//the values here shoud be xKonc[0]=49, xZac[0] = 0, it outprints 490
// but i need the actual difference between those in other inputs
//it also only returns it once even tho on the first input there should be 2 such values
//on another instance(maybe im reading them wrong?) xKonc[0]=29 and xZac[0]=0 but the output is 2907220
}
Is this the proper way of reading into an array?
How do i then get the value of this, i need to use it in for statement later on but i cant seem to get it right. How would i say get the number of xKonc[i]-xZac[i]. it seems to return pointers or something when i try it. So what id like to know is how to subtract actual integers from arrays, and if im reading the data right or is the problem there
I don't see anything obviously wrong with this. Can you include your input file? I would venture to bet you are printing a 49 and a 0, without a newline character, causing you to think you are printing 490

Initialising array with unknown size in C [duplicate]

This question already has answers here:
Length of array in function argument
(9 answers)
Closed 7 years ago.
I have this piece of code:
#include <stdio.h>
int average(int array []);
int main () {
int num_array[];
int x = 0;
while(num_array[x] != -1){
printf("Enter a number\n");
scanf("%d",&num_array[x]);
x++;
}
printf("%d\n", average(num_array));
return 0;
}
int average(int array[]){
int i;
int total_size = (int)sizeof(array);
int sum = 0;
for(i = 0; i < total_size; i++){
sum = sum + array[i];
}
return sum/total_size;
}
But i get an error at compile time, because i'm not initialising the array. However i can't do it, since i don't know it's size.
How can i solve this ?
You can't declare an array like
int num_array[];
in C except when it is a parameter of a function. You must have to specify the size.
This is actually a surprisingly tricky problem in C unless you're using an array library. What you're actually talking about is a growable array. For what you're trying to do, you start with an initial size, say 10, using malloc() and as the inputs grow, you have to realloc() the array to a larger size. Generally, you double the size of the array every time the limit is hit. If you're a beginning C programmer, this is probably too much to take on. I would set a fixed limit, and enforce it by not accepting any more input after the limit is hit. Given that you can comfortably allocate 1000's of ints and a human won't want to type that much, you can easily make a practical limit ahead of time and declare the array as such:
int num_array[1000];
You need to provide the size of the array here: int num_array[];.
If you are working with a structure of unknown size, you could:
Ask the user how many numbers are going to be entered (not really practical, but might suffice if your case is a trivial one).
Initialize it with a default size, say 10 and then if you need, create larger arrays and copying your current data to the new one.
Or else, you use a linked list like data structure and create new elements as you go along, thus allowing your list to grow as much as you need it to be.

What am I doing wrong (C arrays)?

I'm just a beginner at C.
I'm trying to make a simple program to arrange the user-entered digits in ascending order. I have figured out the solution but can't understand why my other code wouldn't work :(
-------------------------------------------------------------------------
working code:
-------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int i,j,num[10];
printf("Enter 10 numbers\n");
for (i=0;i<10;i++)
{scanf("%d",&num[i]);}
for (i=0;i<9;i++)
{
for (j=i+1;j<10;j++)
{
if (num[i]>num[j])
{
num[i]+=num[j];
num[j]=num[i]-num[j];
num[i]=num[i]-num[j];
}
}
}
printf("The numbers in ascending order are:");
for (i=0;i<10;i++)
{
printf(" %d",num[i]);
}
return 0;
}
-------------------------------------------------------------------------
code that won't work:
-------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int i,j,num[10];
printf("Enter 10 numbers\n");
for (i=1;i<=10;i++)
{scanf("%d",&num[i]);}
for (i=1;i<10;i++)
{
for (j=i+1;j<=10;j++)
{
if (num[i]>num[j])
{
num[i]+=num[j];
num[j]=num[i]-num[j];
num[i]=num[i]-num[j];
}
}
}
printf("The numbers in ascending order are:");
for (i=1;i<=10;i++)
{
printf(" %d",num[i]);
}
return 0;
}
In the latter program, numbers appear out of order, and there even are numbers that haven't been entered.
My question is, isn't it basically the same code? Just that in the latter program numbers would be stored from num[1] to num[10] instead of num[0] through num[9]?
Does it have something to do with array definitions?
It seems I have serious misconceptions, please help me out!
In C, when you have int num[10];, your indexes need to go from 0 to 9, never to 10. So look over your code, if any i or j ends up with a value of 10 any time during the program run, that's bad news.
Indexes in C go start from 0. so when you declare an array of size 10, and you try to get element at index 10, you're actually getting the 11th element. Since you haven't defined the 11th element, the array will most likely get some random numbers from memory, which is why you are noticing numbers you have note entered.
Since you are new to programming, I would suggest taking the time now to really learn about how C manages memory, and how different data structures access the memory. It might be a little boring now, but you'll save yourself some headaches in the future, and you will start to build good habits and good practices, which will lead to writing good, optimal code
for(i=0;i<9;i++) //**i<9**
for (j=i+1 ...)
If i=8 then j=9 , everything is OK.
In second code snippet:
for(i=0;i<10;i++) //**i<10**
for (j=i+1 ...)
If i=9 then j=10, so you try to access num[10] and it gives you error.
If you want to access num[10] then you must declare array int num[11] and then you can access num[10].
Array Basics
int num[10]
Capacity of array = 10
Every element of this array are integer.
First element index is 0. So If you want to access first element , num[0]
Last element index is 9. So If you want to access last element, index must be length of array - 1 , so num[9]
There are 10 elements in the array and they are :
num[0] , num[1] , num[2] , num[3] , num[4] , num[5] , num[6] , num[7] , num[8] and num[9]
You can learn further at http://www.cplusplus.com/doc/tutorial/arrays/
In your non-working example, you have invalid memory accesses. For example, when i = 9 and j = 10, you access num[10], which is invalid memory.
Welcome to programming! I believe you are a bit confused about how arrays are indexed in C.
Arrays in most languages (including C) are known as zero-indexed arrays. This means the start of an array is always at position 0. So if you make int num[10], trying to access num[10] isn't actually a valid call at all, because the start is num[0]. Hence you can only access from num[0] to num[9].
It's an easy mistake to make, even though I've been programming for years sometimes when it's been a long night I'll still make silly array indexing issues.
In your other code example, you were doing this:
int num[10];
for(int i = 1; i <= 10; i++) {
//...
}
That means you have an array with ten spaces [0-9], and for the last part of your for loop, you were trying to access num[10] which doesn't exist.
Your working example goes from 0-9 and never tries to read num[10], so it works.
Arrays in C, as in most languages, start with position 0 and count that as position one. So the last element of your array would be the size you entered when you declared the variable, minus one.

Strange behaviour in a C code under gcc 4.4.3

I came across this piece of code today while tutoring some students in a C programming language course.
The exercise asked to implement two functions. The first one scans input from a user and the second displays what has been previously scanned.
The code I came across is the following:
#include <stdio.h>
void myInput(int i,int n)
{
int cpt;
int tab[n];
for ( cpt=0; cpt<n; cpt++)
{
printf("Enter a number :");
scanf("%d",&i);
tab[cpt]=i;
}
}
void myDisp (int n)
{
int tab[n];
int cpt;
for ( cpt=0; cpt <n; cpt++)
{
printf("%d ", tab[cpt]);
}
}
int main()
{
int n; int i;
printf(" Entrer the numbers of elements you want: \n");
scanf("%d \n",&n);
int tab[n];
myInput(i,n);
myDisp(n);
}
Although this code is full of inconsistencies, it does actually work under gcc 4.4.3: it displays the numbers that have been input!!!!!!
Does anyone understands how come these code works?
Thanks very much
If that works, it's through sheer dumb luck. What is printed in myDisp is uninitialized stack, which may or may not contain the data that was put into similarly named variables in myInput. Related reading
Here's an easy way to break it with do-nothing code:
void myInput(int i,int n)
{
// Add some variables to mess up the stack positioning.
int breaker;
int cpt;
int stomper;
int tab[n];
int smasher;
for ( cpt=0; cpt<n; cpt++)
{
printf("Enter a number :");
scanf("%d",&i);
tab[cpt]=i;
}
// Trick the compiler into thinking these variables do something.
breaker = 1;
smasher = 3 * breaker;
stomper = smasher + breaker;
breaker = stomper * smasher;
}
Another way to break it would be to put a function call (say, to printf) between the calls to myInput and myDisp.
It doesn't work, at least not consistently. Granted I have gcc 4.4.4 not 4.4.3
$ ./a.out
Entrer the numbers of elements you want:
5
2
Enter a number :Enter a number :4
Enter a number :1
Enter a number :2
Enter a number :3
2 4 1 134514562 3
Moral of the story is when you access uninitialized memory, anything can happen, including the appearance of working.
Since the two arrays are completely separate it really should not work. If it does it's just because they ended up in the same location in memory.
Probably it works because the memory location of the tab local to myInput e myDisp happens to be (almost?) the same.
It doesn't sound so weird to me: myInput and myDisp have almost the same signature (they differ for just one int parameter); even in the worst case scenario the locations on the stack referred by tab in the two functions would be still correctly aligned and shifted at most by two ints (i and cpt in myInput).
It appears the program is accessing the same memory location for every array int tab[n] you declared but, as mentioned, it should not work.
But I think what's happening here is something like: you are allocating tab[] inside main(), let's say, under the address 0x00000001 (take it as an example only). The array have n integers but no values at all.
Then you go into myInput(), declare the array again (same size), in other address, like 0x001F0000, and then set the values, one by one.
So, when the function terminates, it frees the allocated memory of its variables, so your array does not exist anymore.
But wait, this is C, so when you free the memory, you only tells the heap (or the memory allocator, in general) that the addresses can be used again. You do NOT exactly remove the values from memory.
Then you call myDisp() and declare your array again. It appears the memory you just requested has higher priority and then it is somewhat given again to your program. So your array is again instanciated and on the same address.
So, even if you did not fill it with values, the memory is read (as it is always valid in C) and the values are still there.
Oh, and the array declared inside main()? Nothing happens to that. Try to print its values and I bet you'll not have the correct ones.
That is my guess.
EDIT: Just to see things happening: try to declare another array after tab (do not rename tab), say tab2, same length, and use it to put your values instead of tab, then let the program run again :)

Memory leaks in C?

I'm currently learning to program in C. In one of the tasks in my assignment, I have to make a histogram (drawn by basic console output, like this: http://img703.imageshack.us/img703/448/histogram.jpg) to measure the number of characters in a text file (standard for this assignment is 1.3 MB). I did make a function like this:
int *yAxisAverageMethod(int average, int max, int min)
{
int *yAxis;
int i=0;
for (i=0;i<20;i++)
{
*(yAxis+i)=0;
}
/*
int length=sizeof(data)/sizeof(int);
*/
int lower_half_interval=average/10;
int upper_half_interval=(max-average)/10;
int current_y_value=min;
for (i=0;i<11;i++)
{
if (i==10){
*(yAxis+10)=average;
break;
}
*(yAxis+i)=current_y_value;
current_y_value+=lower_half_interval;
}
current_y_value+=average+upper_half_interval;
printf("Current y value:%d\n",current_y_value);
printf("Current max value:%d\n",max);
for (i=11;i<20;i++)
{
*(yAxis+i)=current_y_value;
current_y_value+=upper_half_interval;
}
return yAxis;
}
In this function, I intend to return an array of 20 integers, in order to make a y axis. I find the average of all characters, then used 20 lines of the console to display it. The lower 10 lines are used to display the lower than average values of the total amount of characters, and 10 lines are used to display the upper part. Each step in the y axis of the lower half is calculated by (average - min)/10, and each step in the y axis of the upper part is calculated by (max - average)/10. This is my method to draw the histogram, because I want to display the variants between values.
In the main method, I have this function call:
int *yAxis;
yAxis=yAxisAverageMethod(average,max,min);
I got a segmentation fault when I ran the function. In netbean GCC++ compiler, it works fine. Howerver, when I ran it on the university machines (which I have to compile it on command line and edit in Vi), I got the error. I guess it is because Netbean has its own memory manager? I don't understand.
Edited: I will ask about merge sort in anothe question.
*yAxis is a wild pointer. You never allocate memory for the int array you want to use.
int *yAxis = malloc(sizeof(int) * 20);
You are returning a pointer to nothing.
Where inside the function do you tell the computer to reserve some memory for *yAxis?
yAxis is a point, and you did not initialize it. it will point to unknown space what depends on the compiler. you should apply some memory for it firstly.
yAxis = malloc(sizeof(int)*20);
Don't forget to free() it in the caller.

Resources