expected expression before 'struct' on c - c

I tried to make a userdata where it's declared as a struct. I tried to use scanf, but everytime i tried to compile it always says "expected expression before 'userdata'.
Anyone know how to fix this? Thank you
Here's my code:
#include <stdio.h>
typedef struct { char name[30]; char age[2]; char country[10]; char date[40];
} userdata;
int main()
{
printf("Please input your name: \n");
scanf("%c", &userdata.name);
printf("Please input your age: \n");
scanf("%c", &userdata.age);
printf("Which country are you from: \n");
scanf("%c", &userdata.country); printf("Please tell me the date of your birth in number format (00 - 00 - 0000)\n");
scanf("%c", &userdata.date);
printf("Here's your userdata: \n");
printf("Name : %c\n", userdata.name);
printf("Age : %c\n", userdata.age);
printf("Country : %c\n", userdata.country);
printf("Date of birth : %c\n", userdata.date);
return 0;
}

You created a type called userdata so now you need to declare an instance of the type to use it:
userdata u;
then you pass the address of the instance:
scanf("%c", &u.name);

By using the typedef keyword, you've declared userdata as a type alias for a struct. It's not a variable name.
If you remove the typedef keyword, you'll declare a variable with that name.
Also, you need to use the %s format specifier to read and write strings. The %c format specifier is used for single characters. Also, since strings are terminated by a null byte, the age member of your struct should be longer.

You are trying to assign a value to a TYPE, not a variable. When you define typedef, you do not create a variable, you create an alias for the type.
Let's say you have the int type, but you don't like it being called int. Then you can do typedef and name the type int as you want:
typedef int MyType; // Create an alias for an int type
You do NOT create a variable of this type.
Your solution is to create a variable of userdata and set it to:
userdata data;
scanf("%s", &data.name);
In addition, as #dbush rightly noted, you need to use the %s specifier to read strings: the %c specifier is used only for single characters.

Related

Why is the 3rd argument of this scanf not a pointer? [duplicate]

This question already has answers here:
When should I use ampersand with scanf()
(3 answers)
Closed 4 months ago.
I am trying to understand why this 3rd argument in the scanf() function needs an ampersand but not the 2nd one, without the ampersand I get an error saying "Argument 3 of scanf() is not a pointer".
struct person {
int age;
float weight;
char name[30];
};
for(i = 0; i < n; ++i)
{
printf("Enter name of person %d and age respectively: ", i);
// To access members of 1st struct person,
// ptr->name and ptr->age is used
// To access members of 2nd struct person,
// (ptr+1)->name and (ptr+1)->age is used
scanf("%s %d", (ptr+i)->name, &(ptr+i)->age);
}
I just want to understand why that's happening and I can't really get the grasp of the arrow pointer operator as well.
When you remove the pointer dereferencing, you get something akin to this:
int age;
char name[30];
scanf("%s %d", name, age);
Where clearly the age argument is just an int, and that can't be mutated.1 scanf needs to be able to alter that, so the C convention for a mutable argument is to pass it in as a pointer, or &age in this case.
When extended to your original example you get &(ptr[i]->age), something that can be expressed as a more relaxed &ptr[i]->age since both [] and -> have higher precedence than &.
--
1 Modifications to argument values are local. Modifications made via a pointer impact the original value.

C Insert int and doubles inside structure

I have a problem with a small project, I have to create a structure containing a person's data,I have to do data entry via a function using pointers.
I don't understand why when I try to enter the weight the program ends with this error:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
I made an example of the code that is giving me problems:
typedef struct{
char name[DIM];
char surname[DIM];
int height;
float weight;
}Record;
int main() {
Record subj;
insRecord(&subj);
}
void insRecord(Record *subj){
printf("\nName ");
scanf("%64[^\n]s", subj->name);
cleanBuffer();
printf("\nSurname ");
scanf("%64[^\n]s", subj->surname);
cleanBuffer();
printf("\nEight ");
scanf("%3s", subj->height);
cleanBuffer();
printf("\nWeight ");
scanf("%6s", subj->weight);
cleanBuffer();
}
int cleanBuffer(){
int cont= 0;
char c;
do{
cont++;
c = getchar();
}while(c != '\n');
return cont;
}
(I only wrote the main functions).
Furthermore, compiler is giving warnings on height and weight scanf() statements:
Format specifies type 'char *' but the argument has type 'int' (for height)
Format specifies type 'char *' but the argument has type 'double' (for weight)
Could you tell me how can I solve?
PS the project is divided into several files (3 files).
In main.c I wrote the insRecord() function, in struct.h I wrote the Record structure, in struct.c I wrote cleanBuffer() function.
You are reading a string (%s) and try to store that in a float. If you use the flag %f for weight and %d for height it will probably work better. Remember that you should provide a pointer to the float and int that you want to store the data in, you are not doing that in your example.
Have a look at the scanf documentation:
https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm
Good luck

