Below is the code I am using to read and print struct array values - I am getting the error when reading string:
#include <stdio.h>
#include <stdlib.h>
struct addressbook{
char *fname;
char *lname;
char *num;
char *email;
};
int main() {
struct addressbook addr[100];
int add=0,m=0;
while (m<3)
{
printf("1. Show All Entries\n");
printf("2. Add Entry\n");
printf("3. Quit\n");
scanf("%d",&m);
if (m==1)
{
int i;
for (i=0; i<add;i++)
{
printf("FName: %s , LName: %s , Number: %s , Email: %s \n",&addr[i].fname, &addr[i].lname,&addr[i].num,&addr[i].email);
}
}
else if (m==2)
{
if (add<101)
{
struct addressbook a;
printf("Enter First Name: ");
scanf(" %s", &a.fname);
printf("Enter last Name: ");
scanf(" %s", &a.lname);
printf("Enter Contact Number: ");
scanf(" %s", &a.num);
printf("Enter Email: ");
scanf(" %s", &a.email);
addr[add] = a;
add=add+1;
}
else{printf("100 limit reached");}
}
else if (m=3)
{
m=3;
}
else
{
m=0;
printf("Invalid option");
}
}
}
This is a basic program - but it is getting closed with unknow error.
if the length of string enters is some just 3 chars then there is no error. Could you please correct me where I have gone wrong.
Tried the below code too yet not working
printf("Enter First Name: ");
scanf(" %s", &addr[add].fname);
printf("Enter last Name: ");
scanf(" %s", &addr[add].lname);
printf("Enter Contact Number: ");
scanf(" %s", &addr[add].num);
printf("Enter Email: ");
scanf(" %s", &addr[add].email);
add=add+1;
Let's assume this is a 32-bit system, so pointers are 4 bytes each. Your addressbook
struct looks like this in memory:
0 1 2 3 4 5 6 7 8 9 A B C D E F
---------------------------------
[fname ][lname ][num ][email ]
When you declare the local variable struct addressbook a;
, this is exactly what you get on the stack -- 16 bytes of uninitialised memory:
0 1 2 3 4 5 6 7 8 9 A B C D E F
---------------------------------
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
And now you start reading into an actual pointer value with scanf
. Here's what your struct looks like after the first input:
0 1 2 3 4 5 6 7 8 9 A B C D E F
----------------------------------
a s d a s d a \0 ? ? ? ? ? ? ? ?
And after the last input:
0 1 2 3 4 5 6 7 8 9 A B C D E F * * * * * *
---------------------------------------------
a s d a c a s c 1 2 3 1 a s d a s d a s d \0
Whoops! So you wrote 6 extra bytes of memory off the end of your structure, which eats into whatever else is on your stack. Now that might just happen to have been the add
and m
variables, which are now some huge value. Then you write to addr[add]
and BOOM -- you just wrote to memory somewhere way outside your stack.
That's one scenario. Anything could happen, really. The point is this is undefined behaviour and you should avoid that at all costs!
What to do? Well, there are large topics about this everywhere, and why scanf
is BAD for reading strings in the first place. But in a pinch, let's assume your users behave themselves. If you just change those pointers to arrays, life will improve:
/* Arbitrary string length limits */
#define MAX_FNAME 20
#define MAX_LNAME 20
#define MAX_NUM 20
#define MAX_EMAIL 50
struct addressbook{
char fname[MAX_FNAME];
char lname[MAX_LNAME];
char num[MAX_NUM];
char email[MAX_EMAIL];
};
And now you make sure you're using the correct pointer when you call scanf
. If you use a.fname
, the compiler will decay the array into a pointer so you should not pass &a.fname
. You either write a.fname
or &a.fname[0]
:
scanf(" %s", a.fname);
This isn't the only solution, of course. And it's already unsafe. But I don't want to overwhelm you with too much information at this point. Hopefully this has a been helpful start. Be careful, okay?! =)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.