Logical issue with printf and scanf - c

I am revising my basic C to prepare for the upcoming quiz, when i was writing a function to simply take a character input and store it into a struct and print it out again. There is no issue with the compiling whatsoever but i kept getting logical issue. How do i fix this?
#include <stdio.h>
struct player
{
char letter;
int age;
double avg;
};
int main()
{
struct player P1;
char name;
int age;
double avg;
printf("Enter age: ");
scanf("%d", &age);
printf("Enter avg: ");
scanf("%lf", &avg);
printf("Enter name: ");
scanf("%s", &name);
P1.letter= name;
P1.avg = avg;
P1.age = age;
printf("\n Age is: %d \n", P1.age);
printf("Avg is: %lf", P1.avg);
printf(" \n Name is: %c \n", P1.letter);
return 0;
}
If i put in '1' for int, output would be "Age is: 0'

you are trying to get name, age and avg. of the player. so to store name , you should declare an array not a character. and for assigning the name to structure variable use strcpy().(direct assignment not works). OR if you taking only a single character as a name then write scanf like this:
scanf("%c", &name);
check below code, it will help you,
#include <stdio.h>
struct player
{
char letter[10];
int age;
double avg;
};
int main()
{
struct player P1;
char name[10];
int age;
double avg;
printf("Enter age: ");
scanf("%d", &age);
printf("Enter avg: ");
scanf("%lf", &avg);
printf("Enter name: ");
scanf("%s", &name);
strcpy(P1.letter,name);
P1.avg = avg;
P1.age = age;
printf("\n Age is: %d \n", P1.age);
printf("Avg is: %lf", P1.avg);
printf(" \n Name is: %s \n", P1.letter);
return 0;
}

You are using a character data type for entering a string, "char name" which is leading you to undefined behavior.
Instead of that you declare a character array like this "char name[10]" and then read name. but while assigning you have to take care that you can not assign directly you have to use strcpy like this.
strcpy(p1.letter,name) (Here letter is also character array)

Two quick suggestions:
1) Unless you are certain the name buffer will be populated only by short names, (9 or less characters), pick a more reasonable size for the buffer, such as:
char name[100];
This will also require lengthening the member letter in your struct.
2) when using scanf() to read in variables, the address of the variable being read is passed as the 2nd argument. For variables such as int a; or float b; you must use the address of operator: & as a prefix to the variable. But because the variable name of a C string points to the first character in the array, it already is the address of that variable. So you do not need the explicit & operator when reading a C string into the scanf() function. The return value of the function should also be used to determine if the call was successful. Change the following line as shown:
scanf("%s", &name);
int count = scanf("%s", name);//note: use return value of function
// remove & ^
if(count < 0)
{
//handle error
}

Related

Don't know how to print a char array in my C code

I wrote the following code. But the when I add %s to print the name , the whole code stops after 1 iteration and either the name[i] or t[i] won't print. Code works fine if I don't add %s to print the name. Can you please tell me what's wrong with my code. Thank you. :)
#include<stdio.h>
#include <string.h>
int main()
{
int i,t1[3],t2[3],t3[3],t[3],avg=0;
char name[3];
for(i=0;i<3;i++)
{
printf("Enter the name:");
scanf("%s",&name[i]);
printf("Enter marks for test 1:");
scanf("%d",&t1[i]);
printf("Enter marks for test 2:");
scanf("%d",&t2[i]);
printf("Enter marks for test 3:");
scanf("%d",&t3[i]);
if(t1[i]<0 || t2[i]<0 || t3[i]<0 ||t1[i]>100 || t2[i]>100 || t3[i]>100 )
{
printf("Invalid score\n");
}
t[i]=t1[i]+t2[i]+t3[i];
avg=avg+t[i];
printf("%s : Total Score of = %d ",name[i],t[i]);
}
}
name needs to be an array of strings, not an array of char.
char name[3][30];
Then you would use
scanf("%s", name[i]); // no need for & when passing an array
Here you are trying to print a char using %s
printf("%s : Total Score of = %d ",name[i],t[i]);
If you want to print a string you have to inizialize name as a string (an array of arrays):
char name[3][20];

