keeping a variable from inside a while loop? - c

I'm trying to create a program that will take inputs into an array, and then print them all when input is terminated. My understanding was that when you declare a variable outside of the loop, it keeps the values, but I can't get this to work out. I know there's a way to do this somehow, but I'm drawing a blank.
#include <stdio.h>
int main(){
int i=0;
int n=0;
int size=0;
int numbers[i];
scanf("%d", &numbers[i]);
while ((i = 1 && numbers[i-1] != 42)){
scanf("%d", &numbers[i]);
i++;
size++;
//printf("%d",numbers[i]);
}
printf ("%d", sizeof(numbers));
while ((n = 0 && n < sizeof(numbers))){
printf("%d", numbers[i]);
printf("\n");
++i;
++n;
}
}

Your while condition:
(i = 1 && numbers[i-1] != 42)
has two problems:
i = ... actually assigns a value to i. In cas of unexpected looping, allways check if there's a =instead of an == in the condition
due to operator precedence, you assign 1 && to i. That's true value (i.e. 1) as long as you're in the loop, and as soon as numbers[i-1] is 42, i turns to 0 (because numbers[i-1]!=42 is false and 1 && false is false i.e. 0 ). This gives you impression that it didn't keep the value.
Edit: Of course, it's the same principle for n in the second loop ;-)

