Pass an unknown number of integers with scanf - c

I need to create an array of ints of an unknown size and pass them all. My code looks like this:
int FillTable(int a[], int max){
int i;
int x = 0;
int m = 0;
for (i = 0; i < max; i++){
printf("Fill the table with integers: ");
scanf("%d", &m);
if (m != "" && m != NULL){
a[i] = m;
}else if (m != "" && m == NULL){
a[i] = 0;
}else{
break;
}
}
printf("\n");
return 0;
}
I know you can pass multiple ints separated by spaces with something like:
scanf("%d %d %d", &var1, &var2, &var3);
But I don't know how to pass a number of integers that I don't know how many will be there. Could I create a string with a bunch of %d and just repeat that for max times? I don't know, but right now, I just ask for ints until the array is full, and I need to be able to have the array be smaller than max if the user doesn't enter in enough values. Does anyone have any ideas as to how I would go about scanning for an unknown number of integers?

Does anyone have any ideas as to how I would go about scanning for an unknown number of integers?
This calls for Dynamic memory allocation!
One way of going with scanning unknown number of integers is, firstly allocate an integer array with size to hold max number of integers.
How to know whether user has ended his input?
If you are only scanning in positive integers from user at array entries then prompt him to end his input by inputting a negative number
or if you are sure about the range of input entries then break out of loop, when user enters input out of range
Example: (considering user inputs only positive numbers)
//creating a large enough array to store user inputs
int *array = malloc(sizeof(int) * max);
//check if memory was allocated or not
if(array == NULL)
{
printf("memory allocation problem!");
exit(1);
}
//integer to make note of size of array or you can use the sizeof() function instead
int size_of_array = 0;
for (i = 0; i < max; i++)
{
printf("Fill the table with integers: ");
if(scanf("%d", &m) != 1) //check for scanf return value
{
printf("wrong input, try again");
char consume; //to consume the character
scanf("%c", &consume);
i--;
continue;
}
if (m > 0) //if positive number, accept
{
array[i] = m;
size_of_array++;
}
else //else break out of scanning
{
break;
}
}
//do the program.....
//don't for get to free the memory at the end
free(array);
here's a working example: https://ideone.com/BHN4sk

You are trying to do something that is not necessary. To predict the size of the array and reallocate the appropriate exact size would be computationally more expensive (in terms of cpu time) so that benefit of saving the memory that you already had allocated is not enough.
The size of the array in c is stored somewhere that not necessarily has anything to do with the array itself. So you simply need to know how many of the array elements are interesting for the program and nothing else.
You could have something like
struct Array {
int *data;
size_t size;
size_t count;
};
where size is the total size of the array, count is the number of elements in the array and data are the elements. I use this pattern a lot and it's useful, specially if combined with realloc() as it saves from unecessarilly reallocating memory too many times which is expensive at the cost of using slightly more memory than actually needed.
But systems today have way more memory than can be used (except if you use Android Studio, which can use as much memory as your computer has).

First, m != "" && m != NULL probably does not do what you think it does. You're probably coming from a different language. What (I think) that statement does is compare the value in the integer variable m to the address of the string literal "" and then compare it to NULL (which evaluates to 0).
Second, scanf by default reads until either a space or a newline.
scanf returns a negative number on failure, so your code should look like this:
for (i = 0; i < max; i++){
printf("Fill the table with integers: ");
if(scanf("%d", &m) > 0) {
a[i] = m;
}
else {
break;
}
}
I left out the a[i] = 0 branch because I don't understand what you wanted there.
Also, you never use the variable x - unless there is more code that you left out.

your problem isn't understand for me properly,however i think this will be helped to you
int arraySize = 200; // Or whatever
int *array_ = malloc(arraySize * sizeof(int));
use this and the pass the *array_ as parameter,first defined array size or get array size as a user input,and run a for loop till size of array

You should decide how the user can stop his input (and include this info in your prompt). A quick-and-dirty way would be "enter anything that is not a number". I chose this way of terminating input, because it's easy to implement (hence, quick and dirty):
printf("Fill the table with integers; terminate with 'x':\n");
for (i = 0; i < max; i++)
{
int result = scanf("%d", &a[i]);
if (result != 1)
break;
}
Note:
The prompt tries to be user-friendly
The scanf function puts the number straight into the array, without using any intermediate variable
The scanf function returns how many numbers it read, which is normally 1; if it's not 1, then the user entered x or anything else
When the code finishes, i holds the number of iterations, which shows how many numbers were read from the user.
Your input function should return the size of the array:
return i; // instead of "return 0"
You might also want to clean the stdin buffer - discard anything that the user entered to terminate the array:
while (getchar() != '\n')
{
// do nothing - keep consuming input until end-of-line
}

Related

Outputting huge number when using an array to print out even and odd numbers on C

