The scanf is not reading the values - c

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;
}

Related

How to find the total number of a certain element in an array(C)

I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)

Error: Stack around the variable "m" is corrupted

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.

Structure Arranging in C

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

program returning garbage values

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.

How can i add numbers to an array using scan f

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!

Resources