As noted in the comments and in the other answers, you have a number of problems. The first two that immediately invoke Undefined Behavior are:
- Attempting to read the state
"NY"
as a string into char state[2];
. To be a valid string in C, the characters must be terminated by a nul-terminating character. Meaning to store a 2-character state abbreviation, you need 3-characters of storage (minimum). E.g. {'N', 'Y', '\0'}
. (Master @JonathanLeffler deduced how the immediate consequence of the short storage for state
could cause the '\0'
character to be stored as the first character in city
causing city
to be an empty-string);
- When reading strings with
scanf
you must provide a pointer to sufficient storage for the string you are reading. Since address, city, state, zip
are character arrays, on access, they are converted to a pointer to the first character (see: C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)) So each is already a pointer when used as a argument for scanf
and no '&'
(address of) operator need precede them in the argument list.
Additional notes, avoid using magic-numbers in your code unless absolutely necessary. 100, 2, 15
are magic-numbers below.
char address[100];
char city[100];
char state[2];
char zip[15];
If you need a constant for the number of characters in address, city, state, zip
, #define
one for each or use a global enum
to do the same thing, e.g.
enum { STSZ = 3, ZIPSZ = 15, CIADDR = 100 }; /* constants */
(note city
and address
are both 100
, so a single CIADDR
constant will do)
When are number absolutely required in your code? When providing a field-width modifier to protect your array bounds when reading with the scanf
family of functions. Additionally, when using the scanf
family, you must check the return, every time. Otherwise a matching or input failure can occur (or the user could generate a manual EOF
to cancel input) and you blindly push forward using the variable that wasn't filled and likely left indeterminate invoking Undefined Behavior.
Putting those pieces together, and thinking forward that you just may find yourself dealing with more than 1 address in your code, the following is an example that can read city, state zip
values in a single line of text and the values are stored in a structure. (which allows you to declare an array of struct, or a pointer and allocate as needed when dealing with more than one address later on)
#include <stdio.h>
enum { STSZ = 3, ZIPSZ = 15, CIADDR = 100 }; /* constants */
typedef struct { /* simple struct presuming in the future */
char address[CIADDR], /* you may have more than 1 address */
city[CIADDR],
state[STSZ], /* STSZ must be 3 to read a string of 2-char */
zip[ZIPSZ];
} loc_t;
int main (void) {
loc_t location1 = { .address = "" }; /* declare/initialize struct */
printf ("enter street address: "); /* prompt/read/validate address */
if (scanf (" %99[^\n]", location1.address) != 1) {
fputs ("sscanf() error: invalid address.\n", stderr);
return 1;
}
printf ("enter city: "); /* prompt/read/validate city */
if (scanf (" %99[^,],", location1.city) != 1) {
fputs ("sscanf() error: invalid city.\n", stderr);
return 1;
}
printf ("enter state: "); /* prompt/read/validate state */
if (scanf (" %2s", location1.state) != 1) {
fputs ("sscanf() error: invalid state.\n", stderr);
return 1;
}
printf ("enter zip: "); /* prompt/read/validate zip */
if (scanf (" %14s,", location1.zip) != 1) {
fputs ("sscanf() error: invalid zip.\n", stderr);
return 1;
}
/* output results preceeded by 2-newlines */
printf ("\n\n%s\n%s, %s %s\n", location1.address, location1.city,
location1.state, location1.zip);
}
(note: numbers for the field-width modifiers are included in each scanf
call to protect your array bounds. additionally the multiple '\n'
before the output compensates for the unused prompts when city, state zip
is all entered at the "city: "
prompt)
Example Use/Output
Entering "New York City, NY 12345"
as one string at the "enter city: "
prompt:
$ ./bin/readaddr
enter street address: 1 Main Street
enter city: New York City, NY 12345
enter state: enter zip:
1 Main Street
New York City, NY 12345
Look things over and let me know if you have further questions.