I was asked to code a program that asks for an integer 'n', then scan for 'n' integers, and then sort and print those integers in even numbers, ascending, then the odd numbers, descending.
So I began by having the even numbers in the first column of an array, and then the odd numbers in the second column, and then print them, but at the end I'm getting nothing but huge, similar numbers instead of the values I initially entered.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int array1_size, unfill;
printf("How many integers do you wish to enter?\n");
scanf("%d",&array1_size);
int array1[array1_size][2];
for (int i = 0; i < array1_size; ++i)
{
printf("Enter integer number %d\n", i+1);
scanf("%d",&array1[i][0]);
}
for (int i = 0; i < array1_size; ++i)
{
if ( (array1[i][0] % 2) != 0 )
{
array1[i][1] = array1[i][0];
array1[i][0] = unfill;
}
}
printf("Your even numbers are:\n");
for (int i = 0; i < array1_size; ++i)
{
printf("%d\n", array1[array1_size][0]);
}
printf("...and your odd numbers are:\n");
for (int i = 0; i < array1_size; ++i)
{
printf("%d\n", array1[array1_size][1]);
}
return(0);
}
You declare
int array1[array1_size][2];
The highest-index legally accessable element inside that is
array1[array1_size-1][2-1]
This line is hence highly suspicious
printf("%d\n", array1[array1_size][1]);
Also you do not initialise unfill but copy its content elsewhere here
array1[i][0] = unfill
You possible leave the content of any array1[i][0] non initialised, because your code is vulnerable by a failing scanf(), because here you ignore the usually very helpful return value, which could warn you in case anything went wrong with scanning.
scanf("%d",&array1[i][0])
Any of these issues could be the explanation of your observed huge numbers, which sometimes are a symptom of using non-initialized variables or content of illegally accessed memory.

using realloc() to change the malloc() size outputs garbage value (C language)

WHAT THE PROGRAM DO:
I am making a program that displays how many times a number has been entered by the user. It will stop asking value if a number less than one has been entered.
SCREENSHOT AND EXAMPLE OF THE PROGRAM
I was able to create the program by initializing the value of the array "count" to 100.
SCREENSHOT OF WHAT I DID.
The issue with this program, is that it will only accept values until 100. It will not accept values more than 100. This is a screenshot if more than a hundred value has been entered: SCREENSHOT OF MORE THAN 100
THE PROBLEM
This is where I want realloc() to come in. I want the to change the malloc() size depending on the highest entered value so it will be more flexible using realloc(). SCREENSHOT OF WHAT I CHANGED IN THE PROGRAM TO USE REALLOC()
However, doing so destroys the program. SCREENSHOT OF THE NEW OUTPUT OF THE PROGRAM
Please help me.
MY PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <stdbool.h>
main()
{
//DECLARATION OF VARIABLES
int i, j, k, highestValue=1, size=1;
int* input = (int*)calloc(size, sizeof(int));
int* count = (int*)calloc(highestValue, sizeof(int));
bool iCondition = true;
//USER INPUT
for (i=0; iCondition==true; i++)
{
//GETS USER INPUT
printf("Enter a number: ");
scanf("%d", &input[i]);
//CHECKS IF THE NUMBER ENTERED IS A HIGH NUMBER
if (highestValue<input[i]){
highestValue = input[i];
count = realloc(count, highestValue * sizeof(int));
}
//CHECKS HOW MANY TIMES THE NUMBER HAS BEEN ENTERED
bool jCondition = true;
for(j=0; jCondition==true; j++)
{
if (input[i] == j){
count[j-1]++;
jCondition=false;
}
}
//ENDS THE LOOP IF THE ENTERED NUMBER IS LESS THAN 1
if(input[i] < 1)
iCondition = false;
//IF NOT, THIS WILL REALLOCATE/CHANGE ARRAY SIZE BY ADDING +1!!
else{
size++;
input = realloc(input, size * sizeof(int));
}
}
//PRINTS OUTPUT | USES THE HIGHESTVALUE AS THE CONDITIONAL EXPRESSION FOR FLEXIBILITY
for (i=0; i<=highestValue; i++)
{
//PRINTS ALL NUMBER THAT IS NOT EQUAL TO ZERO(0)
if (count[i] != 0)
printf("\n %d was entered %d time/s ", i+1, count[i]);
}
getch();
}
When you use realloc, the elements after the end of the old array are unitialized. Thus, your value can be anybody including garbage.
Before using the newly created elements you should initialize them using the standard means (using a loop, using memset)...
Edit: Since you only allocate one extra element with realloc, you can initialize it directly with input[size-1] = '\0'. Note that realloc has a non-trivial overhead so it is generally used to allocate multiple element at a time in real-life use cases.
Also, as mentionned by #KamikCuk, you should post directly text and not screenshots of text.

Why is my for loop running infinitly?