What is causing the error “expected ‘;’, ‘,’ or ‘)’ before ‘.’ token”?

I'm currently working to make an indexer for the students score, but, since I am new in C, I dont get the grasp of reading errors. Here's the error I have:
c:11:27: error: expected ‘;’, ‘,’ or ‘)’ before ‘.’ token
11 | double average(float input.score, int input.many){
c:34:13: warning: comparison between pointer and integer
34 | for(i=0; i < nas->many; i++){
c:48:3: warning: implicit declaration of function ‘average’ [-Wimplicit-function-declaration]
48 | average(sum, nas->many);
The while loop won't work properly
This is the code I work on:
#include <stdio.h>
#include <string.h>
#define MAX 100
typedef struct{
float score, avg, sum, *many;
char name[100][100];
} input;
double average(float input.score, int input.many){
float sum=0, average, a;
int i;
for(i=0; i<input.many;i++){
sum += input[i].score;
}
a = sum/input.many;
average=a;
return average;
}
int main(){
input nas[MAX];
float sum;
int choose, i, aa;
printf("How many students do you want to input?\n");
scanf(" %d",&nas->many);
for(i=0; i < nas->many; i++){
input nas[i];
printf("\nName of Student-%d\t\t: ",i+1);
scanf(" %[^\n]s", nas[i].name);
printf("The score of Student-%d\t\t: ",i+1);
scanf(" %f", &nas[i].score);
while(nas[i].score > 100 && nas[i].score < 0){
printf("Invalid! Please re-input the score\t\t: ");
scanf(" %f",&nas[i].score);
}
average(sum, nas->many);
}
printf("1--> Average of the scores");
scanf("%d", &choose);
if(choose == 1){
printf("The average of %d students is %f", nas->many, average());
}
...
else{ return 0;}
Can anybody help me to understand it? Thank you very much
Because you mustn’t use . inside a C identifier. It’s not valid. You could for instance replace it with _.
The only valid characters in a C identifier are letters, digits and underscore (ignoring Unicode).
So, you have some variables on struct thats do not make any sens, and you have some errors by send the parameters to the function and calling the function! You want the average of N students so you only can call the function after the insertion of score!
Other thing is why you need to save on every student, the sum of scores of all students, as the average of all students! And you are declaring the function always on for so when you insert for 1 student when loops back you lost your data because you declares it again!
#include <stdio.h>
#include <string.h>
#define MAX 100
typedef struct{
float score;
char name[100];
} input;
float average(input nas[], int many){
float sum=0, a;
int i;
for(i=0; i< many;i++){
sum += nas[i].score;
}
a = sum / many;
return a;
}
int main(){
input nas[MAX];
float sum;
int choose, i, many;
printf("How many students do you want to input: ");
scanf(" %d", &many);
for(i=0; i < many; i++){
printf("\nName of Student (%d): ",i+1);
scanf("%[^\n]s", nas[i].name);
printf("The score of Student (%d): ",i+1);
scanf("%f", &nas[i].score);
while(nas[i].score > 100 && nas[i].score < 0){
printf("Invalid! Please re-input the score: ");
scanf("%f", &nas[i].score);
}
}
sum = average(nas, many);
printf("\n1--> Average of the scores: ");
scanf("%d", &choose);
if(choose == 1){
for(int j=0; j < many; j++){
printf("\nName of Student: %s | Score: %f", nas[j].name, nas[j].score);
}
printf("\n\nThe average of %d students is %f\n", many, sum);
}
else{
return 0;
}
}
regarding:
scanf("%[^\n]s", nas[i].name);
are you expecting the user entered field name to be followed by a '\n' then a s?
Probably not.
Also, this statement does not remove the '\n' from stdin.
Therefore, IF anything, that s should be replaced with a space (so any trailing 'white space' is consumed. However, that is 'always' a bad idea.)
Strongly suggest using:
scanf("%[^\n]", nas[i].name); // note: no trailing `s`
note the next call to scanf() with a %f specifier will consume any leading 'white space'.
regarding:
scanf(" %d",&nas->many);
This may result in the first element in the array nas[] field many being set, but a much better method is:
scanf(" %d",&nas[0]->many);
regarding: right after the for() statement:
input nas[i];
This is declaring/re-declaring a new array with however many elements the i variable indicates. Probably not what you want to do.
regarding:
char name[100][100];
This is declaring a 2 dimensional array of 100 entries, with each entry being 100 characters. However, when ever the posted code references this 2d array, all that is given is name. The result will be all names will overlay each other in the first [0] entry
regarding:
scanf("%[^\n]s", nas[i].name);
besides the previously mentioned problem with the format string, and with using name without any indexing, the specifier: %[\n] does not limit the length of a name. Suggest:
scanf("%99[^\n]", nas[i].name[i]);
There are LOTS of other problems in the posted code besides those mentioned above.

Referenced memory could not be written

Whenever I run this struct, I can get down to the line where you would input the constitution modifier and the program crashes with a popup window which reads "The instruction at 0x00000000775AFDE9 referenced memory at 0x000000007758D250. The memory could not be written. Press OK to terminate." Here's the struct in question:
struct player_info create_player(void);
struct player_info{
char name[30];
int Level, Str, Dex, Con, Int, Wis, Cha;
};
struct player_info create_player(void){
struct player_info aPlayer;
{
char c;
int i;
printf("Enter Player Name: ");
scanf("%s",aPlayer.name);
i = strlen(aPlayer.name);
do{
scanf("%c", &c);
aPlayer.name[i++] = c;
}
while (c != '\n');
aPlayer.name[i - 1] = 0;
}
printf("Level: ");
scanf("%d",aPlayer.Level);
printf("Strength Modifier: ");
scanf("%d",aPlayer.Str);
printf("Dexterity Modifier: ");
scanf("%d", aPlayer.Dex);
printf("Constitution Modifier: ");
scanf("%d", aPlayer.Con);
printf("Intelligence Modifier: ");
scanf("%d", aPlayer.Int);
printf("Wisdom Modifier: ");
scanf("%d", aPlayer.Wis);
printf("Charisma Modifier: ");
scanf("%d", aPlayer.Cha);
return aPlayer;
};
And the write bit:
int save_data(){
FILE* PlayerFile = fopen("players.txt","w");
int i = 0;
for (i = 0; i < 1; i++){
struct player_info aPlayer = create_player();
fprintf(PlayerFile, "%s %d %d %d %d %d %d %d\n", aPlayer.name, aPlayer.Level, aPlayer.Str, aPlayer.Dex, aPlayer.Con, aPlayer.Int, aPlayer.Wis, aPlayer.Cha);
}
fclose(PlayerFile);
return 0;
}
Now, to be clear, I can input up to the dexterity modifier. The next line that should ask for the constitution doesn't print, and that's when I get the popup error.
I have tried commenting out everything from the constitution mod down to the charisma just to see, and I get the same problem. Removing just the constitution part doesn't work either. I'm not really sure what's going on here; I've seen other posts saying something about a pointer being wrong, but I don't see anything like that, unless it's just one of those things that you just miss and need someone else to point it out. Anyway, any help is appreciated.
scanf expects the address of the variable you intend to write to. So this
scanf("%d",aPlayer.Level);
Should be this
scanf("%d", &aPlayer.Level);
For all of your stats. The way you have it setup now involves passing an unspecified integral value to scanf (the variable aPlayer.Level and company are uninitialized), which is then reinterpreted as an address that the function attempts to write into. The behavior of of such code is undefined.

C Structure Declaration Issue

I am writing the following program for my Programming Fundamentals Class (C Programming). My IDE is giving me a compile error for the declaration of 'student' as referenced in the lines where user input is read. It is also giving me an error on ISO C standards for nested functions in the letter_grade function. Any help would greatly be appreciated.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX 20
char letter_grade(float a, float b, float c);
int main(void)
{
char temp_name[MAX];
int count=0, last, temp;
struct student {
char f_name[MAX];
char l_name[MAX];
float test1;
float test2;
float test3;
};
printf("Please enter the student's last name (Enter ZZZ to exit): ");
gets(temp_name);
while (strncmp(temp_name, "ZZZ\0", 4))
{
strncpy(student[count].l_name, temp_name, MAX+1);
printf("Please enter the students first name: ");
scanf("%s", &student[count].f_name);
getchar();
printf("Enter the first test score: ");
scanf("%f", &student[count].test1);
printf("Enter the second test score: ");
scanf("%f", &student[count].test2);
printf("Enter the third test score: ");
scanf("%f", &student[count].test3);
printf("\nPlease enter the student's last name (Enter ZZZ to exit): ");
gets(temp_name);
count++;
}
last = count;
temp = last + 1;
printf("\t\t\tStudent Grade Report");
for (last;last>=0;last--){
printf("%s, ", student[last].l_name);
printf("%s ", student[last].f_name);
printf("\t\t Grade: %c\n\n ", letter_grade(student[last].test1, student[last].test2, student[last].test2));
// printf("Test Grade: %c\n", letter_grade(85,88,82));
return 0;
}
char letter_grade(float *a, float *b, float *c)
{
float sum = *a+*b+*c;
if (sum >= 270.0f)
return 'A';
if (sum>= 240.0f && sum <270.0f)
return 'B';
if (sum>= 210.0f && sum <240.0f)
return 'C';
if (sum>= 180.0f && sum <210.0f)
return 'D';
if (sum < 180.0f)
return 'F';
}
You nowhere declared an array or a pointer with name student. The name was not declared. Thus the code where you are refering the name like this statement
strncpy(student[count].l_name, temp_name, MAX+1);
^^^^^^^
is invalid.
What is "student"? Where is it declared?
You only declared type struct student but it is not the same as an object with name student.
Also in this loop
for (last;last>=0;last--){
printf("%s, ", student[last].l_name);
printf("%s ", student[last].f_name);
printf("\t\t Grade: %c\n\n ", letter_grade(student[last].test1, student[last].test2, student[last].test2));
there is absent the closing brace.
Applying all the comments and correcting other problems in the posted code there were many results in:
#include <stdio.h>
#include <string.h>
#define MAX_NAME_LEN (20)
#define MAX_STUDENTS (100)
// define the student struc
struct student
{
char f_name[ MAX_NAME_LEN ];
char l_name[ MAX_NAME_LEN ];
float test1;
float test2;
float test3;
};
char letter_grade(float a, float b, float c);
int main(void)
{
// define an array of 100 instances of the student struct
struct student students[ MAX_STUDENTS ];
printf("Please enter the student's last name (Enter ZZZ to exit): ");
int count=0;
while( count < MAX_STUDENTS && scanf( " %19s", students[count].l_name) && strcmp( students[count].l_name, "ZZZ" ) )
{
printf("Please enter the students first name: ");
scanf(" %19s", students[count].f_name);
printf("Enter the first test score: ");
scanf("%f", &students[count].test1);
printf("Enter the second test score: ");
scanf("%f", &students[count].test2);
printf("Enter the third test score: ");
scanf("%f", &students[count].test3);
count++;
printf("\nPlease enter the student's last name (Enter ZZZ to exit): ");
} // end while
printf("\t\t\tStudent Grade Report");
for ( ; count>=0; count--)
{
printf("%s, ", students[count].l_name);
printf("%s ", students[count].f_name);
printf("\t\t Grade: %c\n\n ",
letter_grade( students[count].test1,
students[count].test2,
students[count].test2));
} // end for
} // end function: main
char letter_grade(float a, float b, float c)
{
float sum = a+b+c;
char grade;
if( sum >= 270.f) grade = 'A';
else if (sum>= 240.0f) grade = 'B';
else if (sum>= 210.0f) grade = 'C';
else if (sum>= 180.0f) grade = 'D';
else grade = 'F';
return grade;
} // end function: letter_grade
You can compare the posted code to the above answer to spot where there were problems in the posted code.
Do not #include header files those contents are not used.
A passed value to a function does not become a pointer in the parameter list of the called function.
In any if then else sequence, there is no need to re-test for previously eliminated values
The posted code nested one function inside another, That is not valid C code, although can be allowed with the gcc compiler extension.
There is no need for a return statement from main() if the returned value is 0.
On any non void function, ALL paths through the code must lead to a return value; statement.
The posted code failed to declare any instance of the struct student structure. And certainly did not declare an array of those struct instances, as is needed when multiple students being processed.
The posted code (and this answer) will fail if any first or last name is greater than or equal to 20 characters.
This answer does not check for failures of the call to scanf() but for reliability, such checking for each must be performed. Similar to:
if( 1 != scanf( " %19s", students[count].l_name) )
{
perror( "scanf failed" );
exit( EXIT_FAILURE ); // `exit()` and `EXIT_FAILURE` found in stdlib.h
}
// implied else, scanf successful
The while() statement in the main() function is very 'busy' for clarity, the call to strcmp() could be extracted and placed in a following statement similar to:
while(...)
{
if( !strcmp( students[count].l_name, "ZZZ" ) {
{
break;
}
...
In general, never trust the input from a user. That is why the returned value (not the parameter value) from each call to scanf() needs to be checked.
As a simplification, rather than hardcoding the MAX LENGTH modifier in the calls to scanf() with a %s format specifier, can use the following changes:
#define MAX_NAME_LEN (19)
...
struct student
{
char f_name[ MAX_NAME_LEN+1 ];
char l_name[ MAX_NAME_LEN+1 ];
float test1;
float test2;
float test3;
};
....
&& scanf(" %" MAX_NAME_LEN "s", students[count].l_name) &&
....
scanf(" %" NAX_NAME_LEN "s", students[count].f_name);

Average generates a negative decimal number

I created a function called average that will calculate the average age. How ever it is generating a strange negative decimal point.It was working fine until I put the strcmp function to people who have enter Texas. Example ages: 20 50 20 30 & 40 generate The average age is -243454739.00.
Can someone point me in the right direction, Thanks.
#include <stdio.h>
#include <string.h>
int main()
{
//function decleration
float average ( int A, int n);
//int deleceration
char names, states, statedata[100], namedata[100];
int agedata[100], age, count = 0, A, n, avg;
float a;
//Get User Input
printf("Enter Number of family members being enter into program \n");
scanf("%d", &n);
//Name Loop
for (names=0; names<n; ++names)
{
printf("Enter Family members name:\n");
scanf("%s", &namedata);
//Age Loop
for (age=0; age<1; ++age)
{
printf("Enter family members age:\n");
scanf("%d", &agedata[age]);
A +=agedata[age];
count= count + 1;
//State Loop
for (states=0; states<1; ++states)
{
printf("Enter Family members state:\n");
scanf("%s", &statedata);
//strcmp function for state name "Texas" Selection
if (strcmp(statedata,"texas")==0)
{
printf("Family members who live in texas\n");
printf("%s\n", namedata);
}
}
}
}
// Average function call
a = average(A, n);
printf("The average age is %.2f\n", a);
return 0;
}
//A declarator
float average( int A, int n){
float average;
average = A / n;
return average;
}
Initialize A to 0 in main(). Uninitialized local variables have indeterminate values in C.
Other issues:
1)
scanf("%s", &namedata);
scanf("%s", &statedata);
Shoud be
scanf("%s", namedata);
scanf("%s", statedata);
Because scanf() expects a char* when for format specifier %s whereas you are passing char(*)[100].
2)
All the values of ages are using type int. So the having the function average() return a float is still going to give an int result.
Change the type A (in main()) and the function parameter A (in average()) to float.
3)
Your inners are running 0..1 i.e. only once. So you don't really need those loops.

Resources