3 things in your code:
int numbers[i]; is trying to declare a zero element array, which accounts to undefined behavior.(although there's no bound/range checking in C)
scanf("%d", &numbers[i]), when i>=1 where is the storage allocated for this? mostly would end up in an undefined area/ over writing an existing value.
Refer the following links for more information:
Declaring an array with 0 number of elements can still store values
Why does C not define minimum size for an array?
that said you could either declare an array of fixed size or declare the size dynamically using malloc, then loop through the elements , assign and print them.
-the while loop: evaluation and priority of operators:
you could re-write your program as:
#include <stdio.h>
int main(){
int i=0;
int n=0;
int size=0;
int numbers[42];
scanf("%d", &numbers[i++]);
while (((numbers[i-1] != 42)))
scanf("%d", &numbers[i++]);
size=sizeof(numbers)/sizeof(int); /* Not necessary as array size pre-defined*/
printf("\nsize:%d\n",size);
while(n < size)
printf("%d\n", numbers[n++]);
printf("\n");
}
Note: you can change the size of the array, do keep in mind that it's an automatic variable and those array elements which haven't been explicitly initialized would be filled with junk values.

There are a lots of mistakes in your code.They are as follow-
1.int i=0;
int number[i]; which makes no sense. because you are creating an array of size 0
while ((i = 1 && numbers[i-1] != 42))
every time you while loop iterates it sets the value of i to 1 and compares numbers[0]!=42 which also makes no sense.
while ((n = 0 && n < sizeof(numbers)))
again you are assigning n to 0 and checking if n is less than sizeof(numbers) which is always true.
Although you did not specify your problem correctly I am assuming that you want to scan number till you get 42. And after that you want to print the size of the array and the numbers too.
Here is your working code.
#include <stdio.h>
int main(){
int i=0;
int n=0;
int size=1;
int numbers[10000];//I am assuming maximum input to be 10000
scanf("%d", &numbers[0]);
i=1;
while (( numbers[i-1] != 42)){
scanf("%d", &numbers[i]);
i++;
size++;
//printf("%d",numbers[i]);
}
printf ("size=%d\n", size);
while ( n < size){
printf("%d", numbers[n]);
printf("\n");
//++i;
++n;
}
}

Related

Storing an array in C

Context: I need to write a program that will accept inputs which will be stored into the array. Before storing in to the array, the inputted number must be checked if it already exists in the array or not. If it does not exist, it is stored into the array. If it exists, another input will be asked.
Now, my code will get inputs from the user, but the code will only work for the first input. It won't work for the second until the last input. Any pointers?
This is my code:
#include<stdio.h>
#define size 5
main()
{
int i;
arr[size];
input;
printf("This program will accept ");
printf("unique inputted numbers that will be stored");
printf(" in an array\n");
for(i = 0;i < size;i++)
{
printf("Enter input: ");
scanf("%d",&input);
if (unique(arr,input,i))
arr[i] = input;
else
i--;
//decrement i because ask for input again
}
for(i = 0;i < size;i++)
printf("%d ",arr[i]);
}
int unique(int arr[],int input,int i)
{
int n, z;
n = 0;
z = 1;
while(i > n)
{
if(arr[n] == input)
{
scanf("%d",&n);
z = 0;
break;
}
else
n=1;
break;
}
return z;
}
Your code is wrong at multiple levels:
The logic in the unique function is wrong.
Doing the scanf in the unique function is extremely bad design. The only thing unique should do is return 0 if input is already in the array.
You have used implicit variable declarations here: arr[size]; input;, it should be int arr[size]; int input;.
You should use descriptive variable names which makes your code easier to understand.
This is a working example (explanations in comments).
#include <stdio.h>
#define SIZE 5 // use capitals for macros (this is a convention)
int unique(int arr[], int value, int arrsize)
{
for (int i = 0; i < arrsize; i++)
{
if (arr[i] == value)
{
return 0; // value found in array
}
}
return 1; // value not found in array
}
void Test(int arr[], int arrsize, int value, int expected)
{
if (unique(arr, arrsize, value) != expected)
printf("Test failed for value %d\n", value);
}
void runtests()
{
int arr[] = { 1,2,3 };
Test(arr, 4, sizeof(arr) / sizeof(*arr), 1);
Test(arr, 1, sizeof(arr) / sizeof(*arr), 0);
Test(arr, 3, sizeof(arr) / sizeof(*arr), 0);
}
#define size 5
int main()
{
int i;
int arr[size]; // declare int variable
int input; // declare int variable
printf("This program will accept unique inputted numbers that will be stored in an array\n");
for (i = 0; i < size; i++)
{
printf("Enter input %d: ", i + 1);
scanf("%d", &input);
if (unique(arr, input, i)) // value already in the array?
arr[i] = input; // no => put it there
else
{ // yes => ask again
printf(" >> %d is already in the array\n");
i--;
}
}
for (i = 0; i < size; i++)
printf("%d ", arr[i]);
}
There are two more functions Test and runtests in this code. They are not called by this code, but they can be very useful for debugging. As an exercise try to understand why they can be useful during the debug phase of your code.
You're close, but overcomplicating it slightly.
Let's take a step back and think about this at a high level. You want to store unique inputs in the array, up to the size of the array. In pseudocode:
while array not full
prompt for and read next input
if input not already in array
store input
else
write a message
end if
end while
What's really key is that you only need one input statement - your unique function should only check for the presence of the input value in the array and return true or false. It shouldn't do any input of its own.
So your main loop is more like
while ( i < size )
{
fputs( "Gimme a number: ", stdout );
/**
* Break out of the loop if there's an error
* on input.
*/
if ( scanf( "%d", &input ) != 1 )
break;
if ( unique( arr, i, input ) )
arr[i++] = input;
else
printf( "%d already exists in the array, try again.\n", input );
}
All your unique function needs to do is cycle through the elements of the array. By calling unique with i instead of size it will only check array elements that have been written to so far and not bother with unassigned elements. This way you don't have to make sure that all of the array elements have been initialized to some known, out-of-band value that's guaranteed to compare unequal to any valid input.
You'll need to compile against C99 or later and include stdbool.h to use the bool type and the true and false constants.
#include <stdbool.h>
...
bool unique( int *arr, size_t size, int input )
{
bool result = true;
for( size_t i = 0; i < size && result; i++ )
if ( arr[i] == input )
result = false;
return result;
}
If you want to get really terse, you could directly assign the result of the Boolean expression to result:
for ( size_t i = 0; i < size && result; i++ )
result = (arr[i] == input);
but people will hit you. It's perfectly valid code, but a little eye-stabby, and most programmers aren't used to seeing Boolean expressions outside of an if, for, while, or switch statement control expression.
Finally, some suggestions:
Fix your formatting. The compiler doesn't care, but it makes it easier for other people to understand what you're trying to do and to spot mistakes.
The presence of main() in your code suggests you're using C89 or K&R C. C99 did away with implicit int declarations. You really should define main as either int main( void ) or int main( int argc, char **argv ). Furthermore, you should move to a compiler that supports later versions of C (C11 or C18).

I'm just trying to scan strings into an array. What am I doing wrong?

#include <stdio.h>
#include <string.h>
int main(void) {
const int NUM_VALS = 20;
int i;
int actualInput;
char userString[actualInput][NUM_VALS];
int matchCount = 0;
scanf("%d", &actualInput);
for (i = 0; i < actualInput; ++i) {
scanf("%s", userString[i]);
printf("%s", userString[i]);
}
return 0;
}
Output:
b'hellohi\x80\x07#\xd2\x05#\x9a\x16[\xea\xccp\xa6\x15\xf6\x18+\xbf\x87\x8a#\x14)\x05#\xfe\x7f'b'\x92\x1fk\xb3\xfe\x7f\xfe\x7f\x118\x08\xe8\x03\x0eY\x03k\xb3\xfe\x7f\xfe\x7f\xb2Y{\xe8C}8\r\x8b-u{\x8cx86_64'F-8sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin/usr/sbin:/usr/bin:/sbin:/binsbin:/binTF-88tf8RELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so64-linux-gnu/coreutils/libstdbuf.sols/libstdbuf.soout
I've tried some variations replacing userString[i] with userString in the scanf function. The result is outputting 50,000 inputs of my last string. I don't understand what's happening.
The problem is this sequence of code:
int actualInput;
char userString[actualInput][NUM_VALS];
int matchCount = 0;
scanf("%d", &actualInput);
The first line declares a variable called actualInput but doesn't assign a value to that variable.
The second line declares a variable length array (VLA) using the value in actualInput. Using the value of an uninitialized variable results in undefined behavior, which basically means that after that point in the code, anything can happen. What's likely happening (based on your description of the problem) is that actualInput is either zero, or a small number, so you get an array that's too small to hold your input.
The last line (with the scanf) finally assigns a value to actualInput. You may be thinking that the array will resize itself when actualInput is changed. That definitely does not happen. In C, after a VLA is created, its size cannot be changed.
The solution is simple, rearrange the code so that things are done in the proper order:
int actualInput;
scanf("%d", &actualInput);
char userString[actualInput][NUM_VALS];
int matchCount = 0;
As a side note, you should really do some error checking to make sure that the user inputs a reasonable number, before using that number to create an array. For example
int actualInput;
if (scanf("%d", &actualInput) != 1 || actualInput < 1 || actualInput > 1000)
{
printf("That is not a valid array size\n");
return 1;
}
char userString[actualInput][NUM_VALS];
you cant declare it as a 2D array then treat it as a normal array .
each case should include only one letter but it can't be done automatically , I suggest you add this :
for (i = 0; i < actualInput; ++i)
{
gets(stri);
for (k=0;k<strlen(stri);k++)
userString[i][j]=stri[j];
}

do while for array in c

i work for a question that generate random number and sort in array, then display numbers from biggest to smallest.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 40
int main()
{
int array[SIZE];
int inner, outter, temp, i;
srand((unsigned)time(NULL));
//do... while to assign array value
i=0;
do{
array[i] = (int)((rand()%101)+1);
i++;
}while(i<SIZE);
puts("Original array:");
for(outter=0; outter<SIZE-1;outter++){
printf("%d\t", array[outter]);
}
//bubble sort
for(outter=0; outter<SIZE-1;outter++){
for(inner=outter+1; inner<SIZE; inner++ ){
if(array[outter] > array[inner]){
temp = array[outter];
array[outter] = array[inner];
array[inner] = temp;
}
}
}
puts("\n");
puts("Sorted array:");
printf("i= %d\n",i);
printf("%d\n", array[39]);
for(outter=0; outter<SIZE;outter++){
printf("%d\t", array[outter]);
}
puts("\n");
for(outter=SIZE-1; outter>0;outter--){
printf("%d\t", array[outter]);
}
puts("\n");
// try using do while loop to display reverse number from biggest to smallest numbers
do{
printf("i= %d\n", i-1);
i--;
}while(i>-1);
}
when i used do while for displaying reverse array number, my code goes crush.
However, i display the value the "i" that used for looping array, it displayed from 39 to -1. I don not why i have -1 for "i" value since i set "i>-1".
TL;DR: Either change your printf to this: printf("i= %d\n", i); or change your while loop to while(i > 0);. Either way, it should fix your problem.
A do while loop does the action in the curly braces and then checks the condition. I'm not quite understanding your question, but it seems to me that it's printing -1 because it's doing first, then checking the condition. Furthermore, you're using i - 1 in your printf function (which is probably where you've confused yourself the most).
EDIT: To be even more explicit about the while loop, the problem is that your condition is (i > -1). That means that when you reach 0, your code will check: is 0 greater than -1?. It will return true and then move on the i = -1 where it prints -1. Then it reaches the while condition once more where it sees that -1 is not greater than -1 which is when the code terminates.
Your main problem is probably the starting value for i.
After the first do ... while loop it equals 40 when the condition fails.
Therefore you could make things a lot easier if you adjust your starting value for the second loop:
i--; // or i = SIZE-1;
do{
printf("i= %d\n", i);
i--;
} while (i >= 0);
Then you don't have any headache by shifting your values by one and can just use the values you want.
If you insist on doing it the way you did, then check the limits...
do{
printf("i= %d\n", i-1); // last value to be printed is 0 ==> i == 1
i--; // The last wanted value of i now is 0.
} while (i>0); // Stop if we reach last wanted value

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)

Scanf input & other questions

I have a program that has these objectives:
Read input into array
Read until EOF
Record the number of successful (numeric) inputs
I start by initializing:
int array[200];
int size = sizeof(array)/sizeof(int);
int num_inputs = 0;
Then I call a function void input(int * array, int size, int *num_inputs)
input(array, size, &num_inputs);
_
void input(int * array, int size, int *num_inputs) {
int i = 0;
printf("Enter numbers:\n");
while( scanf("%d", &array[i]) != EOF ) {
i++;
*num_inputs++;
if (i == (size-1))
break;
}
}
num_inputs doesn't work. From debugging (or what little I know about debugging), num_input goes from 0 to some random number. What am I doing wrong? Something with pointers?
Let's say I input 5 9 8 8 3 4 - will scanf interpret it as 6 inputs? Will num_input be 6? If not, how do I achieve that? I want to be able to write 5 6 3 6 Newline 4 9 3 and the program to be able to interpret it as writing 7 things into the array and num_input being 7.
Thanks in advance.
As #BlueMoon already mentioned, it is because you are incrementing the pointer num_inputs. Not the pointee *num_inputs.
So, change *num_inputs++; to (*num_inputs)++; (Or use a local variable, thanks #BlueMoon).
Yes. After the above change, you will get the output you needed for both the cases.
Run and check the code below:
#include <stdio.h>
void input(int * array, int size, int *num_inputs) {
int i = 0;
printf("Enter numbers:\n");
while( scanf("%d", &array[i]) != EOF ) {
i++;
(*num_inputs)++;
if (i == (size-1))
break;
}
}
int main() {
int array[200];
int size = sizeof(array)/sizeof(int);
int num_inputs = 0;
input(array, size, &num_inputs);
printf("num_inputs: %d\n",num_inputs);
return 0;
}
The problem is with this line:
*num_inputs++;
It deferences and returns the value and then increments the pointer, but the pointee is not incremented at all. It effectively invokes undefined behaviour due to the pointer being incremented.
That's why it's always better to write readable code so that you don't have to worry about precedence.
Use a local variable and use it to increment in the loop and finally assign it to *num_inputs.
int count = 0;
while( scanf("%d", &array[i]) != EOF ) {
i++;
count++;
if (i == (size-1))
break;
}
*num_inputs = count;

Resources