Getting error - local variable referenced before being initialized - c

I have written a simple function which reads in a pointer to an array. It looks at the elements of the array and compares adjacent values for equality. If they are equal it adds their value to "sum"
I am getting a runtime error telling me "local "sum" was referenced before being initialized." I don't understand this because sum is definitely initialized in my function. See code snipet.
int arrRead (char *Pinput){
int sum, a, b = 0;
while (*Pinput){
a = *Pinput;
++Pinput;
b = *Pinput;
if(a == b)
sum += a;
}
return sum;
}

int sum, a, b = 0;
here only b is initialized with 0.
sum and a are uninitialized.
You need to write:
int sum = 0, a = 0, b = 0;
Or, each variable on its own line:
int sum = 0;
int a = 0;
int b = 0;
Even if in your function technically only sum needs to be initialized for the algorithm to work, it is a very good practice to initialize all the variables upon declaration.
Another good suggestion by #melpomene is to narrow the scope of the variables. For instance a and b are used only in the while loop:
int sum = 0;
while (*Pinput){
int a = *Pinput;
++Pinput;
int b = *Pinput;
if(a == b)
sum += a;
}
return sum;

You’re not initializing sum with
int sum, a, b = 0;
Only b is being initialized. You need to add an initializer for sum as well.
int sum=0, a=0, b = 0;

The operator += adds the right side value to the left side value, and then stores the sum back into the left side value.
If sum is uninitialized, the operation sum += X invokes undefined behavior; the result depends on the previous value of sum.

Related

Can we initiate an array literal with variables in C?

I have been searching if we can initiate an array literal with variables but couldn't find it. Bit of context, I want to pass an array literal to a function. Below is what I am trying to do:
int fun(int * a, int num){
int sum=0;
for (int i=0; i< num; ++i){
sum = sum + a[i];
}
return sum;
}
int main(){
int a = 3, b =2, c = 1 ;
int x[3] = {a,b,c}; // Is this legal? It compiles fine on all compilers I tested.
int p = fun( (int[3]){a,b,c} , 3); // I want to do something like this. pass a literal to the fucntion
return 0;
}
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
The string literal defined in this record
int p = fun( (int[3]){a,b,c} , 3);
has automatic storage duration. So you may initialize it with non-constant expressions in particularly using the variables a, b, and c.
Pay attention to that as the function does not change the passed array then the first parameter should have the qualifier const and to avoid overflow it is better to declare the return type as long long int.
Here is a demonstration program.
#include <stdio.h>
long long int fun( const int * a, size_t n )
{
long long int sum = 0;
for ( size_t i = 0; i < n; ++i )
{
sum += a[i];
}
return sum;
}
int main( void )
{
int a = 3, b = 2, c = 1 ;
printf( "%lld\n", fun( ( int[] ){a, b, c} , 3 ) );
}
Your code (sans the extra x array) compiles just fine with -std=c99 so yes, I'd say it's standard C99 code.
#include <stdio.h>
int fun(int a[], int num) {
int sum = 0;
for (int i = 0; i < num; ++i) {
sum = sum + a[i];
}
return sum;
}
int main() {
int a = 3, b = 2, c = 1;
int p = fun((int[3]){a, b, c}, 3);
printf("%d", p);
return 0;
}
This would not be allowed if the initializer is static, since the value needs to be assigned before the program executes. From C99:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
Otherwise, each initializer needs to be an "assignment-expression" or, in other words, a valid expression that can be assigned to an object.
So yes, this is legal in C.
Well, yes. The array is being initialized as it should which can be tested by printing it.
The array is also being sent to the function properly as p returns 6. However, do note that you are making a new array to send to the function.

swap pair to make sum equal