Entering the size of the array works. But the Enter integers for loop runs infinitely.
#include <stdio.h>
int main() {
int c, array[5], i;
printf("Enter the size of the array.");
scanf("%d", &c);
array[c];
printf("Enter the integers to fill the array.");
for (i = 0; i <= c; i++) {
scanf("%d", &array[i]);
}
for (i = 0; i <= c; i++) {
printf("%d", array[i]);
//if (array[0] >= array[i]) {
// ...
//}
}
return 0;
}
Your array is of a fixed size 5. The line array[c]; doesn't resize it. It's an array access (possibly an out of bounds access) and therefore your entire program has undefined behavior.
To define a VLA, you must move the array declaration after the call to scanf1:
int c;
printf("Enter the size of the array.");
scanf("%d",&c);
int array[c];
Then, make sure your loop condition is correct. In C array indices a 0-based, meaning we loop on the interval [0, c-1] and not [0, c].
for(int i = 0; i < c; ++i)
And as a final point of contention, notice how I moved all variable declaration to just before their initial use. Organizing your code like that (with a certain locality of data and execution) has a tendency to clarify what you write. So I strongly advise you to do this.
And be sure to check the return value of scanf. You do not want to define an array if the call to the library function failed.
array[c] refers to an element at 'c' position in array and doesn't do any fruitful job. Try removing that and check once.
In your for loop, you're reading and printing elements from 0 to c, which means you took c+1 elements instead of c elements. Make it : for(i=0;i<c;++i)

While loop to read interger values from standard input

I need my program to read integer values into adjacent elements in the array, and set the counter to the total number of integers read. I also need another loop to print the values to the screen.
How do I go about doing this?
#include <stdio.h>
int main(void) {
int numArray[100];
int counter, value;
printf("Enter array length \n");
scanf("%d", &counter);
int i = 0;
while(i < counter) {
scanf("%d", &numArray[i]);
value = numArray[i];
i++;
}
return 0;
}
I need my program to read integer values into adjacent elements in the array, and set the counter to the total number of integers read. I also need another loop to print the values to the screen.
How do I go about doing this?
The overall program should work, however you need to initialize:
value = 0; /*Initialize Variables */
counter = 0;
In C when you enter a function like main variables like value and counter get initialized with random value -- if you don't initialize. It could cause you problems.
while(i < counter) /*Scans the values into the array */
{
scanf("%d", &numArray[i]);
value = numArray[i];
i++;
}
The scanf function here scans the value you entered into the array.
I'm not sure what you would use values for; your array stores the values for you. However, it could make your code shorter if you use it in a different way.
A loop to print the values would look similar to your original loop.
while(i < counter)
{
printf("%d", &numArray[i]); /*Prints the values in the array */
i++;
}

Why does this C program go pear-shaped? Have I broken my buffers?

I've been experimenting with C a little bit. I usually use PHP and javascript.
I did "Hello World" and then I typed in this, which I copied from a website somewhere...
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int intcmp(const void*v1, const void *v2){
return (*(int *)v1 - *(int *)v2);
}
main(){
int arr[MAX], count, key , *ptr;
printf("Enter %d integer values; press enter after each\n", MAX);
for (count = 0; count < MAX; count++)
scanf("%d", &arr[count]);
puts("Press a key to sort the values");
getc(stdin);
qsort(arr, MAX, sizeof(arr[0]), intcmp);
for(count=0; count < MAX; count++)
printf("\narr[%d] = %d.", count, arr[count]);
puts("\nPress a key to continue");
getc(stdin);
printf("Enter a val to search for");
scanf("%d", &key);
ptr = (int * )bsearch(&key, arr, MAX, sizeof(arr[0]), intcmp);
if(ptr != NULL){
int fred = (ptr - arr);
printf("%d found at arr[%d]", key ,fred);
}else{
printf("%d not found", key);
}
}
So far so good. I'm trying to understand what all the stars do, but it's falling into place (ha ha - falling stars :)
However, if I type in a float e.g. 21.45 when it asks me for 20 integers, it rushes through to "Enter a val to search for" having filled the 20 array values with weird numbers.
Have I created some sort of buffer overflow? I realise that input should be checked - but I'm interested to know what I've done. Could I use my program to run arbitrary code? (Well, no, not with my knowledge... but could someone?)
However, if I type in a float e.g. 21.45 when it asks me for 20 integers, it rushes through to "Enter a val to search for" having filled the 20 array values with weird numbers
If you enter a value such as 21.45 the call to scanf("%d") will fail, as it is not an int, and will leave the .45 in stdin (the 21 will be extracted as a valid int) to be processed again. This causes the loop to re-read this value again and again (as it fails every time). The weird numbers are due to the elements of the array being uninitialised.
Check the return value of scanf() which returns the number of assignments made and if it fails skip whatever is in stdin:
int count = 0;
while (count < MAX)
{
if (1 == scanf("%d", &arr[count]))
{
count++; /* OK, so get next. */
}
else
{
/* !OK, skip invalid input. */
int c;
while ((c = fgetc(stdin)) != EOF && c != '\n');
}
}
If you fill the standard input with something that's not in the right format (in this case a float), the extraction of the value will fail. However, the broken data won't get extracted from the input stream. This means that scanf will fail repeatedly. As such, your arr[0...MAX-1] is not filled at all by scanf.
If you want to get a float, then in the scanf you need to have:
scanf("%f", &arr[count]);
Additionally, you need to declare your array as float arr[MAX]

Resources