Char parameter in function is null or empty in C - c

I'm currently learning c, then I'm playing with functions and data types, specifically in this case char[]'s.
The following code I've written declares a function called verifyMessage() and receives two parameters, name and gender.
When I execute the function, I pass the two parameters that the user enters through the console, but when I print the name it doesn't print anything.
#include <stdio.h>
int main() {
int i = 0;
double controlNumber = 21200164;
double number = 0;
char name[50];
char gender[1];
int attempts = 5;
int aux = 0;
do {
printf("Introduzca el numero de control: ");
scanf("%lf", &number);
if (controlNumber == number) {
printf("\nWrite your name: ");
scanf("%s", name);
printf("\nWrite your gender (M/F): ");
scanf("%s", gender);
verifyMessage(name, gender);
break;
} else {
i++;
}
} while (i < attempts);
return 0;
}
void verifyMessage(char name[50], char gender[1]) {
if ('M' == gender[0]) {
printf("\n\Name: %s", name);//Here doesn´t print the name
printf("\nMen");
} else if ('F' == gender[0]) {
printf("\nWoman");
} else {
printf("\nInvalid gender");
}
}

Using char gender[1]; with %s is dangerous because gender has room for only one element, so it can accept only strings upto zero characters (the only room will be occupied by terminating null-character)
On the other hand, %s will read positive-length strings (it cannot read strings with zero characters), so it will cause out-of-range access on successful read.
Allocate enough elements and set the maximum length to read (upto the number of elements minis one for terminating null-character) to avoid buffer overrun.
char name[50];
char gender[2];
/* ... */
printf("\nWrite your name: ");
scanf("%49s", name);
printf("\nWrite your gender (M/F): ");
scanf("%1s", gender);
Checking results (return values) of scanf() to check if they successfully read desired things will improve your code more.

Related

Using scanf to create new struct object