Question: Given two arrays of integers A[] and B[] of size N and M, the task is to check if a pair of values (one value from each array) exists such that swapping the elements of the pair will make the sum of two arrays equal.
My approach:
find sum of both arrays.
Identify array with larger sum(denote with A[]).
Sort A.
For all values in B binary search (sum(A)-sum(B)/2 + B[i]) in A, if found return true.
Return false.
code:
int sum(int a[], int n){
int s=0;
for(int i=0; i<n; i++){
s+= a[i];
}
return s;
}
int findSwapValues(int A[], int n, int B[], int m)
{
// Your code goes here
int a = sum(A, n);
int b = sum(B,m);
int t;
int *temp;
if(a<b){
temp = A;
A = B;
B = temp;
t = n;
n = m;
m = t;
t = a;
a = b;
b = t;
}
sort(A, A+n);
for(int i=0; i<m; i++){
if(binary_search(A,A+n,(a-b)/2+B[i])){
return 1;
}
}
return -1;
}
Doubt: My algorithm is failing for some test cases(not TLE). As the test cases are very large, it's difficult to reason out the problem in the algorithm. I searched online and understood other approaches. My only curiosity is why its incorrect?
I think the error in your code is that you find B[i] + (a-b)/2.
The problem with this is that if (a-b) is an odd value, division by 2 will round it down to the nearest integer and you end up finding the wrong value.
What you can instead do is check if the difference is odd before even swapping the arrays, and if it is true, straight-away return -1 because if the difference is odd, no such pair can ever exist.
I hope I cleared your doubt :).

Implement F# List.scan in C?

How would you implement a function with the same behavior as List.scan in F#?
Here is the description:
Applies a function to each element of the collection, threading an
accumulator argument through the computation. This function takes the
second argument, and applies the function to it and the first element
of the list. Then, it passes this result into the function along with
the second element, and so on. Finally, it returns the list of
intermediate results and the final result. (link)
Of course I have attempted myself and here is my pseudocode (I do not expect you to provide working c-code btw): For the call scan(myop, ne, x), I have the pseudocode
int n = length(x);
char *b = (char*)malloc(n); //Allocate n bytes
b[0] = ne;
int i = 0;
while (i < n) {
bool tmp = myop(b[i-1], x[i]);
bool b[i] = tmp;
i = i+1;
}
bool list y = b;
but this fails for i > 0 since then b[i] is not initialized. How would you implement this?
but this fails for i > 0 since then b[i] is not initialized
In your pseudo code:
bool tmp = myop(b[i-1], x[i]);
It will be failed when i = 0 (it means at the first time you enter the while loop), because you try to access the index -1 (i = 0, so b[i-1] becomes b[-1]) of b, it is undefined behavior.
You have to begin the while loop at i = 1 at least. So, before the loop:
b[0] = ne;
int i = 0;
Can change to:
b[0] = ne;
// do something with b[0] if you want.
int i = 1;
In your code, you refer to the previous element even for i == 0, which is incorrect. You could special case the first element by storing b[0] = myop(ne, x[0]) and start the loop at i = 1, but this solution would not work for an empty source list (n == 0). Furthermore, length(x) cannot be computed from a pointer, only from an actual array as sizeof(x) / sizeof(*x). It is best to pass the size as a separate argument.
Here is a C function that performs the semantics of List.scan for int arguments, taking a pointer to the function, an initial value, an array of int values, the length of this array and a pointer to the destination array, which can be the same as the source array:
int array_scan(int (*func)(int, int), int v1, const int *src, size_t count, int *dest) {
for (size_t i = 0; i < count; i++) {
int v2 = src[i];
dest[i] = v1;
v1 = func(v1, v2);
}
return v0;
}
In C there is no way to define lambda expressions inline, so you must define the function separately with a name and pass it explicitly to array_scan.

Understanding fractional knapsack, arrays and pointers

