Infinite array index without any pointer in C - c

I want to get a variable from user and set it for my array size. But in C I cannot use variable for array size. Also I cannot use pointers and * signs for my project because i'm learning C and my teacher said it's forbidden.
Can someone tell me a way to take array size from user?
At last, I want to do this two projects:
1- Take n from user and get int numbers from user then reverse print entries.
2- Take n from user and get float numbers from user and calculate average.
The lone way is using array with variable size.
<3
EDIT (ANSWER THIS):
Let me tell full of story.
First Question of my teacher is:
Get entries (int) from user until user entered '-1', then type entry numbers from last to first. ( Teacher asked me to solve this project with recursive functions and with NO any array )
Second Question is:
Get n entries (float) from user and calculate their average. ( For this I must use arrays and functions or simple codes with NO any pointer )

Modern C has variable size arrays, as follows:
void example(int size)
{
int myArray[size];
//...
}
The size shouldn't be too large because the aray is allocated on the stack. If it is too large, the stack will overflow. Also, this aray only exists in the function (here: funtion example) and you cannot return it to a caller.

I think your task is to come up with a solution that does not use arrays.
For task 2 that is pretty simple. Just accumulate the input and divide by the number of inputs before printing. Like:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float result = 0;
float f;
int n = 0;
printf("How many numbers?\n");
if (scanf("%d", &n) != 1) exit(1);
for (int i=0; i < n; ++i)
{
if (scanf("%f", &f) != 1) exit(1);
result += f;
}
result /= n;
printf("average is %f\n", result);
return 0;
}
The first task is a bit more complicated but can be solved using recursion. Here is an algorithm in pseudo code.
void foo(int n) // where n is the number of inputs remaining
{
if (n == 0) return; // no input remaining so just return
int input = getInput; // get next user input
foo(n - 1); // call recursive
print input; // print the input received above
}
and call it like
foo(5); // To get 5 inputs and print them in reverse order
I'll leave for OP to turn this pseudo code into real code.

You can actually use variable sized arrays. They are allowed when compiling with -std=c99
Otherwise, you can over-allocate the array with an arbitrary size (like an upper bound of your actual size) then use it the actual n provided by the user.
I don't know if this helps you, if not please provide more info and possibly what you have already achieved.

Related

Why does c print a different array the second time it's printed?