Hi I'm using to create a simple program that contains a list of Users (based on the struct below), and I'm trying to create new users based on user input, where I ask for each property seperately using scanf. But I'm having trouble with the structs limitations, for example id should be at max 10 chars and nome can have a max of 25 chars. Here's my code for more context:
struct user {
char id[10];
char name[25];
char group;
float score;
};
struct user list[25];
int registered = 0;
void createNewUser() {
struct user *userPtr, newUser;
userPtr = &newUser;
printf("\nId: ");
scanf("%10s", &(*userPtr).id);
printf("\nName: ");
scanf("%25s", &(*userPtr.name);
printf("\nGroup: ");
scanf("%c", &(*userPtr).group);
printf("\nScore: ");
scanf("%f", &(*userPtr).score);
insert(newUser);
printf("%10s\n", list[0].id);
printf("%25s\n", list[0].name);
printf("%c\n", list[0].group);
printf("%.1f\n", list[0].score);
}
void insert(struct user newUser) {
if (registered < 25){
list[registered] = newUser;
registered += 1;
}
}
With the code I presented above, if I type more than 10 chars for the first input, the next 2 are ignored. And my 3rd scanf is always ignored, the one for group. Can anyone here help me out with this?
The problem with scanf is that when it stops converting characters and there are
more in the input buffer (because the user entered more than you anticipated), then scanf will leave those characters there.
Specially the newline character (inputed when the user presses ENTER)
remains in the input buffer, which causes problems to subsequent calls of
scanf that read characters or strings. So in this case you have to "clean" the input buffer,
so that the next scanf does not consume the left overs of the previous scanf calls.
You can use this function after every scanf:
void clean_stdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
Then you can do:
printf("\nId: ");
scanf("%10s", (*userPtr).id); // no need for &, id is char[]
clean_stdin();
printf("\nName: ");
scanf("%25s", (*userPtr).name); // same here
clean_stdin();
printf("\nGroup: ");
scanf("%c", &(*userPtr).group);
clean_stdin();
printf("\nScore: ");
scanf("%f", &(*userPtr).score);
Also note that the way you are if the maximal length of the ID is 10, then the
buffer must be of length 11, because in C you need to terminate the strings with
the '\0'-terminating byte. So change your structure to this:
struct user {
char id[11];
char name[26];
char group;
float score;
};
Also bear in mind, using a pointer like this
struct user *userPtr, newUser;
userPtr = &newUser;
printf("\nId: ");
scanf("%10s", (*userPtr).id);
...
is not necessary, it actually makes the code harder to read. You can do:
void createNewUser() {
struct user newUser;
printf("\nId: ");
scanf("%10s", newUser.id);
clean_stdin();
...
printf("\nScore: ");
scanf("%f", &newUser.score);
...
}

s expects argument of type char c but argument 2 has type 'int' warning and bad return

Yes ,I know that this question was already asked for many times ,but none of these helped me to discover the problem (duplicate...yeah). I want to read from input a series of strings into an array and then search from 'First Name'. If the name exist ,I want to display all the data stored in that element of array (I attached the code to undestand easily). When I run it ,I read from keyboard all the data ,but it returns me absolutely nothing.
#include<stdio.h>
typedef struct record {
char name[10],lname[10],phone[10],bday[10];
};
void main() {
struct record rec;
char search;
int i,nr;
printf("\nInput number of records: ");
scanf("%d",&nr);
for (i=0 ; i<nr ;i++) {
printf("First name: ");
scanf("%s",&rec.name[i]);
printf("Last name: ");
scanf("%s",&rec.lname[i]);
printf("Phone: ");
scanf("%s",&rec.phone[i]);
printf("Bday: ");
scanf("%s",&rec.bday[i]);
}
printf("Input the first name for searching: ");
scanf("%s",&search);
for (i=0 ;i<nr;i++) {
if (search == rec.name[i]) {
printf("First name: %s\nLast name: %s\nPhone: %s\nB-day: %s",rec.name[i],rec.lname[i],rec.phone[i],rec.bday[i]);
}
}
}
NOTE: I already replaced
scanf("%s",&rec.name[i]);
with
scanf("%s",rec.name[i]);
but no effect.
I believe there are a lot of problems with your code.
Firstly in this line:
scanf("%s",&search);
You have declared search as only a char, when really you want an array of chars. You also don't need & with search, as an array decays to a pointer to the first element.
It instead should be like this:
char search[10];
scanf("%9s", search); /* %9s to avoid buffer overflow */
You need to make this change to all your other scanf() calls, as this seems to be everywhere in this code.
It also seems that you want to create an array of records(structures), So you might need to make this after getting the value of nr. You can create it like this:
struct record rec[nr]; /* array of nr structures */
This also means calls like this:
rec.name[i]
Don't make sense, as you are iterating over the characters within a name, not over all the records in struct records.
This needs to be instead:
rec[i].name
Secondly, Your using == to compare strings, when you should be using strcmp instead. Using == will only compare the base address of the strings, not the actual contents of strings.
Your line should be this instead:
if (strcmp(search, rec[i].name) == 0) {
If you read the manual page for strcmp(), checking for a return value of 0 means that both strings are equal in comparison.
Lastly, in your first scanf() call:
scanf("%d",&nr);
You should really check the return value of this:
if (scanf("%d", &nr) != 1) {
/* exit program */
}
Note: For reading strings, you should really be using fgets instead. You can try upgrading to this later, but I think it is better to understand these basics first.
Here is working example of what your program should do:
#include <stdio.h>
#include <string.h>
#define STRSIZE 10
typedef struct {
char name[STRSIZE+1]; /* +1 to account for null-btye at the end */
char lname[STRSIZE+1];
char phone[STRSIZE+1];
char bday[STRSIZE+1];
} record;
int main() {
char search[STRSIZE+1];
int i,nr;
printf("\nInput number of records: ");
if (scanf("%d", &nr) != 1) {
printf("Invalid input.\n");
return 1;
}
record rec[nr]; /* array of records */
for (i = 0; i < nr ; i++) {
printf("First name: ");
scanf("%10s", rec[i].name);
printf("Last name: ");
scanf("%10s", rec[i].lname);
printf("Phone: ");
scanf("%10s", rec[i].phone);
printf("Bday: ");
scanf("%10s", rec[i].bday);
}
printf("Input the first name for searching: ");
scanf("%10s", search);
for (i = 0; i < nr; i++) {
if (strcmp(search, rec[i].name) == 0) {
printf("First name: %s\nLast name: %s\nPhone: %s\nB-day: %s\n",rec[i].name,rec[i].lname,rec[i].phone,rec[i].bday);
} else {
printf("Record not found.\n");
}
}
return 0;
}
The numeric input leaves a new line character in the input buffer, which is then picked up by the character input. when numeric input with scanf() skips leading white space, character input does not skip this leading white space.
Use a space before %c and it will help you cause if space is not used then a buffer added with value .so that use space before %c
scanf(" %c",&rec.name[i]);

Restrict User To Enter Integers?

Hello I Want To Ask A Question About That How i Restrict User From Enter Integers And Enter Only String OR Characters.
If You Know The Answer Can You Fit That In My Code Below that Would be great if you do that btw forget the date part its just other thing.
void checkin()
{
char comp_choice,more_choice,in_comp_choice;
int comp_amount;
int date_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int date_month1[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int charges_per_room_per_day = 5000,bill;
struct info user;
system("cls");
printf("\t\tCHECK IN FORM\n");
printf("Please Fill Following Information\n");
FILE *fp;
fp = fopen("checkin.txt","a");
time_t t;
time(&t);
printf("First Name : ");
fflush(stdin);
gets(user.first_name);
printf("Last Name : ");
fflush(stdin);
gets(user.last_name);
fflush(stdin);
printf("Contact Number : ");
gets(user.contact_no);
fflush(stdin);
printf("\nGuests : ");
scanf("%d",&user.guest);
printf("Rooms : ");
scanf("%d",&user.rooms);
fprintf(fp,"%s %s %s %d %d\n",user.first_name,user.last_name,user.contact_no,user.guest,user.rooms);
Label2:
printf("Today date and time is %s\n",ctime(&t));
printf("Check In date (DD-MM-YYYY) : ");
scanf("%d %d %d",&user.date,&user.month,&user.year);
printf("Check out date (DD-MM-YYYY) : ");
scanf("%d %d %d",&user.date1,&user.month1,&user.year1);
This Is Image of i am entering Integers And Program Doesn't Say Any Thing
A way to enforce a user entering a valid integer is to read in whatever the user enters (e.g. into a char[..]-buffer), and then to interpret/check the result as required. For this check, you can then either write your custom logic, or use the logic of built in functions, like, for example, strol.
The following sample makes use of strtol. The signature of strtol is long int strtol(const char *nptr, char **endptr, int base). Basically, after a successful scan, endptr will point to the first character of nptr after the (successfully) scanned number; if we do not accept any characters after a (valid) number, we check if endptr actually points to string terminator '\0'; in the case of an unsuccessful scan, endptr is equal to nptr.
Here you go:
#include <stdio.h>
#include <stdlib.h>
int enterIntegerValue(const char *message) {
char inputBuffer[21];
char *endOfScan;
bool error;
int result;
do {
printf("%s", message);
scanf("%20s", inputBuffer);
result = (int)strtol(inputBuffer,&endOfScan,10);
error = (endOfScan == inputBuffer) || (*endOfScan != '\0');
if (error)
printf("Invalid number. Please enter a valid integer number.");
}
while (error);
return result;
}
int main()
{
int rooms = enterIntegerValue("Rooms : ");
printf("input: %d", rooms);
return 0;
}

How do I add a contact to a phonebook program in C?

For my intro to programming class, we have to code a phonebook in C that lets users add contacts, as well as delete and display them. It also has to allocate and free memory as necessary (I tried to do this, but I honestly don't really know what I'm doing).
Anyway, I cannot figure out how to add a contact to the phonebook. I've pasted the relevant part of the program so far. It compiles, but it crashes every time I try to add a contact. Once I get this figured out, I think I can get the rest of the functions without too much trouble. If anyone could help me out, I'd really appreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct entry {
char fname[20];
char lname[20];
char pnumber[20];
} entry;
// function prototypes
void addentry(int, entry*, char addfname[20], char addlname[20], char addpnumber[20]);
main() {
int selection = 0;
int inputtest = 1;
int pnum = 0; // keeps track of number of contacts
char addfname[20] = { '\0' };
char addlname[20] = { '\0' };
char addpnumber[20] = { '\0' };
entry *pcontacts;
pcontacts = (entry*)calloc(1, (sizeof(entry)));
if (pcontacts == NULL) {
printf("No memory is available.");
free(pcontacts);
return 0;
}
while (1) {
do {
printf("\nPhonebook Menu\n\n");
printf("1:\tAdd contact\n");
printf("2:\tDelete contact\n");
printf("3:\tDisplay contacts\n");
printf("4:\tExit\n");
printf("\nChoose an action (1-4): ");
scanf("%d", &selection);
if (selection < 1 || selection > 4) {
printf("Invalid input. Please enter an integer between 1 and 4.\n");
inputtest = 0;
}
if (selection == 4) {
free(pcontacts);
printf("\nThank you for using this phonebook.");
return 0;
}
switch (selection) {
case 1:
pnum++;
printf("\nEnter first name: ");
scanf("%s", addfname);
printf("Enter last name: ");
scanf("%s", addlname);
printf("Enter phone number (no spaces): ");
scanf("%s", addpnumber);
addentry(pnum, pcontacts, addfname[20], addlname[20], addpnumber[20]);
break;
}
} while (inputtest == 1);
}
}
void addentry(int pnum, entry *pcontacts, char addfname[20], char addlname[20], char pnumber[20]) {
pcontacts = (entry*)malloc(pnum * (sizeof(entry)));
if (pcontacts != NULL) {
strcpy(*pcontacts[pnum - 1].fname, addfname);
printf("\nContact has been added.");
} else {
printf ("No memory is available.\n");
}
}
You get strings from standard input with scanf, but you should tell scanf the maximum number of bytes to store to the destination arrays to avoid buffer overruns:
scanf("%19s", addfname);
...
scanf("%19s", addlname);
...
scanf("%19s", addpnumber);
The way you call addentry is incorrect:
addentry(pnum, pcontacts, addfname[20], addlname[20], addpnumber[20]);
You actually try to read the byte just after the end of addfname, addlname and addpnumber. You should instead pass the arrays themselves, that will be passed to the function addentry as pointers to their first bytes:
addentry(pnum, pcontacts, addfname, addlname, addpnumber);
addentry should reallocate the array with realloc. It should be passed a pointer to the array pointer to it can update the pointer in main.
addentry does not copy the strings correctly: it only copies one, but with a syntax error.
Here is a corrected version:
void addentry(int, entry**, char addfname[20], char addlname[20], char addpnumber[20]);
int main(void) {
int selection = 0;
int inputtest = 1;
int pnum = 0; // keeps track of number of contacts
char addfname[20];
char addlname[20];
char addpnumber[20];
entry *pcontacts = NULL;
for (;;) {
do {
printf("\nPhonebook Menu\n\n");
printf("1:\tAdd contact\n");
printf("2:\tDelete contact\n");
printf("3:\tDisplay contacts\n");
printf("4:\tExit\n");
printf("\nChoose an action (1-4): ");
scanf("%d", &selection);
if (selection < 1 || selection > 4) {
printf("Invalid input. Please enter an integer between 1 and 4.\n");
inputtest = 0;
}
if (selection == 4) {
free(pcontacts); /* OK for NULL */
printf("\nThank you for using this phonebook.");
return 0;
}
switch (selection) {
case 1:
printf("\nEnter first name: ");
scanf("%19s", addfname);
printf("Enter last name: ");
scanf("%19s", addlname);
printf("Enter phone number (no spaces): ");
scanf("%19s", addpnumber);
addentry(pnum, &pcontacts, addfname, addlname, addpnumber);
pnum++;
break;
}
} while (inputtest == 1);
}
}
/* add an entry at position pnum */
void addentry(int pnum, entry **pp, char addfname[20], char addlname[20], char pnumber[20]) {
entry *pcontact = *pp;
pcontacts = realloc(pcontacts, (pnum + 1) * sizeof(entry));
if (pcontacts != NULL) {
*pp = pcontacts; /* update pointer in main */
strcpy(pcontacts[pnum].fname, addfname);
strcpy(pcontacts[pnum].lname, addlname);
strcpy(pcontacts[pnum].pnumber, addpnumber);
printf("\nContact has been added.");
} else {
printf ("No memory is available.\n");
}
}

why my program stops working when type enter?

My main goal for this code is to capture the users input and do whatever he wants to do with the choices I have presented, but I'm stuck: when I compile, I can only type the word and the program stops working.
i have no idea where I'm making a mistake.
The is my code:
#include <stdio.h>
#include <string.h>
#define MAX_STRING_LENGTH 100
void grab_user_input(void);
void load_menu(void);
void Count_the_letters(void);
int main(void)
{
grab_user_input();
return 0;
}
void grab_user_input(void)
{
char word;
{
printf("Please enter a single word (25 characters or less): \n");
scanf("%s", &word);
printf("Thanks! The word you entered is: %s\n", word);
}
void load_menu(void)
{
int choice;
do
{
int choice;
printf("\n(:===Menu====:)\n");
printf("1. Count_the_letters\n");
printf("2. Count_the_vowels\n");
printf("3. Reverse_the_word\n");
printf("4. Check_if_palindrome\n");
printf("5. Enter_a_new_word\n");
printf("6. Exit\n");
scanf("%d", &choice);
switch (choice)
{
case 1: Count_the_letters();
break;
}
} while (choice != 3);
}
void Count_the_letters(void)
{
char S[MAX_STRING_LENGTH];
int count;
count = 0;
do {
printf("string:\t");
scanf("%s",S);
if (strcmp(S,"exit") != 0)
++count;
} while (strcmp(S,"exit") != 0);
printf("word count:\t%d\n", count);
}
return 0;
}
scanf("%s", &word);
needs an array of characters to read the data. &word only has space for one character.
You are running into undefined behavior.
Use
char word[26];
scanf("%25s", &word);
The reason is that you are passing the address to the char variable you declared and scanf() is trying to write two bytes where it only fits one.
char word
this declares a char variable, it can hold a single byte
scanf("%s", &word);
whill require at least one byte for an empty string the '\0'.
But also, you declared a lot of functions inside void grab_user_input(void), that is not valid standard c, it might work with some compiler, but it's not standard.

Resources