This program is returning garbage values in output of total marks and average marks.
even after declaring s.total=0 and s.marks[15]=0 in the beginning of program
//student database
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
struct student
{
int name[20];
int roll[5];
int total;
float avg;
int marks[15];
};
struct student s;
int subject_no,i;
s.total=0;
s.marks[15]=0;
printf("Enter the name of student:\t");
scanf("%s",s.name);
printf("enter the roll no:\t");
scanf("%d",&s.roll);
printf("Enter the number of subjects:\t");
scanf("%d",&subject_no);
for(i=0;i<subject_no;i++)
{
printf("Enter marks in subject %d:\t",i);
scanf("%d",&s.marks);
s.total=s.total+s.marks[i];
}
printf("total marks are:%d\n",s.total);
s.avg=(s.total)/(subject_no);
printf("The average is :%d",s.avg);
getch();
}
This is an illegal memory access: s.marks[15]=0.
If you have 15 entries in the array, then legal indexes are between 0 and 14.
So you can do s.marks[0]=0 or s.marks[6]=0, but you should not do s.marks[15]=0.
If you want to set the entire array to zero values, then you can iterate it:
for (i=0; i<sizeof(s.marks)/sizeof(*s.marks); i++)
s.marks[i] = 0;
Or simply use memset:
memset(s.marks,0,sizeof(s.marks));
You should explicitly clear your s structure with
memset (&s, 0, sizeof(s));
Of course your filling of s.marks[15] is out of bounds (undefined behavior and/or buffer overflow!!)
Your code never fills or uses s.roll[1] so why make s.roll an array?
At last, your first for loop should be
if (subject_no >= 15) exit(EXIT_FAILURE);
for(i=0;i<subject_no;i++) {
printf("Enter marks in subject %d:\t",i);
scanf("%d",&s.marks[i]);
s.total=s.total+s.marks[i];
}
It would be better to store the name in a char array, rather than an int array (although that will work)
Also, you have been inconsistent in you use of scanf with arrays.
Related
I need some help with a program I've been making for the university. Inside this program, it must be a function that must increase the price of a type of product according to a value given by the user. Fine, I've written the following function:
void increase_price(struct reg products[SIZE], int count){
int i;
float increase, perc;
char option;
printf("Type of product: ");
fflush(stdin); scanf("%c", &option);
printf("\nThe increase percentage: ");
fflush(stdin); scanf("%f", &perc);
for(i=0; i<count; i++){
if(products[i].type == option){
increase = products[i].price * (perc/100);
products[i].price += increase;
}
}
}// Fim increase_price()
The problem is that the increase's calculation always results in zero. I can't understand why it's happening. I also tried to print the 'perc' variable after receiving its input, but strangely it didn't work.
Some more code:
The definition of struct reg:
#include <stdio.h>
#include <conio.h>
#define SIZE 100
struct reg{
int cod;
char desc[30], type;
float price;
};
At the main function, the only usefull thing for this function is the call of the function itself, and, sure, the declaration of the struct and the count variable(whose value comes from another function according to the number of products).
The type is defined in another function in which you can add products. it's a litteral value like P (for pants), T (for T-shirt) etc.
Im trying to make a program which says how many times a specific digit appears on a 100 numbers sequence.
Meanwhile I got this error and I can´t understand what is the solution to this. I´d appreciate if you could get me some tip or the solution.
#include <stdio.h>
int main() {
int i, m, digit, val[99], count=0;
printf("Enter a number:");
scanf("%d", &val[0]);
while (val[0] < 0) {
printf("Enter a number:");
scanf("%d", &val[0]);
}
for (i=1;i<101;i++) {
val[i]=val[0]++;
printf("%d\n", val[i]);
}
printf("Enter a digit:");
scanf("%d", &m);
while (m<0||m>9) {
printf("Enter a digit:");
scanf("%d", &m);
}
do {
digit=val[i]%10;
val[i]=val[i]/10;
if (digit==m) {
count++;
}
}while (val[i]>0);
printf("The digit %d is printed %d times in this sequence.", m, count);
}
In the for loop you step outside of the array val of which the last index is 98. Instead of hard-coding the length of the array in several places it is more convenient to use a length macro, like this:
#define LEN(anArray) (sizeof (anArray) / sizeof (anArray)[0])
...
for (i = 1; i < LEN(val); i++) {
...
Also, in the do-while loop the index i is outside of the array bounds of val. You also need to check the return value of scanf to make sure the input is valid. The last printf statement also needs a trailing newline.
Edit: Note that LEN only handles "real" arrays; arrays passed to functions are received as pointers.
You allocated only int /* ... */ val[99] (only val[0] to val[98] are available) and accessed upto val[100] because the loop condition is i<101.
This will lead to dangerous out-of-range write (undefined behaior).
Allocate enough elements like int /* ... */ val[101] or fix the loop condition not to cause out-of-range access.
Also you didn't set value of i after the for (i=1;i<101;i++) loop, so value of uninitialized element will be used in the do ... while loop. Values of uninitialized elements of non-static local variables are indeterminate and using the value invokes undefned behavior.
Set i to proper value before the loop or change the indice i to proper thing.
I am trying to make a program that will arrange my structures by people ids.
I used long double because IDs are 20 digits long.
For example if I introduce 3 persons:
1.Alex Alex / id = 219(...)
2.John John / id = 200(...)
3.Robert Robert / id = 199(...)
I want my program to rearrange so Robert comes first, John second and Alex third.
I am having a problem on "for" structure - I don't exactly know how to swap two structures since I have chars and ints combined.
typedef struct
{
char name;
char prename;
long double id;
int j;
} PERSON;
int main()
{
int n,i,j;
printf ("How many people = ");
scanf("%d", &n);
PERSON v[n];
for(i=1;i<=n;i++)
{
printf("For person number nr. %d\n", i);
printf("name = ");
scanf("%s", &v[i].name);
printf("Prename = ");
scanf("%s", &v[i].prename);
printf("id = ");
scanf("%d", &v[i].id);
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n-1; j++)
{
if( v[i].id > v[j+1].id )
{
int temp = v[j].id;
char temp2[100];
char temp3[100];
strcpy(v[j].prename,temp3);
strcpy(v[j].name,temp2);
v[j].id = v[j+1].id;
v[j+1].id = temp;
}
}
}
return;
}
Ok, because there is so many things you've done here that are not obvious to a new C developer, I want to point them out to help you learn:
typedef struct
{
// These need to be arrays if they are to be strings
// Preferably using a constant for size or dynamic
// if you want them to be variable sized to match input.
char name;
char prename;
// Do not use floating point numbers to represent integer values.
// IRL, you'd use a library, but here, you may want to use an array of
// some sort of integer type instead.
long double id;
// This is a really poor name for a struct variable and probably shouldn't be here.
int j;
} PERSON;
int main()
{
int n,i,j;
printf ("How many people = ");
// Dropping raw output from scanf into a memory allocation is crazy dangerous.
// At least error check the results to be sure it is meaningful.
scanf("%d", &n);
// This is a variable length array and often is not supported directly.
// You probably want to use a malloc()/free() pair to handle this.
// (Update: VLA is now part of newer standards, but are not safe because they cannot fail gracefully on out of memory.)
PERSON v[n];
// Anytime in C I see an array start at 1 and use <= for condition, I get very nervous because
// it tends to lead to indexing errors.
for(i=1;i<=n;i++)
{
printf("For person number nr. %d\n", i);
printf("name = ");
// Oops - and this is why. You just skipped the first entry at 0
// and will overwrite memory on the last loop.
// Also, scanf into a string without a length can blow up memory...
scanf("%s", &v[i].name);
printf("Prename = ");
// Ditto
scanf("%s", &v[i].prename);
printf("id = ");
// Ditto - worse because you've crossed your types - %d doesn't go into a long double.
scanf("%d", &v[i].id);
}
// Should be its own function to make it easier to swap later to a better sort.
for(int i=0; i<n; i++)
{
// Bubble sort usually wants j=i here.
for(int j=0; j<n-1; j++)
{
if( v[i].id > v[j+1].id )
{
// Make a swap function here. Makes it clearer what you want to do.
int temp = v[j].id;
// What is 100? How do you know that is enough?
// These are called magic numbers and lead to code death.
char temp2[100];
char temp3[100];
// Ah, strcpy - 3 things wrong here.
// 1 - You have the parameters backwards - you are copying temp3 to your struct.
// 2 - You have no way to know if the destination will fit the source because it copies until it finds a '\0' - very dangerous.
// 3 - Because your parameters are backwards and temp123 is not initialized, this very well could copy forever.
// strncpy (also crazy dangerous) at the least should be used and consider using better means like strlcpy() and such.
strcpy(v[j].prename,temp3);
strcpy(v[j].name,temp2);
v[j].id = v[j+1].id;
v[j+1].id = temp;
// You kinda forgot to swap the strings, but the program is already dead so no worries.
}
}
}
// Please enable compiler warnings - you must return a value here.
return;
}
In seriousness, I'm sure I missed a few other things, but this is good enough for a free internet code review and learning session. :)
Info on strcpy() and strncpy()
Why is strncpy insecure?
Info on scanf() safety
How to prevent scanf causing a buffer overflow in C?
Info on Variable Length Array safety:
Is it safe to use variable-length arrays?
The main problem with your code is here:
typedef struct
char name; <--- just a char! no room for a string
char prename; <--- just a char! no room for a string
long double id;
int j;
} PERSON;
You need to make these arrays so that they can hold the names.
Like:
#define MAX_NAME_LEN 100
typedef struct {
char name[MAX_NAME_LEN];
char prename[MAX_NAME_LEN];
long double id;
int j;
} PERSON;
Besides that, you should always check the value returned by scanf and never do scanf("%s", &v[i].prename); as it may lead to buffer overflow. Instead do scanf("%99s", v[i].prename); but even better use fgets
And for sorting... just use qsort - see http://man7.org/linux/man-pages/man3/qsort.3.html
BTW: A long double can't be scan'ed using scanf("%d", &v[i].id); - %d is for integers. That said, I doubt you want to use long double. You probably want some interger type - maybe long long unsigned or uint64_t
Hey this is the entire code.
I m a beginner in C, I was trying to make a code which has a structure mall and takes into input the name, number of items shopped , the name of each item and the cost of each item.
* For small programs like this i fix the max size of the structure object
But the program cant take the input in the manner desired.
#include<stdio.h>
struct mall
{
char name[50];
char obj[10][30];
float price[10];
int numb;
}b[50];
void main()
{
int m; // number of persons who shopped at the mall
scanf("%d",&m);
for(int i=0;i<m;i++)
{
num=0;
scanf("%s",&b[i].name);
scanf("%d",&b[i].numb);
printf("%s\n%d",b[i].name,b[i].numb);
for(int j=0;j<num;j++)
{
scanf("%s",&b[i].obj);
scanf("%f",&b[i].price);
}
}
}
For the input :
1
Ram 2 bread 50.00 jam 25.00
I m getting the output as
2500
Your code has many small mistakes:
scanf("%s", &b[i].name); does not need &
num=0; is not necessary; remove it
Nested loop condition should use j < b[i].numb as its condition
Nested loop is not using j. It needs to add [j] to both obj and price.
Once you fix these problems, your code runs as expected as long as the input is correct (demo).
However, this is not enough to make your code robust: you need to add error checking to ensure that invalid input does not cause undefined behavior:
Add limits to string format specifiers in scanf to avoid buffer overflows (e.g. %49s to read name[50]),
Add a limit to the outer loop in case m is above 50,
Add a limit to the nested loop in case b[i].numb is above 10,
Add checks of return values for scanf.
num is undeclared. The program does not compile to executable. See below.
Don't pass &b[i].name to scanf(3), as the %s format requires a char * and the &b[i].name is not that type (it is, indeed, char *[50], while compatible, it is not the same type, while b[i].name is)
change num by b[i].numb in the inner for loop. This is the proper number of items. You have to check for array sizes also, as you have hardwired them in the code. If you don't you can overrun
Use inside the inner loop b[i].obj[j] for the object name as the reference to scanf(3)
Use inside the inner loop &b[i].price[j] for the j-esim price. You have forgotten it here and in the point above.
you have to add code to print the individual objects (the inner loop has no printf(3) at all.
A valid (but not completely correct, as array sizes are not checked) could be:
#include<stdio.h>
struct mall {
char name[50];
char obj[10][30];
float price[10];
int numb;
}b[50];
int main()
{
int m; // number of persons who shopped at the mall
scanf("%d",&m);
for(int i=0; i<m; i++) {
scanf("%s",b[i].name);
scanf("%d",&b[i].numb);
printf("* name = %s\n"
" numb = %d\n",b[i].name,b[i].numb);
for(int j=0; j < b[i].numb; j++) {
scanf("%s",b[i].obj[j]);
scanf("%f",&b[i].price[j]);
printf(" * obj = %s\n", b[i].obj[j]);
printf(" price = %.2f\n", b[i].price[j]);
}
}
return 0;
}
I want to add numbers to an array using scanf
What did i do wrong? it says expected an expression on the first bracket { in front of i inside the scanf...
void addScores(int a[],int *counter){
int i=0;
printf("please enter your score..");
scanf_s("%i", a[*c] = {i});
}//end add scores
I suggest:
void addScores(int *a, int count){
int i;
for(i = 0; i < count; i++) {
printf("please enter your score..");
scanf("%d", a+i);
}
}
Usage:
int main() {
int scores[6];
addScores(scores, 6);
}
a+i is not friendly to newcomer.
I suggest
scanf("%d", &a[i]);
Your code suggests that you expect that your array will be dynamically resized; but that's not what happens in C. You have to create an array of the right size upfront. Assuming that you allocated enough memory in your array for all the scores you might want to collect, the following would work:
#include <stdio.h>
int addScores(int *a, int *count) {
return scanf("%d", &a[(*count)++]);
}
int main(void) {
int scores[100];
int sCount = 0;
int sumScore = 0;
printf("enter scores followed by <return>. To finish, type Q\n");
while(addScores(scores, &sCount)>0 && sCount < 100);
printf("total number of scores entered: %d\n", --sCount);
while(sCount >= 0) sumScore += scores[sCount--];
printf("The total score is %d\n", sumScore);
}
A few things to note:
The function addScores doesn't keep track of the total count: that variable is kept in the main program
A simple mechanism for end-of-input: if a letter is entered, scanf will not find a number and return a value of 0
Simple prompts to tell the user what to do are always an essential part of any program - even a simple five-liner.
There are more compact ways of writing certain expressions in the above - but in my experience, clarity ALWAYS trumps cleverness - and the compiler will typically optimize out any apparent redundancy. Thus - don't be afraid of extra parentheses to make sure you will get what you intended.
If you do need to dynamically increase the size of your array, look at realloc. It can be used in conjunction with malloc to create arrays of variable size. But it won't work if your initial array is declared as in the above code snippet.
Testing for a return value (of addScores, and thus effectively of scanf) >0 rather than !=0 catches the case where someone types ctrl-D ("EOF") to terminate input. Thanks #chux for the suggestion!