Just started learning C programming and decided to take a class in algorithmic Toolbox on Coursera. One of the challenges is writing a code using fractional knapsack, maximizing the value of loot and a pseudo code was given to help in coding the solution. Below are the pseudo code and the code I wrote for the pseudo code.
#include<stdio.h>
int min(int a, int b)
{
if (a < b)
return a;
else
return b;
}
int knapsack(int value[], int weight[])
{
int capacity = 100;
int val = 0;
int array[] = { 0 };
for (int i = 1; i < capacity; i++)
{
if (capacity == 0)
{
return val;
}
for (int i = 1; i < capacity; i++)
{
if (weight[i] > 0 && (value[i] / weight[i]))
{
int a = min(weight[i], capacity);
val = val + a * (value[i] / weight[i]);
weight[i] = weight[i] - a;
array[i] = array[i] + a;
capacity = capacity - a;
}
}
}
return val;
}
int main()
{
int value[100];
int weight[100];
scanf("%d", &value[100]);
scanf("%d", &weight[100]);
printf("%d", knapsack(value[100], weight[100]));
return 0;
}
pseudo code
Knapsack(W, w1,v1,......wn,vn)
A <-- [0,0,], V <-- 0;
repeat n times:
if W = 0:
return (V,A)
select i with Wi > 0 and max vi/wi
a <-- min(wi, W)
V <-- V + a(vi/wi)
wi <-- wi - a, A[i] <-- A[i] + a, W <-- W - a
return (V, A)
I am getting errors when I compile such as "passing argument 1 of 'knapsack' makes pointer from integer without a cast [-Wint-conversion]"
printf("%d", knapsack(value[100],weight[100]));
"expected int * but argument is of type 'int'"
int knapsack(int value[], int weight[])
I also want to know if it is a good practice to declare int value[], int weight[] in the function int knapsack argument and also more explanation in using arrays and pointers in situations like this.
int knapsack(int value[], int weight[])
The above statement gives the compiler the information about HOW the function should be called (type of arguments) and WHAT the function will return.
It says the function knapsack will return an integer value (the 1st int).
Its name is knapsack (case-sensitive).
It expects two arguments: an integer array (named value) and an integer array (named weight).
Points 1, 2 and 3 together make up the signature of a function.
To call the function you have to pass 2 integer arrays as its arguments.
The mistake : value[100] corresponds to an INTEGER ENTRY in the array and not the array itself.
To pass the array you should pass the array name as its argument, which your function expects.
Call the function like this: knapsack(value, weight)
value corresponds the array value and weight corresponds to the array weight
Also, passing value[100] corresponds to some garbage value that is not within the array bounds as you can only access elements ranging from value[0] to value[99] (0-based indexing).

How to make Fibonacci equation? (Error about uninitialized variable)

#include<stdio.h>
int main(void)
{
int a, b, c, n;
printf("What Fibonacci number would you like?:");
scanf("%d", &n);
if (n == 0 || n == 1)
return printf("%d", n);
else
for (c = 0; c < n; c++)
{
c = a + b;
a = b;
b = c;
}
printf("%d ", c);
return 0;
}
I have made this program for using Fibonacci equation. But I get following errors during compilation:
Error 1 error C4700: uninitialized local variable 'a' used d:\computer programming c++\20150923\20150923\20150923-1.c 15 1 20150923
Error 2 error C4700: uninitialized local variable 'b' used d:\computer programming c++\20150923\20150923\20150923-1.c 15 1 20150923
How can I fix it??
Change int a, b, c, n; as below in the code.
int a = 0, b = 1, c, n; /*Here you initialize the variables a to zero and b to one*/
You are trying to access the variables a and b without initializing it. As they are local variables, they contain garbage values.
When executing this line c = a + b;, the value of a and b are garbage values which may alter the way the code behaves which apparently leads to undefined behavior.
Well the compiler is right, you have to initialize variables before use, e.g.
int a = 0, b = 1, c = 0, n = 0; // etc.
Otherwise you will trigger undefined behaviour (which you should try to avoid when using languages such as C or C++) if you read values of uninitialized variables.
And indeed as noted in the comments it doesn't make sense to have c as loop index.
You have to initialize the variable declared. Since you didn't declare a and b, compiler is throwing the error.
Also you need to change c<n to c<=n to get the required fibonacci number
So your final code will look like this:
#include<stdio.h>
int main(void)
{
int a=0, b=1, c, n;
printf("What Fibonacci number would you like?:");
scanf("%d", &n);
if (n == 0 || n == 1)
return printf("%d", n);
else
for (c = 0; c < =n; c++)
{
c = a + b;
a = b;
b = c;
}
printf("%d ", c);
return 0;
}
In addition to initializing a and b, the code needs to use a separate variable for a loop counter (I used i). By using unsigned int, n can be up to 47, with result = 2971215073. I changed the summation to c = b + a since this corresponds to fib(i) = fib(i-1) + fib(i-2);
#include<stdio.h>
int main(void)
{
unsigned int a=0, b=1, c, i, n;
printf("What Fibonacci number would you like?:");
scanf("%d", &n);
if (n == 0 || n == 1){
printf("%u\n", n);
return 0;
}
for (i = 2; i <= n; i++)
{
c = b + a;
a = b;
b = c;
}
printf("%u\n", c);
return 0;
}

Resources