I need to populate an array of integers with an unknown number of elements. I am using a while loop to input values and exit the loop as a non integer value is entered. Outside the loop an integer j is initialized at 0 and used to address array elements inside the loop. At each round of the loop I check the value of j before and after the input value is assigned to array element v[j], then j is incremented.
Depending on the size chosen for the array in the declaration, (in the example below v[8]), index j is unexpectedly affected by the assignment itself: in the example below when j equals 11 before the assignment it becomes 2 after the assignment, thereafter messing it all up. As a result the code fails to assign the correct input values to the array.
I am surely lacking some deeper knowledge about C/C++ array management... anyone can help to to fill the gap explaining the apparently strange behaviour of my code?
#include <stdio.h>
int main()
{
int j = 0, m, v[8];
printf("Enter an integer: to finish enter x\n");
while (scanf("%d", &m))
{
printf("j before assignment:%d - ", j);
v[j] = m;
printf("j after assignment:%d - ", j);
printf("v[j] after assignment:%d\n", v[j]);
j++;
}
return 0;
}
You write beyond the array boundaries of v. To avoid this, check j in a for loop, e.g. replace while (...) with
for (j = 0; j < 8 && scanf("%d", &m) == 1; ++j) {
// ...
}
This way, the loop stops after the end of the array (v[7]) is reached.
To comment the "strange" behaviour, read about stack and stack layout, e.g. Does stack grow upward or downward?
As always, check the C tag wiki and the books list The Definitive C Book Guide and List
Related
I wrote this little code just to start learning some if statements and C coding in general. However, there is an issue. When running it, if the largest element is the last one, the code won't recognize it. Why is that?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int num[100];
int max;
int i;
printf("Enter 10 numbers: \n");
for(i = 1; i < 10; i++){
scanf("%d\n", &num[i]);
}
max = num[0];
for(i = 0; i < 10; i++){
if(max < num[i]){
max = num[i];
}
}
printf("The biggest nr is: %d", max);
return 0;
}
Your first loop should start from 0, not 1.
for(i = 0; i < 10; i++){
scanf("%d\n", &num[i]);
}
max already starts with an uninitialized value, here be dragons.
Inside of:
for (i = 1; i < 10; i++) {
scanf("%d\n", &num[i]);
}
max = num[0];
max has an indeterminate value because the loop's counter variable i starts at 0, not 1 which gives the result that the first element of the array wasn't assigned inside of the loop. So you end up assigning this indeterminate value to max.
To use an indeterminate value in the following code:
if (max < num[i]) {
max = num[i];
}
invokes undefined behavior.
"However, if I change i=0, the program asks me for 11 inputs before moving on. And among those 11 inputs, the program still won't count the last one, if it is the largest."
"When running it, if the largest element is the last one, the code won't recognize it. Why is that?"
It doesn't actually ask you for an 11th input for any presumed 11th array element as you think it does and the last in the loops1 treated element of the array is not the one you think it is. That is just an impression to you.
This behavior is caused by the newline character in the format string of the scanf() call:
scanf("%d\n", &num[i]);
The newline character (\n ) is equal to any white space and with this directive, scanf() reads an unlimited amount of white space characters until it finds any-non white space character in the input to stop consuming and the control flow continues to the next statement.
Why does scanf ask twice for input when there's a newline at the end of the format string?
It doesn't ask for the input of the 11th element of the array (as you think it does). It simply needs any non-white space character that the directive fails.
The last element of the array (which is treated inside of the loops1) is still the 10th (num[9]), not the 11th (num[10]) and so is the output correct when you initialize the counter to 0 and it prints:
The biggest nr is: 10
because 10 is the value of the last treated element num[9].
1) Note that you made a typo at the declaration of num -> int num[100];. With this you define an array of one hundred elements, but you actually only need one of 10 elements -> int num[10];.
Side Note:
Also always check the return value of scanf()!
if (scanf("%d\n", &num[i]) != 1)
{
// Error routine.
}
There are two problems in the code one after another:
The loop should begin from 0 instead of 1:
for (int i = 0; i < 10; i++)
The main problem is here:
scanf("%d\n", &num[i]);
_________^^____________
Remove the \n and your problem will be fixed.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am unable to understand how is it working. Can somebody explain me this code?
#include <stdio.h>
int main () {
/* local variable definition */
int i, j;
for(i = 2; i<100; i++) {
for(j = 2; j <= (i/j); j++) {
if(!(i%j)) break; // if factor found, not prime
}
if(j > (i/j)) printf("%d is prime", i);
}
return 0;
}
1.#include <stdio.h> is a header that defines three variable types, several macros, and various functions for performing input and output. In other words, it's basically a C-Library being referenced to add some other externally defined logic, besides the code below, like the size_t variable, which is the result of the sizeof keyword for example. That's just one example of what the the stdio.h header does but you can see more info here: https://www.tutorialspoint.com/c_standard_library/stdio_h.htm
2.int main() is an integer function (int) that uses a deprecated declaration style main(), meaning you shouldn't it anymore because it's outdated by other functions, and the main() function in particular is a function that takes an unspecified number of arguments (integers in this case) and then runs some operations with those integers.
Next, the curly braces are what contain all the logic inside of the int main() function. Then inside of it, on the line int i, j; , two local variables are declared (i and j) to be later used as placeholders for some integers that will be plugged into the function.
Below that, for(i = 2; i<100; i++) indicates there is a loop that sets the i variable to 2, then after the semi-colon i<100 means that the loop will continue to execute again and again as long as the variable i is less than 100. After yet another semi-colon, i++ means that each time that the loop runs, the variable i will increment by 1. So it starts at 2, then 3, then 4, etc, until i reaches 100 and the loop stops executing.
Next, for(j = 2; j <= (i/j); j++) is another loop inside of the first loop, but this time the loop is using the variable j as a placeholder/counter instead of the variable i (the variable used by the previous loop), which surrounds this loop starting with "for(j..." . This loop also setsj to 2 (the same way the surrounding loop set i to 2); as long as j is less than or equal to (i divided by j) the loop will continue to execute; and j will increment (increase) by one each time that the loop is run, the same way that i does in the loop that surrounds this one.
if(!(i%j)) break; // if factor found, not prime this line means that the loop will also stop executing (break) if the remainder of i divided by j does not equal zero.
if(j > (i/j)) printf("%d is prime", i); This line means that if j is greater than i divided by j that the loop will write/output the text to stdout (std out is the standard output device, a pointer to a FILE stream that represents the default output device for the application).
Lastly, the last return 0; line indicates a return from the function and the final curly brace encloses the functions logic/code. The main function also should return 0(also EXIT_SUCCESS) to identify that the program has executed successfully and -1 otherwise (also EXIT_FAILURE).
Additional Note - Loops in every programming language I've seen personally tend to have a few things in common:
i. An init counter, a value where the loop will initialize (start counting), inside the loop's parentheses and before the first semi-colon.
ii. A test counter, which will be evaluated each time that the loop continues, and if it evaluates to TRUE the loop will continue usually but if it evaluates to false then the loop will end. This is the part of the loop after the first semi-colon but before the second semi-colon.
iii. An increment/decrement counter, which increases or decreases the loop by some value each time that the loop is run. This is the part of the loop inside the parentheses, after the second semi-colon. If there is no increment counter or test counter that causes the loop to exit/break at some point, then this is known as an infinite loop. This is a very bad thing in programming because it will cause just about any computer program to crash since it will execute and consume computing resources indefinitely. Not good :)
Disclaimer: I don't actually code in C but the language has so many similarities with programming languages I do use, that I'm guessing this answer is very close if not 100% correct. Curious to hear some input from an expert C programmer though!
Your code is looping over all integers from 2 to 99, holding the actual number in i.
for(i = 2; i<100; i++)
Then, for every number i, the code is looping again over all integers from 2 to (i/j).
for(j = 2; j <= (i/j); j++)
Your loop's finishing condition is mathematically equivalent to j being smaller than the square root of i, since any larger integer j would already contain itself a smaller factor of i.
(To check this, get a paper and rewrite the inequality so hat i is the sole part of the right hand side of your condition.)
Then it checks whether or not j divides i.
(i%j)
If j is a factor of i, then i modulo j is zero and hence
if (!(i%j))
evaluates to true (since 0 is evualted as false and ! negotiates this) and you can break out of the loop since i has a divisor not being 1 or i, hence i is not a prime.
On the other hand, if the inner loop is finished, you have found a prime since it has only 1 and i as divisor.
Needles to say that this bruteforce approach is very slow for large integers (you won't crack RSA with that), but does this clarify your questions?
#include <stdio.h>
int main () {
/* local variable definition */
int i, j;
// Loop from 2 to 99; i will hold the number we are checking to
// see if it is prime
for(i = 2; i<100; i++) {
// now loop through the numbers checking each one to see if
// it is a factor of i (if it is, then i isn't prime). This
// loop stops when j^2 is greater than or equal to the number
// we are checking
for(j = 2; j <= (i/j); j++) {
// i % j (i modulus j) is 0 iff j is a factor of i. This
// if test relies on the fact that 0 is false in C (and
// all nonzero values are true)
if(!(i%j)) break; // if factor found, not prime
}
// this tests to see if we exited the above loop by failing
// the test in the for() statement, or whether we exited the
// loop via the break statement. If we made it through all
// iterations of the loop, then we found no factors, and the
// number is prime.
//
// note that a \n is missing at the end of the printf format
// string. The output will be "2 is prime3 is prime5..."
if(j > (i/j)) printf("%d is prime", i);
}
// returns from main() with a value of 0, which will result in
// the program exiting with an exit code of 0. An explicit
// exit(0) is better form here, but this is not incorrect.
return 0;
}
I have observed that memory allocated for array seems to be dynamic.
Here is the sample code I found in this tutorial:
#include <stdio.h>
main() {
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
n = n + 1;
while( j >= k){
LA[j+1] = LA[j];
j = j - 1;
}
LA[k] = item;
printf("The array elements after insertion :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}
and sample output:
The original array elements are :
LA[0]=1
LA[1]=3
LA[2]=5
LA[3]=7
LA[4]=8
The array elements after insertion :
LA[0]=1
LA[1]=3
LA[2]=5
LA[3]=10
LA[4]=7
LA[5]=8
How its working I did not get.
First, a general statement, for an array defined without explicit size and initialized using brace-enclosed initializer, the size will depend o the elements in the initializer list. So, for your array
int LA[] = {1,3,5,7,8};
size will be 5, as you have 5 elements.
C uses 0-based array indexing, so the valid access will be 0 to 4.
In your code
LA[j+1] = LA[j];
trying to access index 6, (5+1) which is out of bound access. This invokes undefined behavior.
Output of a code having UB cannot be justified in any way.
That said, main() is technically an invalid signature as per latest C standards. You need to use at least int main(void) to make the code conforming for a hosted environment.
The code has a buffer overflow bug! Arrays in C cannot be extended! You need to allocate enough space when you declare/define it.
You can declare additional space by supplying a size in the declaration:
int LA[10] = {1,3,5,7,8};
LA will now have room for 10 elements with index 0 through 9.
If you want more flexibility you should use a pointer and malloc/calloc/realloc to allocate memory.
Note:
There is a second bug in the copying. The loop starts one step too far out.
With j starting at 5 and assigning index j+1 the code assigns LA[6], which is the 7th element. After the insertion there are only 6 elements.
My conclusion from these 2 bugs is that the tutorial was neither written nor reviewed by an experienced C programmer.
To add on to the other answers, C/C++ do not do any bounds checking for arrays.
In this case you have a stack allocated array, so as long as your index does not leave stack space, there will be no "errors" during runtime. However, since you are leaving the bounds of your array, it is possible that you may end up changing the values of other variables that are also allocated in the stack if it's memory location happens to be immediately after the allocated array. This is one of the dangers of buffer overflows and can cause very bad things to happen in more complex programs.
I am have a multi-dimensional array that needs to be resolved, to solve for the unknown values (x1,x2,x3,..). In this multi-dimensional array, my array size in the i and j coordinate are different; B[n][n+1]. I know this Basic C, Gauss Jordan Method to solve for the unknown, is incorrect and would like someone to point in how to modify it..
This code is accurate for an Array with the same n values only; eg. A[n][n].
//Computation to solve
for(j=0; j<=n; j++)
{
for(i=0; i<=n; i++)
{
if(i!=j)
{
c=B[i][j]/B[j][j];
for(k=0;k<=n+1;k++)
{
B[i][k] = B[i][k] - c*B[j][k];
}
}
}
}
//Print Solution
printf("\nThe solution is:\n");
for(i=0; i<=n; i++)
{
x[i]=B[i][n+1]/B[i][i];
printf("\n x%d=%.3f\n",i,x[i]);
}
An example would be if my n=2. The array that i would want to solve is B[2][3].
0 -20 0 -1
0 30 -10 0
0 -10 10 1
The output of this code is
x1= -inf
x2=0.050
x3=0.000
The correct output should be
x1=0.00
x2=0.05
x3=0.15
This code is accurate for an Array with the same n values only; eg.
A[n][n].
No, the code already accounts for column n+1 (which holds the right-hand constant terms) in the loop
for(k=0;k<=n+1;k++)
{
B[i][k] = B[i][k] - c*B[j][k];
}
(since k runs up to n+1). So, it is correct in this regard.
An example would be if my n=2. The array that i would want to solve is
B[2][3].
C arrays are declared by specifying the number of elements in the array, not the highest index, so you want B[3][4].
The main fault of the shown code is its lack of the row swapping operation, which may be necessary if B[j][j] is zero, and the related test. We can implement that by inserting
if (!B[j][j])
{
for (i=j+1; i<=n; i++)
if (B[i][j]) { swap(B[j], B[i]); break; }
if (!B[j][j]) continue; // leave all-zero column as is
}
at the beginning of the for(j=0; j<=n; j++) loop body (implementing swap() left to the reader).
The correct output should be
x1=0.00
Whether this is correct is debatable, but if you want a variable where every number is a solution to take the value zero, you may insert
if (B[i][i] == 0 && B[i][n+1] == 0) x[i] = 0;
before the printf("\n x%d=%.3f\n",i,x[i]).
I´m trying to do a simple exercise where should I should enter 2 inputs (monto and loc) in a struct using pointers and malloc. When I try yo print the data it shows garbage. I tried to check what was happening so I print the data after entering and shows things like
-1414812757 -158839287345460020000000000000000000000.00
struct transaccion{
int loc;
float monto;
char nombre[50];
} cliente,*pcliente;
int cargadatos (struct transaccion*);
void mostrarlocalidad(struct transaccion*,int);
void mostrarestructura(struct transaccion*);
void main()
{
int tam=50,ll;
struct transaccion *pTrans;
pTrans=(struct transaccion*)malloc(sizeof(struct transaccion)*tam);
pTrans[0].monto=5;
if(pTrans==NULL){
puts("Falta memoria");
exit(3);
}
ll=cargadatos(pTrans);
mostrarlocalidad(pTrans,ll);
free(pTrans);
system("pause");
}
int cargadatos (struct transaccion *pTrans)
{
int i=0;
while (pTrans[i].loc!=0){
puts ("ingrese numero de localidad");
scanf("%d", &pTrans[i].loc); fflush (stdin);
puts ("ingrese monto");
scanf("%.2f",&pTrans[i].monto); fflush(stdin);
int j=0;
for (j=0; j<=i; j++) {
if (pTrans[j].loc==pTrans[i].loc){
pTrans[j].monto=pTrans[j].monto+pTrans[i].monto;
i--;
}
}
printf("%d %.2f \n",pTrans[i].loc,pTrans[i].monto);
i++;
}
return;
}
I´ve been trying many things for hours but I cant figure it out where are the errors.
The reason you're seeing garbage is because your j loop is wrong. Since you are iterating through <= i, your check will always be true. In the first entry, you're checking pTrans[j].loc==pTrans[i].loc with both i and j being 0. Therefore you set the values of j to itself, and decrement i. When your printf runs, you're printing pTrans[-1] and not pTrans[0] as you probably are thinking you're doing.
Your easiest fix is to change your j loop to be j < i and not j <= i. That way it won't ever run against itself which seems silly anyway.
There are three problems here caused by the same mistake - a wrong condition on the j loop.
What I assume you are trying to do is read into an array element, and
scan all previous array elements and see if you already have something at that location-in which case you want to use the "old" element for the count and then reuse the new element.
Now the range on the j loop being wrong will cause 3 problems:
You will ALWAYS read into element 0.
You will ALWAYS have the monto double what it should be
You will ALWAYS print array element [-1] which is not initialized and not what you ever intended.
This happens because when i=0, your j (being <=0) will compare pTrans[0].loc==pTrans[0].loc.
As this is always true, you will now double your pTrans[0].monto (not what you expect) giving a wrong result to start with.
Now i is decremented in an attemp to reuse it - making i==-1.
You now print this, uninitialized, unexpected [-1] element giving you whatever happens to be in that memory location.
Now you get hit by a third effect - you increment i making it 0, and iterate the while with the 0 element again.
ALL this is the result of one small mistake: using the condition j<=i in the j loop.
If you change this to
for (j = 0 ; j < i ; j++)
your program will probably work ok.
struct transaccion{
int loc;
float monto;
char nombre[50];
} cliente,*pcliente;
You declared two variables that you don't use anywhere.
pTrans=(struct transaccion*)malloc(sizeof(struct transaccion)*tam);
Casting from malloc is not necessary.
the following block should be placed before you use the pointer.
if(pTrans==NULL){
puts("Falta memoria");
exit(3);
}
This loop may or may not be executed, depending on the random value you will find in the specified memory area.
while (pTrans[i].loc!=0){
What is said in the other answers remains true as well.
Thanks a lot to everyone, now I realized that I made way to much mistakes. Also I know that there variables I´m not using its because of thing I didn't implement yet. I'll correct it and post the working code.