C99 | (BItfield) Struct in a Struct don't work to be choosen with name1.name2.variable

How to fix this error? I want to have an Array where i can scan the data of "students" and used therefore structs. The Problem is, that the bitfield struct in the other struct fails.
Is there any way to fix this, without changing the most structure of the code? Only want to fix, that the bitfields(day, month, etc) can be choosen.
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MAX 10
#define MAXCHAR 30
char comma;
struct date {
unsigned int day:5;
unsigned int month:4;
unsigned int year:11; //funktioniert bis yr 2047;
};
struct student {
unsigned long matriculation_number;
char first_name[MAXCHAR];
char last_name[MAXCHAR];
struct date birthdate;
}Student[MAX];
/*
void scan_student(void) {
b
} */
int main(void) {
int i = 0;
printf("------------------------------\nGeben Sie alle benötigten Daten ein\n");
printf("Vorname: ");
fgets(Student[i].first_name, MAXCHAR, stdin);
printf("Nachname: ");
fgets(Student[i].last_name, MAXCHAR, stdin);
printf("Matrikelnummer: ");
scanf(" %lu", &Student[i].matriculation_number);
printf("Geburtstdatum (DD.MM.YYYY): ");
scanf(" %u%c%u%c%u", &Student.birthdate.day, &comma, &Student.birthdate.month, &comma, &Student.birthdate.year);
printf("\n");
return EXIT_SUCCESS;
}
ERROR-Log:
student.c: In function ‘main’:
student.c:42:26: error: cannot take address of bit-field ‘day’
scanf(" %u%c%u%c%u", &Student[i].birthdate.day, &comma, &Student[i].birthdate.month, &comma, &Student[i].birthdate.year);
^
student.c:42:61: error: cannot take address of bit-field ‘month’
scanf(" %u%c%u%c%u", &Student[i].birthdate.day, &comma, &Student[i].birthdate.month, &comma, &Student[i].birthdate.year);
^
student.c:42:98: error: cannot take address of bit-field ‘year’
&Student[i].birthdate.day, &comma, &Student[i].birthdate.month, &comma, &Student[i].birthdate.year);
While you cannot pass bitfield members to scanf, you can pass temporaries to scanf then assign them to the bitfield without issue:
unsigned char day = 0, month = 0;
unsigned short year = 0;
scanf(" %hhu%c%hhu%c%hu", &day, &comma, &month, &comma, &year);
Student.birthdate.day = day;
Student.birthdate.month = month;
Student.birthdate.year = year;
Note that this does involve narrowing, so you may have a successful scanf that then can't store its full value in the bitfield.
Given the further comments noting that you're not allowed to use the tmp step, which is entirely unreasonable of whoever set this task, you can't use scanf at all. You can however read the string separately, then use strtoul or similar to convert the numeric tokens into returned values that can be directly assigned into the bitfields. I really don't recommend this, but if it's a requirement of an assignment or similar it is possible.
As requested: The C11 specification section 7.21.6.1 paragraph 7 describes the length modifiers, hh and h, used in this example. These allow the length of an integral type to be read to be specified, where hh is the length of a char, and h is the length of a short. Combining these with d i o u x or X allows specifying all the built-in integral types to be read by (f)scanf.
struct date is defined using bitfields, and therefore it is not aligned on a byte boundary. Because it is not on a byte boundary you cannot take the address of it with the & operator. Trying redefining struct date as follows.
struct date {
unsigned char day;
unsigned char month;
unsigned short year;
}
This has the added benefit of allowing you to store years unto 65535 instead of 2047.

How can I Get character from user in console and then show it? [duplicate]

