Reputation: 11
I'm trying to make a program to just see what I can do with structures in C. But getting an error in the main function at scanf_s("%s", &user.name)
:
Exception thrown at 0x5C26D3EC (ucrtbased.dll) in StructureTest.exe:
0xC0000005: Access violation writing location 0x01341000. occurred
I also get some compiler warnings. This is my code:
#include <stdio.h>
struct birthdate {
int day;
char month[9];
int year;
};
typedef struct birthdate dob;
struct info {
char name[40];
dob birthdate;
int age;
char sex[6];
char *origin;
};
void printinfo(struct info user) {
printf("---- User Data ----\n");
printf("Name: %s\n", user.name);
printf("Date of birth: %d/%s/%d\n", user.birthdate.day,
user.birthdate.month, user.birthdate.year);
printf("Age: %d\n", user.age);
printf("Sex: %s\n", user.sex);
printf("Country of origin: %s", user.origin);
}
int main() {
printf("--Please enter your info--\n");
struct info user;
printf("Please enter your name: ");
scanf_s("%s", &user.name); // <-- exception thrown here
printf("Please enter your date of birth in the format (dd/mm/yyyy): ");
scanf_s("%d %s %d", &user.birthdate.day, &user.birthdate.month,
&user.birthdate.year);
printf("Please enter your age: ");
scanf_s("%d", &user.age);
printf("Please enter your gender ([M]ale/[F]emale): ");
scanf_s("%s", &user.sex);
printf("Please enter your country of origin: ");
scanf_s("%s", &user.origin); // <- Another exception thrown here
printf("\n\n");
printinfo(user);
printf("\nPress ENTER to continue..");
getchar();
return 0;
}
I'm not really experienced with structures yet, but I suspect it might have something to do with arrays and pointers, and the name I write in going into nowhere.
Upvotes: 1
Views: 1393
Reputation: 12668
You didn't show the input you feed to the program.
There are some minor mistakes and some major in your program:
First, you have been too tigth in the allocation of char
arrays. For example, month
field in birthdate
struct has only 9 spaces to store the month, and this means you cannot store a month like september
that requires 9 characters plus one more for the \0
nul character at the end of the string. This can be the problem with your execution if you aren't careful.
It's not common practice to pass struct
s directly by value to a function, as this makes the compiler to copy the complete struct contents into the parameter stack. It's more common to pass the struct by reference, as in
void printinfo(struct info *user);
and then calling it as
printinfo(&user);
which makes the compiler to pass only a pointer to the structure, saving time and memory.
I have not found the scanf_s
function in my manual online, where did you get it? Well, after some digging, I found them... from the VC manual for those functions (not standard, just a Microsoft extension):
Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable...
so you must use
scanf_s("%s", &user.name, sizeof user.name - 1);
and the same for the other strings you are reading.
Those _s
suffixed functions are only Microsoft extensions to their compiler. They are not portable (nor standard in anyway) and don't appear in the majority of C implementations. It's better not to use them, except if you are going to use only Microsoft C compilers (and you are not warranted for them to disappear in the future). There are other means to check for buffer size than to use nonstandard functions, e.g.
scanf("%.39s", user.name); /* there's no need to use the & operator here */
(in case you need to pass the size as a parameter, you can do the following):
SCANF("%.*s", sizeof user.name - 1, user.name);
will do the work, or
fgets(user.name, sizeof user.name, stdin);
(this call requires you to eliminate the last \n
from the string) both of these calls are standard, included in <stdio.h>
.
Upvotes: 3
Reputation: 12404
Besides the problems using scanf_s
mentioned in the other answer you also provide a wrong parameter:
scanf_s("%s", &user.origin);
With origin
being a pointer to char
, that's not the correct type. You need to provide a char *
but you provide a char **
.
Upvotes: 0