I'm new to C and I can't figured it out why this code does not work properly.
The whole idea was to enter few numbers and output amount of even numbers.
int n, p;
printf("How many numbers would you like to enter?\n");
scanf("%d", &n);
int array[n];
printf("Enter your numbers\n");
for (int i = 0; i == n; i++) {
scanf("%d\n", &array[i]);
if (array[i] % 2 == 0) {
p++;
}
}
printf("Amount of even numbers: %d", p);
There are multiple problems in your code fragment:
p is uninitialized: the behavior is undefined. You must initialize p as int p = 0;
scanf("%d\n", &array[i]); will consume any trailing white space, forcing the user to type the next value before returning. Just use scanf("%d", &array[i]);
the loop test is incorrect: i == n is false at the first iteration unless n is 0. You should write:
for (int i = 0; i < n; i++) {...
Note that you do not need to store the input values into an array but you should check the return value of scanf() to avoid undefined behaviour on invalid input:
#include <stdio.h>
int main() {
int n, val, p = 0;
printf("How many numbers would you like to enter? ");
if (scanf("%d", &n) != 1) {
printf("invalid input\n");
return 1;
}
printf("Enter your numbers: ");
for (int i = 0; i < n; i++) {
if (scanf("%d", &val) != 1) {
printf("invalid input\n");
break;
}
if (val % 2 == 0) {
p++;
}
}
printf("Amount of even numbers: %d\n", p);
return 0;
}
There are multiple issues:
You haven't given an initial value for the variable p. Many programming language may give it a default value of 0 by default, by that's not the case with C/C++. In C/C++, the default value for a variable is simply a garbage value. What you're doing is incrementing a garbage value instead of incrementing a zero.
Your loop condition is wrong. You should loop while i < n, not i == n.
If you fixed these 2 points, your code will work. But wait! that doesn't mean the code is good. There are still potential issues:
NEVER create an array of unknown size on the stack. You don't know how large number the user may enter. Your program will crash, which is bad.
You're not using the array anyways. You can just take the number and increment your counter.
C is an unsafe language. Unlike many other languages, it does not do anything for you unless you tell it to. I the line:
int n,p
You create two variables, this tell the compiler to create space for them on the stack. What is does not tell the compiler is what to put into those variables. What ends up happening is whatever was in those memory locations at the time end up in the variables. This can be literally anything and in C terminology is undefined behaviour. (In C undefined is the same as very bad).
What you need to do to fix things is to use:
int n = 0;
int p = 0;
You can save the work of initializing n since scanf does it for you but until you are sure it is a good idea, always initialize variables.
As an aside, be careful with scanf you case is fine but when dealing with strings, scanf might overflow your variable. To be safe use sscanf. This allows you to specify your size.
Related
I need to know if I have used free() correctly while attempting to free dynamically allocated memory for an array of pointers to int's.
My code is modified from a code snippet out of one of my books and is the beginning of a program which requests temperature readings for three cities.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ctr, num, num2 = 0, ctr2 = 0;
int* temps[3];
for(ctr = 0; ctr < 3; ctr++)
{
puts("how many readings for the city?");
scanf(" %d", &num);
temps[ctr] = (int*)malloc(num * sizeof(int));
num2 += num;
while(ctr2 < num2)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
}
for(ctr = 0; ctr < 3; ctr++)
{
free(temps[ctr]);
}
getchar();
getchar();
return (0);
}
I know that a pointer which is assigned memory using malloc() may have values assigned and accessed through a combination of a loop and array indexes. Hence I have assigned values from user input using the indexes of a two dimensional array, and need to know if I used free correctly. I know this is extremely sloppy coding and I am merely seeking to understand free correctly to prevent any potential memory leaks.
it's okay since you respect the same number of loops for allocation and deallocation with the same statement:
for(ctr = 0; ctr < 3; ctr++)
Just make sure that temps can hold at least 3 elements, which is the case, and that num is not zero or undefined (test return value of scanf & value of num). You can use a sizeof formula in your case to avoid hardcoding the value, only because you have an array of pointers, not pointers on pointers.
also avoid casting return value of malloc. And use the size of the element, instead of hardcoding as int (so if type of the pointer changes, your sizes are still right). Improvement suggestion for allocation:
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
puts("how many readings for the city?");
if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); } // or better error handling
temps[ctr] = malloc(num * sizeof(*temps[ctr]));
You may still get a segmentation fault when calling free if you corrupt the memory when filling your arrays (a comment suggests it does, since num2 grows and grows). If you get such errors, run your code with valgrind, or just perform allocations/deallocations (and not the rest) to find which part of the code causes the problem.
The proper way of freeing the dynamically allocated memory is to free it after you check if it has been allocated at the very first place or not. As your loop structure is same for allocating and freeing, there wont be any problem here as such if all the allocations are successful. Therefore I suggest you check at all the places if the allocation is successful after allocating and also check if the memory is allocated before freeing.
Following code will make sure all the cases:
scanf(" %d", &num);
/*
* check here if the value of ctr in non-negative and in the appropriate range
*/
temps[ctr] = (int*)malloc(num * sizeof(int));
if (temps[ctr] == NULL) {
printf ("Memory allocation failed\n");
/*
* appropriate error handling
*/
}
Also, check when you are freeing the memory to be on the safer side.
for(ctr = 0; ctr < 3; ctr++)
{
if(temps[ctr]) {
free(temps[ctr]);
}
}
Also there is a bug in your code where after the first iteration itself you will get memory out of bound error, as the variable ctr2 in never reinitialized.
num2 += num;
while(ctr2 < num2)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
Here if the value of num was 20 in the first iteration, then in the second iteration you will end up taking the input starting from temps[1][20], and assuming the value of num in the second iteration to be 5, you have allocated just 5 * sizeof(int)), so obviously you are going out of bounds when you try to access temps[1][20].
Please let me know if the following code would be considered acceptable:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ctr, num, ctr2 = 0;
int * temps[3];
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
puts("how many readings for the city?");
if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); }
temps[ctr] = (int *) malloc(num * sizeof(*temps[ctr]));
while(ctr2 < num)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
ctr2 = 0;
}
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
free(temps[ctr]);
}
getchar();
getchar();
return (0);
}
While I was learning to code in C about structure and pointers, I tried to make a program that calculate grades of students.
I thought it would work from my previous experiences for such calculation without pointers and structure. But with those, it gave me wild results in the program.
#include <stdio.h>
#include <string.h>
/*
The program will scan year, name, score of three different subjects,
and calculate the sum and the average.
Three different people (using array) will be taken into account.
*/
struct grade {
int year;
char name[20];
int score[3];
int total;
float avg;
};
void main() {
struct grade p[3];
char str = 'c';
char *pstr = NULL;
int i, j;
pstr = &str;
for (j = 0; j < 3; j++) {
printf("Year of Admission: ");
scanf("%d", &p[j].year);
printf("Name of the Student: ");
scanf("%s", pstr);
strcpy(p[j].name, pstr);
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
scanf("%d", &p[j].score[i]);
p[j].total += p[j].score[i];
}
p[j].avg = p[j].total / 3.0;
}
for (j = 0; j < 3; j++) {
printf("%s's\n", p[j].name);
printf("Total score: %d\n", p[j].total);
printf("Average: %.2f\n", p[j].avg);
}
}
I could have written each of three different subjects as one variable but for an extra "challenge", I made an array inside the structure.
int score[3];
However, the program only prints out extremely small number -89541694... for both totals and averages.
I assume that this particular line inside a for-loop is a problem.
scanf("%d", &p[j].score[i]);
But I could not figure out why. I am really new to pointers and still learning them.
I hope for your generous teaching and explanations.
Thank you in advance.
Local variables are not initialized with 0, so you just need to zero it before calculating total:
p[j].total = 0;
before
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
scanf("%d", &p[j].score[i]);
p[j].total += p[j].score[i];
}
The variable pstr points to a single char. A string in C needs to be at least two characters for a single-character string: The actual character, and the null terminator.
When you use e.g. scanf to read a string, the function will write at least two bytes to the memory pointed to by pstr. But since it only points to a single byte you will write out of bounds and that leads to undefined behavior.
If you want to be able to read more than a single character you need to have more space allocated for the string. And you need to limit scanf so it will not write out of bounds.
For example
char pstr[40]; // Allows for strings up to 39 character, plus terminator
// ...
scanf("%39s", pstr); // Read at most 39 characters from standard input, and write to pstr
Another problem is that local variables are not automatically initialized, their values will be indeterminate.
That means the contents of the array p is unknown and seemingly random.
When you do
p[j].total += p[j].score[i];
you use the seemingly random value of p[j].total to calculate another seemingly random number.
To initialize all structures and all their members to "zero" in the array, do e.g.
struct grad p[3] = { 0 };
Instead of making pstr a pointer you might wanted to do somehting like this
char pstr[30];
And accordingly you will scanf the string using scanf("%29s",pstr); and check it's return value.
To describe the problem a bit - you had a pointer pointing to a char which is not capable of holding an input characters and the corresponding \0 (nul terminating character). As a result this gives rise to undefined behavior. And then using it in strcpy is also an illegal code. (Undefined behavior).
Here the solution I gave simply declared an array of 30 characters and we limited the string input using scanf upto 29 characters because we need to store the terminating null.
Showing you atleast a bit of code to make you understand how to write these codes:-
if( scanf("%29s",pstr)!= 1){
fprintf(stderrm"Error in input");
exit(EXIT_FAILURE);
}
Another problem is initialize the variables - here you used p[j].total += p[j].score[i]; What is the value of p[j].total initially. It contains garbage value. In the loop make p[j].total = 0; first. That will give you the correct result.
Note: The wild results are the garbage value resulted from addition of some garbage value with p[j].score[i].
Also note that without making the changes that I said if you only change the initialization thing then also code is not guranteed to work. undefined behavior is undefined behavior - cases may arise which will simply crash the program making you wonder where you went wrong.
Illustration code may help you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
The program will scan year, name, score of three different subjects,
and calculate the sum and the average.
Three different people (using array) will be taken into account.
*/
struct grade {
int year;
char name[20];
int score[3];
int total;
float avg;
};
int main(void) {
struct grade p[3];
char pstr[20];
int i, j;
for (j = 0; j < 3; j++) {
printf("Year of Admission: ");
if(scanf("%d", &p[j].year)!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
printf("Name of the Student: ");
if(scanf("%19s", pstr)!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
strcpy(p[j].name, pstr);
p[j].total = 0;
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
if(scanf("%d", &p[j].score[i])!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
if(p[j].score < 0){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
p[j].total += p[j].score[i];
}
p[j].avg = p[j].total / 3.0;
}
for (j = 0; j < 3; j++) {
printf("%s's\n", p[j].name);
printf("Total score: %d\n", p[j].total);
printf("Average: %.2f\n", p[j].avg);
}
return 0;
}
In fact instead of using the pstr just input the names directly in the structure variable instance itself. No need to use a temporary variable.
I'm writing a program that requires me to do a union of two arrays. Here is my code so far.
I get Segmentation fault as an error after I enter set A.
#include <stdio.h>
void Union(int a[], int b[], int set1, int set2)
{
int u[20], i, j, unionIndex=0,trigger;
for(i=0; i<set1; i++)
{
u[unionIndex] = a[i];
unionIndex++;
}
for(i=0; i<set2; i++)
{
trigger=0;
for(j =0; j<set1; j++)
{
if(b[i] == u[j])
{
trigger =1;
break;
}
}
if(trigger =0)
{
u[unionIndex]=b[i];
unionIndex++;
}
}
for(i=0;i<unionIndex;unionIndex++)
{
printf(" %d",u[i]);
}
}
int main(void) {
int N=0;
int M=0;
int i;
int j;
printf("Please enter the number of elements in set A: ");
scanf("%d",N );
int a[N];
printf("Enter the numbers in set: ");
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
printf("Please enter the number of elements in set B: ");
scanf("%d",M );
int b[M];
printf("Enter the numbers in set: ");
for(j=0;i<M;i++)
{
scanf("%d",&b[i]);
}
Union(a,b,N,M);
return 0;
}
I'm pretty sure the issue has something to do with arrays because the program will compile but i get the error right after the user enters set A. I'm a beginner at C but I know a lot more about Java, so I'm thinking this has something to do with memory allocation. I'm not really sure how to solve the issue, so if you could point me in the right direction that would be helpful.
You need to pass the address of the variable to scanf()
Change
printf("Please enter the number of elements in set A: ");
scanf("%d",N );
to
printf("Please enter the number of elements in set A: ");
scanf("%d", &N);
Same goes for other place
printf("Please enter the number of elements in set B: ");
scanf("%d", &M);
There is another possible mistake
Its here
for(j =0; j<set1; j++)
{
if(b[i] == u[j])
In this set1 is equal to N, so j will go from 0 to N-1. And array u[] has only 20 elements. There is a possibility of array access out of bound if some user enter value more then 20 for N.
The problem, as I see it is in
scanf("%d",N );
and
scanf("%d",M );
It invokes undefined behavior as scanf() needs the argument to a format specifier to be a pointer to the type.
Just to clarify, you're essentially passing the address as 0 (value of the variable), which is not a valid addres, anyway.
You need to pass the address there, like
scanf("%d", &N );
and
scanf("%d", &M );
That said, in your Union() function, you're using a user-defined value to limit the for loop, against a constant value 20. In case the user input is more than 20, you'll be overrunning the memory which invokes undefined behavior.
The reason you're getting the segmentation fault is because of how you're calling scanf when reading in N and M. The %d format specifier for scanf expects an int *, i.e. the address of an int, but you're passing in an int. This is undefined behavior.
So you can fix them like this:
scanf("%d",&N );
....
scanf("%d",&M );
Some addtional bugs:
When looping to read in the values for b:
for(j=0;i<M;i++)
{
scanf("%d",&b[i]);
}
You have the wrong loop indexes:
for(j=0;j<M;j++)
{
scanf("%d",&b[j]);
}
When checking trigger:
if(trigger =0)
This is an assignment, not a comparison:
if(trigger == 0)
When looping to print out u:
for(i=0;i<unionIndex;unionIndex++)
You're incrementing the wrong variable:
for(i=0;i<unionIndex;i++)
Finally, u need to have a length of at least set1 + set2, otherwise you risk writing off the end of the array:
int u[set1+set2];
Fix those and you should get the desired results.
I'm trying to write a simple program that'll prompt the user to enter N numbers, store them in an array, then just sum them all up
I understand I can just do this with a recursion but I'm trying to learn how array works
Example:
1 (hit enter)
2 (hit enter)
...
10 (hit enter)
Expected output: 55
#include <stdio.h>
int main (void){
int n;
int a[n];
int counter;
printf("How many numbers do you want to enter? \n");
scanf("%d", &n);
printf("OK! now enter your number: \n");
for (int i = 0; i <= n; i++){
scanf("%d", &a[i]);
counter =+ a[i];
}
printf("The answer is: %d\n", counter);
return 0;
}
Right now there's no error message, no output, just the standard windows error message
"scanner.exe has stopped working..."
I'm using Win8 and GCC compiler
First of all, you can't create an static array without first knowing its size. You first need to ask the user for the "n" variable and then declare your array.
You also need to explicitly initialize your counter variable to be zero before you start counting. In C, variables don't default to 0 when you declare them.
The operator "=+" doesn't exist AKAIK, change it to "+=".
Last but not least, the limit in your loops is a little off, you're asking for 11 values ;)
(I edited this post, I was wrong about only asking for 9 values. I tend to confuse that sort of stuff)
#include <stdio.h>
int main (void){
int n;
int counter = 0;
printf("How many numbers do you want to enter? \n");
scanf("%d", &n);
int a[n];
printf("OK! now enter your number: \n");
for (int i = 0; i < n; i++){
scanf("%d", &a[i]);
counter += a[i];
}
printf("The answer is: %d\n", counter);
return 0;
}
You are using variable length arrays. At run time the value of n must be known. Place the declaration
int a[n];
after taking input for n, i.e, after scanf("%d", &n); and initialize counter to zero before using it otherwise you will get garbage value (because of undefined behavior).
Also change the for loop condition from i <= n to i < n.
After this line:
int n;
What do you think the value of n is?
Now go to the next line:
int a[n];
How big is this array?
Can you access it properly?
This program takes the first number in a file and indicates how many numbers are going to be after it, then does various other things with the numbers that follow.
It seems like scanf is causing an infinite loop when trying to read from the file. WHen I run the program not even the check at 1 works
Here is the code:
#include <stdio.h>
int main(void) {
int N, a, n;
int x=0;
int t=0;
printf("1"); //Check
scanf("%d", &N);
printf("2"); //Check
int nums[N];
int i;
printf("%d", &N); //Check
for (i=0; i<N; i++)
{
scanf("%d", &nums[i]);
t+=nums[i];
if (nums[i] > x) x=nums[i];
if (i=0 || nums[i] < n) n = nums[i];
}
a = t/N;
printf("Number Processed: \t%d\n", &N);
printf("Maximum: \t%d\n", &x);
printf("Minimum: \t%d\n", &n);
printf("Total: \t%d\n", &t);
printf("Average: \t%d\n", &a);
}
The way i run the program is
gcc -lab16
./a.out <in1
where in1 is text and has the numbers
7
6
-30
90
3903
-934
443
445
Thanks for your time.
if (i=0 || nums[i] < n) n = nums[i];
you are assigning i = 0, so the loop never realy advances! You probably wanted i == 0. This is causing the infinite loop.
Other issue: int nums[N]; - if you want an array of dynamic [determined in run-time] size, you will probably need to malloc() it.
Update: note that int nums[N] is valid in C99, so if your assigment is assuming C99 you should not worry about this issue. Otherwise - malloc() will be needed:
int* nums = (int*) malloc(sizeof(int) * N)
And don't forget to free(nums) before the program ends, or you will get memory leak.
if (i=0 || nums[i] < n) n = nums[i];
This is the culprit. You are making an assignment i=0 when you should do a comparison : i==0
Your loop goes to infinity because everytime you are i to 0.
Moreover, the code you gave us, gave me an error, because you were creating new variables during runtime.
#include <stdio.h>
#include "stdlib.h"
int main(void) {
int N, a, n;
int x=0;
int t=0;
int i;
int *nums;
printf("1"); //Check
scanf("%d", &N);
printf("2"); //Check
nums = malloc(N*sizeof(int));
....
There are numerous problems with this code.
You mistook assignment for comparison:
i=0
sets i to zero. You probably meant
i==0
which checks whether i is equal to zero.
You should check the value returned by scanf(). When data read by scanf() doesn't fit the format you specified it leaves the data in the buffer and the next call to scanf() sees the same data again.
The reason that the first printf() doesn't print anything is most likely that you are not printing any newline. Note that on some output devices like terminals output is line-buffered.
You are passing a pointer to a variable to printf(), but your format specifies %d. You probably meant the variable itself, not a pointer to it.
Also, if you need an array of length dependent on a value known only at runtime, you need to allocate it on the heap, e.g. using malloc().