My cousin has a school project and we can't figure out why is the array different the second time it's printed when there is no values changing in between?
Basically you enter a number which states how many rows/columns will the matrix have, and during first loop he assigns a number to every position and prints out the random number. However, the second time we go through the matrix the numbers are different and it seems that they are copied through the matrix from bottom left corner to top right corner for some reason. It seems strange to us because we never assign a different value to a position in the array after defining it for the first time.
int i,j,n,matrica[i][j],suma=0;
srand(time(NULL));
printf("\nunesi prirodan broj N[3,20] = \n");
scanf("%d",&n);
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
matrica[i][j]=rand()%100;
printf("%d, %d = %4d ",i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
printf("\n");
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
printf("%d, %d = %4d ", i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
And here is the result of this (the code I pasted here has 2 prints, and in the image there is 3 but every time you go through the matrix after the first time it's going to be the same):
We need to use malloc to allocate the dynamic amount of memory.
After
scanf("%d",&n) // PS You should check the return value - read the manual page
Put
matrica = malloc(sizeof(int) * n * n);
And declare it as
int *matrica;
Then replace
matrica[i][j]
with
matrica[i * n + j]
And after you have finished with matrica - use free i.e.
free(matrica);
int i,j,n,matrica[i][j]
At this point I must ask, what value do you think i and j will have? Right there you're invoking undefined behaviour by referring to variables declared with automatic storage duration which you've not initialised. Anything after this point is... undefined behaviour.
Having said that, I noticed a few other parts that look strange. Which book are you reading? The reason I ask is that the people I know to be reading reputable textbooks don't have these problems, thus your textbook (or resource, whatever) mustn't be working for you...
I can't read the commentary inside of the string literals, which is a shame, since that's usually quite valuable contextual information to have in a question. Nonetheless, moving on, if this were me, I'd probably declare a pointer to an array n of int, after asking for n, like so:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n;
printf("Enter n, please: ");
fflush(stdout);
if (scanf("%zu", &n) != 1 || n == 0 || SIZE_MAX / n < n) {
puts("Invalid input or arithmetic overflow...");
return -1;
}
int (*array)[n] = malloc(n * sizeof *array);
if (!array) {
puts("Allocation error...");
return -1;
}
/* now you can use array[0..(n-1)][0..(n-1)] as you might expect */
free(array);
}
This should work for quite high numbers, much higher than int array[n][n]; would in its place... and it gives you that option to tell the user it was an "Allocation error...", rather than just SIGSEGV, SIGILL, SIGBUS or something...
... but nothing would be more optimal than just saving the seed you use to generate the random numbers, and the user input; that's only two integers, no need for dynamic allocation. There's no point storing what rand generates, amd you realise this, right? rand can generate that output purely using register storage, the fastest memory commonly available in our processors. You won't beat it with arrays, not meaningfully, and not... just not.

Storing integers as an array by reading size of array and the elemnts of the array in a single line

I am trying to create an array from the integers that a user inputs. They must be inputted on the same line, e.g. 5 1 2 3 1 6. The number of integers can be any amount.
However, the first number + 1 determines the size of the array. E.g. if the user inputs the number 5 first, it must be followed by 5 other random integers thus making the length of the array 6. I'm getting confused on how to do this because there is so much user input. Thanks in advance!
Here is my code so far, though i don't think it'll be much help:
#include <stdio.h>
int main(void) {
int arr_days[13];
int i = 0;
printf(" ");
while(i < 13) {
scanf("%d", &arr_days[i]);
i = i + 1;
}
printf("%d", arr_days[0]);
return 0;
}
You weren't too far off, you just need to allocate the buffer dynamically and read the first number separately so that you know how much space and how many loops to perform.
You might also want to check if arr_days is NULL after the malloc to protect against 'out of memory' problems.
#include <stdio.h>
int main(void) {
int* arr_days;
int i = 0;
int n;
printf(" ");
// get first number to find out how many more to expect
scanf("%d", &n);
// create memory space to store them
arr_days = malloc(n * sizeof(int));
while(i < n) {
scanf("%d", &arr_days[i]);
i = i + 1;
}
printf("%d", arr_days[0]);
return 0;
}
EDIT: I see from some comments further down that there is some confusion about scanf. This command will trigger an input request if there is no input pending, then it will process any pending input. So when you type in a bunch of numbers in response to a scanf input prompt (or pipe a text file with those numbers in to the program) each invocation of scanf("%d",...) will only extract the next single integer, leaving the rest of the input still available. If you think of it like the string is a file, scanf is reading from that file and leaving the file pointer at the end of the bit it just read ready for the next invocation to read the next bit... (which is exactly what happens if you pipe a text file!)
First you would need to get the number so that you know how many numbers to read and how big to allocate the array.
int num;
scanf("%d", &num);
int *arr = malloc(num * sizeof(int));
Second, read each of the numbers one by one.
int I;
for (I = 0; I < num; I++) {
scanf("%d", &arr[I]);
}
This shows as an example of how to do the task, you will need to take care of check scanf's result to make sure the input was successful, and check malloc for allocation too.
If you want to set the array size based on an input then the input has to be read first. What you want is to input all numbers in a line(including size of the array), which means the numbers will be read after the end of line only(after pressing [Enter]). This case is not possible with static arrays.
You can't read all the inputs i.e. array size & integers to be put in it on the same line & build an static array. But you may build a dynamic array by implementing a dynamic array and taking all inputs in the same line.
A dynamic array is a re-sizable array or array list with random
access, variable-size list data structure that allows elements to be
added or removed.
A static array required the size of the array to be created so
that that memory could be allocated before array elements can be added
to it.
All this being said,
if your array size has an upper-bound size(i.e. the maximum number of elements which you would accept is set) then you may create a static array of the maximum size and read you inputs into it.
int arr[MAX_ARRAY_SIZE ASSUMED];
This allocates an array of size MAX_SIZE_ASSUMED which means all your inputs maybe stored in the static array. But this is a bad way to implement as MAX_SIZE_ASSUMED is always the size of the array even when you may just enter one element into the array.

(C) Allow infinite of numbers to be entered, reverse the order of entered numbers & end program when 0 is entered

I'm working on a project at the moment where I have to allow a user to enter an infinite amount of numbers and reverse the order of those entered numbers and end the program if 0 is entered. I did something similar, except the one I did set the amount of numbers the user could enter, so for example in the code below, I allowed the user to enter only three numbers, reverse the order and end when -1 is entered.
#include <stdio.h>
#define MAX 3 // Defining max amount of numbers to be entered to 3
main()
{
int numbers[MAX], i, end;
printf ("Please enter %d integers:\n", MAX);
for (i = 0; i < MAX; i++){
scanf("%d", &numbers[i]);
if (numbers[i]==-1){ // Loop ends when -1 is entered
for (end=i; end<MAX; end++)
numbers[end]='\0'; // Nulls the value of blank locations in the array
i=MAX;
}
}
printf ("\nThe values in reverse order are:\n");
for (i = MAX-1; i >= 0; i--)
{
if(numbers[i]!='\0') // Will not print null values in the array
printf("\n%d ", numbers[i]);
}
return 0;
}
How can I go about achieving this? I'm guessing I won't be able to use an array, and I'm pretty new to this so...
No, arrays can't be grown dynamically (not without some extra tinkering, see comment below) so they can't hold an infinite amount of items.
You'll need some structure you can grow, C doesn't provide one so you'll have to use a third party implementation or write your own. A stack fits your problem the best.
Also, your loop will have to go on until -1 is entered. Either an infinite loop with a break statement, or a do-while loop that checks the entered number.
EDIT: The original question targeted C++, my original answer, below, is no longer relevant.
You want to look into C++'s STL. std::vector, std::deque or std::stack for example, would be useful in your case.
You can use a std::vector to do this.
Here's the declaration of your std::vector. Where the tells the vector you want it to be a vector of type int
std::vector<int> numbers;
Then to add to the end of the std::vector you use push_back(), which puts the integer onto the back of the array. The size of the vector will dynamically increase as you push more elements on to the back.
int input;
numbers.push_back(input);
Then to iterator through it you can use a reverse iterator or just iterate the same way you have been doing it using numbers.size() to find out how many elements are in the vector.

C program stops responding for large inputs

I am (re-)learning C and in the book I am following we are covering arrays, and the book gives an algorithm for finding the first n primes; myself being a mathematician and a decently skilled programmer in a few languages I decided to use a different algorithm (using the sieve of Eratosthenes) to get the first n primes. Well making the algorithm went well, what I have works, and even for moderately large inputs, i.e. the first 50,000 primes take a bit to run as you would expect, but no issues. However when you get to say 80,000 primes pretty much as soon as it begins a window pops up saying the program is not responding and will need to quit, I made sure to make the variables that take on the primes were unsigned long long int, so I should still be in the acceptable range for their values. I did some cursory browsing online and other people that had issues with large inputs received the recommendation to create the variables outside of main, to make them global variables. I tried this for some of the variables that I could immediately put outside, but that didn't fix the issue. Possibly I need to put my arrays isPrime or primes outside of main as well? But I couldn't really see how to do that since all of my work is in main.
I realize I should have done this with separate functions, but I was just writing it as I went, but if I moved everything into separate functions, my arrays still wouldn't be global, so I wasn't sure how to fix this issue.
I tried making them either static or extern, to try and get them out of the stack memory, but naturally that didn't work since they arrays change size depending on input, and change over time.
the code is:
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
unsigned long long int i,j;
unsigned long long int numPrimes,numPlaces;
int main(void)
{
bool DEBUG=false;
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// the nth prime is bounded by n*ln(n)+n*ln(ln(n)), for n >=6
// so we need to check that far out for the nth prime
if (numPrimes>= 6)
numPlaces = (int) numPrimes*log(numPrimes)+
numPrimes*log(log(numPrimes));
else
numPlaces = numPrimes*numPrimes;
if(DEBUG)
printf("numPlaces: %llu\n\n", numPlaces);
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
bool isPrime[numPlaces+1];
// only need numPrimes places, since that is all we are looking for
// but numbers can and will get large
unsigned long long int primes[numPrimes];
for (i=2; i<numPlaces+1;i++)
isPrime[i] = true; // everything is prime until it isn't
i=2; // represents current prime
while (i < numPlaces + 1)
{
for (j=i+1;j<numPlaces+1;j++)
{
if (isPrime[j] && j%i ==0) // only need to check if we haven't already
{
isPrime[j] = false;// j is divisibly by i, so not prime
if(DEBUG)
{
printf("j that is not prime: %llu\n",j);
printf("i that eliminated it: %llu\n\n",i);
}//DEBUG if
}//if
}//for
// ruled out everything that was divisible by i, need to choose
// the next i now.
for (j=i+1;j<numPlaces+2;j++)// here j is just a counter
{
if (j == numPlaces +1)// this is to break out of while
{
i = j;
break;
}// if j = numPlaces+1 then we are done
else if (isPrime[j]==true)
{
i = j;
if (DEBUG)
{
printf("next prime: %llu\n\n",i);
}//DEBUG if
break;
}//else if
}// for to decide i
}//while
// now we have which are prime and which are not, now to just get
// the first numPrimes of them.
primes[0]=2;
for (i=1;i<numPrimes;i++)// i is now a counter
{
// need to determine what the ith prime is, i.e. the ith true
// entry in isPrime, 2 is taken care of
// first we determine the starting value for j
// the idea here is we only need to check odd numbers of being
// prime after two, so I don't need to check everything
if (i<3)
j=3;
else if (i % 2 ==0)
j = i+1;
else
j = i;
for (;j<numPlaces+1;j+=2)// only need to consider odd nums
{
// check for primality, but we don't care if we already knew
// it was prime
if (isPrime[j] && j>primes[i-1])
{
primes[i]=j;
break;
}//if, determined the ith prime
}//for to find the ith prime
}//for to fill in primes
// at this point we have all the primes in 'primes' and now we just
// need to print them
printf(" n\t\t prime\n");
printf("___\t\t_______\n");
for(i=0;i<numPrimes;i++)
{
printf("%llu\t\t%llu\n",i+1,primes[i]);
}//for
return 0;
}//main
I suppose I could just avoid the primes array and just use the index of isPrime, if that would help? Any ideas would help thanks!
Your problem is here, in the definition of the VLA ("Variable Length Array", not "Very Large Array")
bool isPrime[numPlaces+1];
The program does not have enough space in the area for local variables for the array isPrime when numPlaces is large.
You have two options:
declare the array with a "big enough" size outside of the main function and ignore the extra space
use another area for storing the array with malloc() and friends
option 1
#include <stdio.h>
unsigned long long int i,j;
bool isPrime[5000000]; /* waste memory */
int main(void)
option 2
int main(void)
{
bool *isPrime;
// ...
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// ...
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
isPrime = malloc(numPrimes * sizeof *isPrime);
// ... use the pointer exactly as if it was an array
// ... with the same syntax as you already have
free(isPrime);
return 0;
}
The array you allocate is a stack variable (by all likelihood), and stack size is limited, so you are probably overwriting something important as soon as you hit a certain size threshold, causing the program to crash. Try using a dynamic array, allocated with malloc, to store the sieve.

Simply C loop is driving me nuts

So I have only ever programmed in c++, but I have to do a small homework that requires the use of c. The problem I encountered is where I need a loop to read in numbers separated by spaces from the user (like: 1 5 6 7 3 42 5) and then take those numbers and fill an array.
the code I wrote is this:
int i, input, array[10];
for(i = 0; i < 10; i++){
scanf("%d", &input);
array[i] = input;
}
EDIT: added array definition.
any suggestions or hints would be very highly appreciated.
Irrespective of whatever is wrong here, you should quickly learn to NEVER write code that does not check the return value from any API call that you make. scanf returns a value, and you have to be interested in what it says. If the call fails, your logic is different, yes?
Perhaps in this case it would tell you what's going wrong. The docs are here.
Returns the number of fields
successfully converted and assigned;
the return value does not include
fields that were read but not
assigned. A return value of 0
indicates that no fields were
assigned.
This code working good.
If your numbers is less than 10, then you must know how many numbers is before you start reading this numbers, or last number must be something like 0 to terminate output then you can do while(true) loop, but for dynamically solution you must read all line into string and then using sscanf to reading numbers from this string.
You need the right #include and a proper main. The following works for me
#include <stdio.h>
int main(void) {
/* YOUR CODE begin */
int i, input, array[10];
for (i = 0; i < 10; i++) {
scanf("%d", &input);
array[i] = input;
}
/* end of YOUR CODE */
return 0;
}
i'm not a c programmer but i can suggest an algorithm which is to use scanf("%s",&str) to read all the input into a char[] array then loop over it and test using an if statment if the current char is a space, if it is then add the preceeding number to the array

Resources