I wrote a C program that is behaving in a way I don't understand. I am posting this in the hope that I will learn a bit more about C. The code seems to be writing variable names into other variables using fscanf when that was not asked of it at all...
#include <stdio.h>
#include <stdlib.h>
int main() {
float BCL[6];
float varsRA[23],varsLA[23],varsBB[23],varsPV[23];
FILE *inputfil;
int i;
inputfil = fopen ("file.txt", "rt");
for(i=0;i<24;i++) {
fscanf(inputfil,"%f %f %f %f\n", &(varsRA[i]), &(varsLA[i]), &(varsBB[i]), &(varsPV[i]));
}
i=23;
printf("vars%d:%f %f %f %f\n",i,varsRA[i], varsLA[i], varsBB[i], varsPV[i]);
i=0;
while(!feof(inputfil)) {
fscanf(inputfil,"%f ",&(BCL[i]));
i++;
}
i=23;
printf("vars%d:%f %f %f %f\n",i,varsRA[i], varsLA[i], varsBB[i], varsPV[i]);
fclose(inputfil);
return 0;
}
The outcome is:
vars23:-66.336823 -68.164223 -57.850136 -60.762585
vars23:-66.336823 -68.164223 -57.850136 177.000000
Why was the last value of varsPV changed to 177, which is the first value of BCL, when I read the rest of the file?!
Many thanks for your help,
Marta
The program has undefined behaviour as it is accessing beyond the bounds of the arrays:
for(i=0;i<24;i++) {
fscanf(inputfil,"%f %f %f %f\n", &(varsRA[i]), &(varsLA[i]), &(varsBB[i]), &(varsPV[i]));
}
Array indexes run from 0 to N - 1, where N is the number of elements in the array.
The arrays are defined with 23 elements, meaning valid indexes are from 0 to 22. Change the loop terminating condition to i < 23 or use a compile time constant to define the array size and the terminating condition to avoid duplicating that piece of information.
There are other out of bounds accesses in the program and this loop needs protection from going out of bounds:
i=0;
while(!feof(inputfil)) { /* i < 6 required */
fscanf(inputfil,"%f ",&(BCL[i]));
i++;
}
Always check the return value of fscanf() to ensure assignments were actually made. fscanf() returns the number of assignments made:
for (i = 0; i < 6 && 1 == fscanf(input, "%f", &BCL[i]); i++);
Your arrays aren't being defined big enough. The array varsRA[23] only contains 23 elements numbered 0 through 22. You're reading in 24 elements numbered 0 through 23. Change your array definitions to the following and you should be good to go.
float varsRA[24],varsLA[24],varsBB[24],varsPV[24];
Array indices in C are zero-based.
float varsRA[23],varsLA[23],varsBB[23],varsPV[23]
Those arrays have 22 as their last valid index, which makes 23 elements. That's why
for(i=0;i<24;i++)
writes one extra element to each of them. What you get is undefined behavior (so there is nothing reasonable to expect), but your particual kind of undefined behavior is overwriting a piece of another array (and probably some random memory location).
Related
Please read the code below.
#include <stdio.h>
int main(void)
{
char* a[4];
int i=0;
while(i<3)
{
char b[50];
scanf(" %s",b);//Assume user enters one two three
a[i++]=b;
}
i=0;
while(i<3)
printf(" %s ",a[i++]);//Why does it always print three three three
return 0;
}
Clarify the following:
Is it that b gets allocated same 50 bytes in memory each time so that all the elements of array a point to same 50 bytes and thus we get only three printed three times(i.e. what's entered last)
Since after the completion of while, array b can be removed very well but no it remains there every single time printing only three's. Why?
Is it not at all a coincidence that this code prints only three's when it could print one two three, one three three as well. What's wrong?
I know the question is very wrongly put. Forgive me for that. I am new here.
QUESTION #1:
The variable b is a variable that is strictly local to the
while loop.
Therefore, do not reference via a pointer any memory formerly used by b outside (after) the while loop.
Storage for b will be reallocated 3 times.
At the end of the while loop, b will go out of scope.
QUESTION #2:
After the while loop, a is not a valid pointer anymore
because a was assigned to point to b,
and b has gone out of scope after the while loop.
NEVERTHELESS, the memory allocated to b may still
not have been modified. You cannot predict what the value of dereferencing a will be after the while loop - since a is only assigned based on b.
QUESTION #3:
(Please see #2) The code that is dereferencing a after the while loop is using a stale pointer - I would not rely on the output.
The code in the question exhibits undefined behaviour because the second loop attempts to access the data that was only valid in the first loop. Therefore, there is very little that can usefully be said.
The question title is "does a variable declared in a loop get the same address each time the loop executes". Here's a proof by counter-example that the address of the variables in a loop need not always be the same, even in a single invocation of a non-recursive function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(0));
for (int i = 0; i < 3; i++)
{
int n = rand() % 30 + 5;
char a[n];
for (int j = 0; j < n - 1; j++)
a[j] = rand() % 26 + 'a';
a[n-1] = '\0';
printf("a: %p %2d [%s]\n", (void *)a, n, a);
char b[50+n];
scanf("%s", b);
printf("b: %p %2d [%s]\n", (void *)b, n+50, b);
}
return 0;
}
On a Mac running macOS Sierra 10.12.4 (using GCC 7.1.0), one run of the program (lv83) produced:
$ ./lv83 <<< 'androgynous hermaphrodite pink-floyds-greatest-hits-dark-side-of-the-moon'
a: 0x7fff507e53b0 23 [sngrhgjganmgxvwahshvzt]
b: 0x7fff507e5360 73 [androgynous]
a: 0x7fff507e53c0 9 [wblbvifc]
b: 0x7fff507e5380 59 [hermaphrodite]
a: 0x7fff507e53b0 26 [pqsbfnnuxuldaactiwvjzvifb]
b: 0x7fff507e5360 76 [pink-floyds-greatest-hits-dark-side-of-the-moon]
$
The address at which the two arrays are allocated varies depending on how big they are. By using different formulae for the sizes of the two arrays, the base addresses could be tweaked. It looks as though the compiler rounds the base address of the arrays to a multiple of 16.
I was doing a programming question and one of the sample output is 64197148392731290. My code for that question is correct as it is giving me the right answers for other test cases (output for those test cases are in single digit).
I understand that there will be too many iterations for the test case which has 64197148392731290 as output. So what should I do to get correct answer for that test case too.
Here is the code :
#include<stdio.h>
#include<string.h>
int main() {
int test_case;long long int i, j, count, n, k, k1;
scanf("%d", &test_case);
while(test_case--) {
scanf("%lld%lld", &n, &k);
char a[n];
count=0;
k1=k;
scanf("%s", a);
while(k1--) {
strcat(a,a);
}
for(i=0;i<(n*k);i++) {
if(a[i]=='a') {
for(j=(i+1);j<(n*k);j++) {
if(a[j]=='b') {
count++;
}
}
}
}
printf("%lld\n", count);
}
return 0;
}
Sample Input and Output :
Input:
3
4 2
abcb
7 1
aayzbaa
12 80123123
abzbabzbazab
Output:
6
2
64197148392731290
My task is to count the number of subsequences "ab" (not necessarily consecutive) in the new string. The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains two integers N and K, denoting the length of the initial string S and the number of repetitions respectively.
The second line contains a string S. Its length is exactly N, and each of its characters is a lowercase English letter.
If you are trying to store input in "int" that wont work coz this number its out of range, change it to "long long int"
Well the previous answer was sure wrong. Thanks for the code.
Sorry don't have time for detailed study but preliminary analysis tells me that maybe the error is because you are trying to store a sting of length 2n in a[n]. It works for smaller values since when you declare
char a[n];
^
variable known at runtime
it actually allocates a large block so that any value of n within range is possible. For large values strcat(a,a) will probably fail.
Basically somewhere down the line the string becomes corrupt. Most probably that is because of strcat. I suggest remove strcat, do something else to a similar effect.
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.
This is a homework project I was assigned some time ago... I've been successful in getting this far on my own, and the only hiccup I have left is (I believe) an issue with data types and overflow.
I've tried changing over to unsigned and double, and the code complies and still accepts input in the terminal, but it seems to hang up after that... nothing is printed and it looks like it's caught in a loop.
Here is the code...
/* pascaltri.c
* A program that takes a single integer as input and returns the nth line of
* Pascal's Triangle. Uses factorial() function to help find items of
* individual entries on a given row.
*/
#include <stdio.h>
#include <stdlib.h>
long factorial(long i)
{
long fact = 1;
while(i > 1)
{
fact = fact * i;
i = i - 1;
}
return fact;
}
main(void)
{
long n;
long *nPtr;
nPtr = &n;
scanf(" %i", nPtr);
if (n >= 0)
{
long k;
long *kPtr;
kPtr = &k;
for(k = 0; k <= n; k++)
{
long ans;
long *ansPtr;
ansPtr = &ans;
ans = factorial(n) / (factorial(k) * factorial(n - k));
printf("\n %i", ans);
}
return 0;
}
return 0;
}
It's not perfect or pretty, but it works up to an input of 13 (that is, row 14) of the triangle. Beyond that I start getting gibberish and even negative values sprinkled throughout the returns... much larger values break the code and return nothing but an exit error message.
Any ideas on how I can correct this problem? I've been staring at the screen for much to long to really see anything myself. Also, it's not essential, but I would like to print my return values on one line, rather than having them separated by a newline character.
1 5 10 10 5 1
Would the easiest way be to load the values into an array as they are computed, and then print the array? Or is there a built-in way I can tell the print statement to occur on only one line?
You are suffering from integer overflow. You may need to find a different approach to the algorithm to avoid having to calculate the large numbers.
In answer to your other point about the newline, you are explicitly printing the newline with the \n in your print statement. Remove it, and you will get answers printed on one line. You probably want to inlucde a final printf("\n"); at the end so the whole line is terminated in a newline.
Some other observations:
You don't need the first return 0; - the control will drop out of
the bottom of the if block and on to the second (should be only)
return 0; and not cause any problems.
You're declaring kPtr but not using it anywhere
You don't need to declare a separate variable nPtr to pass to scanf; you can pass &n directly.
For the garbage, you are most likely running into an integer overflow, that is, your calculated values become too large for the long data type. You should correct it by calculating your factorial function without explicitely calculating n!.
Change scanf(" %i", nPtr); to
scanf(" %ld", nPtr);
and printf("\n %i", ans); to
printf("\n %ld", ans);
to get printout on one line, use:
printf(" %ld", ans);
If you are using gcc, turn on warnings, i.e. use -Wall.
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