I am trying to write this simple program which reads multiple variables in one scanf function but an exception is thrown after I enter the input?
Edit: I used scanf initially but it causes an error saying it may be unsafe.
Exception thrown:
Exception thrown at 0x52DAB87C (ucrtbased.dll) in Program.exe: 0xC0000005: Access violation writing location 0x00D00000
#include <stdio.h>
#include <stdlib.h>
void main()
{
char name[20];
int age;
char gender;
float income;
printf("Enter <name> <age> <gender> <income> :");
scanf_s("%s %d %c %f", &name, &age, &gender, &income);
printf("Name : %s", name);
printf("Age : %d", age);
printf("Gender : %c", gender);
printf("Income : %.2f", income);
system("pause");
}
The %s format specifier to scanf/scanf_s expects a pointer to the first element of an array of char, i.e. a char *. Instead, you're passing in the address of an array, in this case a char (*)[20]. Those types are incompatible. Passing the the wrong type for a format specifier invokes undefined behavior.
Instead of passing in &name, pass in name. When passed to a function, an array decays to a pointer to the first element, so this is the proper type.
scanf_s("%19s %d %c %f", name, sizeof(name), &age, &gender, sizeof(gender), &income);
Also note the length specifier given, which limits the number of characters that can be read in so it doesn't try to write past the end of the array.

Returning structure from function

Below is the code through which I am returning structure from function. May be the question is very basic but I am not clear why I am writing emp in this line struct emp putinfo (){. I am not clear why I need to write the structure name? Because inside the function I am defining the structure as struct emp t;. What is the specific reason?
#include <stdio.h>
struct emp {
int number;
char name [200];
};
void print (struct emp team){
printf ("Details of employee %d %s", team.number, team.name );
}
struct emp putinfo (){
struct emp t;
printf ("Enter number"); scanf ("%d", &t.number);
printf ("Enter name"); scanf ("%s", &t.name);
return t;
}
int main (){
struct emp test;
test = putinfo ();
print (test);
return 0;
}
struct emp is actually the name with which you address the structure in C. You can typedef it and then you can write only emp.The reason why it stands before putinfo is because this is the returned type by the function.struct emp t just makes a new structure of type emp and assigns it to t.
In C the name of the type you create when you define a structure is struct structure_name C++ allows to use this format or just structure_name
Example:
struct some_struct{};
struct some_struct x; // Variable declaration C, C++ syntax.
some_struct y; // Only C++ syntax.
If you are working with C you must specify the return value of your function using C syntax:
struct some_struct my_function(){}
on the other hand in C++ you can
struct some_struct my_function(){}
or
some_struct my_function(){}
Define your struct and use the type definition instead:
#include <stdio.h>
typedef struct {
int number;
char name [200];
}emp;
void print (emp team){
printf ("Details of employee %d %s", team.number, team.name );
}
emp putinfo (){
emp t;
printf ("Enter number"); scanf ("%d", &t.number);
printf ("Enter name"); scanf ("%d", &t.name);
return t;
}
int main (){
printf("hello\n");
emp test;
test = putinfo ();
print (test);
return 0;
}
You're right in that this is redundant (at a first glance, but see below), but this is how C works, there is no type inference. This is the same for every type (and unrelated to structures):
succ.c
unsigned succ(unsigned n) {
unsigned succ = n + 1;
return succ;
}
Here, you could also say, there's no real reason you have to specify the return type.
So, now the part why this is needed:
1) It's needed at least in a prototype because the compiler may not be able to see the definition, consider
main.c
#include <stdio.h>
unsigned succ(unsigned);
int main(void) {
printf("%u\n", succ(1));
}
where the object file containing the implementation of succ may be already compiled (you could compile via gcc main.c succ.o or the like).
2) Consider
long int_to_long(int n) { return n; }
where an int is converted to a long (and the compiler couldn't have known without a return type). OK, this doesn't hold for structures (they are never implicitly converted), but it's consistent.
And usually, you don't pass structures by value at all, but pass pointers to it, especially if they are large.
Finally, a few notes about your code:
Never, ever, use %s without a length for scanf. It's always wrong (how should scanf know how big the array you provided is?), do e.g.
printf ("Enter name\n"); scanf ("%199s", t.name);
or use fgets instead; in productive code, you almost never want to use scanf, because the error handling is complicated. Also note the newline I added, the message asking for input may not appear until after you've written a newline to stdout (stdout is usually line buffered, and so is usually a terminal, a (better) alternative would be fprintf(stderr, "Enter name: ");, as stderr is unbuffered and this output shouldn't really go to stdout anyway.).
Generally, I would advise you to not write interactive programs until you're familiar with pointers and arrays, dynamic memory allocation, error handling, and file buffering, but pass information from the user via command-line arguments. You currently know too little to write interactive programs properly.
HTH

Resources