If statements in C [duplicate] - c

This question already has answers here:
What does strcmp() exactly return in C?
(6 answers)
Closed 1 year ago.
I have a problem with my code, I want the code to check if the name is equal to the realname and print what's inside of the if statement, otherwise, to print what's inside of the else statement, at the end of the code it says what it throws.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char name[5];
char realname[] = "Mike";
printf("Please, enter your name: ");
fgets(name, sizeof(name), stdin);
scanf(name, realname);
if (strcmp(name, realname))
{
printf("Nice to meet you %s ", name );
printf("I'm known as robot. ");
printf("And welcome to starting.com");
}
else
{
printf("You're not the owner of this account.");
}
}
//If i type "john" it returns this.
//Please, enter your name: john
//Nice to meet you john I'm known as machinecode. And welcome to starting.com

strcmp returns 0 when both arguments passed to it are equal, and 0 is a "false" value in C. In short, you have your condition reversed. The most readable way to write it, IMHO, is to explicitly compare the result of strcmp to 0:
if (strcmp(name, realname) == 0)
{
printf("Nice to meet you %s ", name );
printf("I'm known as robot. ");
printf("And welcome to starting.com");
}
else
{
printf("You're not the owner of this account.");
}

You have (at least) 3 bugs/misunderstandings in your code.
strcmp return value
It seems you expect strcmp to return something like "TRUE" if the strings are equal. But that's not how strcmp works. If two strings are equal it returns zero. Zero in an if controlling expression is like "FALSE", i.e. the substatement won't be executed. You need to compare the return value to zero, like if (strcmp(name, realname) == 0)
scanf usages
This part scanf(name, realname); is strange. I'm not sure what you expect it to do but as it is, the makes no sense. Delete the line.
fgets usages
fgets reads the std input including the newline character. So before comparing strings, you need to remove that newline character. However, if the provided buffer is too small to hold the typed input, fgets will only store BUFFER-SIZE-1 characters and there will be no newline. You need to handle that case as well. See this question: Removing trailing newline character from fgets() input
So, your code could be:
int main()
{
char name[5];
char realname[] = "Mike";
printf("Please, enter your name: ");
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = 0;
if (strcmp(name, realname) == 0)
{
printf("Nice to meet you %s ", name );
printf("I'm known as robot. ");
printf("And welcome to starting.com");
}
else
{
printf("You're not the owner of this account.");
}
}

Related

My last prompt answers itself. What do I do?

I'm new to C, and I was trying to create a password system with 2 questions. 1. "What is your password?" I prompted the user to answer and recorded the argument. Any input was assigned to the variable. 2."Are you sure? Do you want this password? Enter Yes or No." It would decide whether to use the answer or discard it. Everything was working smoothly until this part. I couldn't type Yes or No. It automatically assumed that I had typed yes and saved it. Can somebody please give me some advice?
#include <stdio.h>
int
main ()
{
char password;
printf ("Hello User.");
printf ("Please type in your password:");
scanf ("%d", & password);
char answer;
printf ("\nAre you sure? Do you want this password? Enter Yes or No: \n");
scanf ("%c", answer);
printf ("\nAnswer is %c");
if (answer == 'Yes')
printf ("Confirmed.");
else (answer == 'No');
printf ("OK. Thank you.");
password = 0;
return 0;
}
As noted in the comments, you likely didn't intend to store a password in a single character. Nor did you likely intend to scanf the password as an integer using, which is what you're saying with %d.
You may want to use getline instead to read an entire line, and store it in password if you declare it as char array.
Let's say you gave it room for 100 chars.
char password[100];
You might read your password in with:
getline(password, 100, stdin);
You can do the same for the second question, but should always use strcmp to compare strings in C. When the two strings are equal, the return value is 0. Be careful as this is opposite of the way that "true" is usually represented by integers in C.
if (strcmp(response, "yes") == 0) {
...
}
Hopefully these tips will point you in the right direction.
Research and study the functions and syntax.
#include <stdio.h>
#include <string.h>
//function: Clears password
void clearPassword(char p[])
{
for(int i = strlen( p ); i>=0; i--)
{
p[i]='\0';
}
}
int main ()
{
char password[101]; //C version of a String
char line[100]; //C version of a String
char answer;
printf ("Hello User.");
printf ("Please type in your password: ");
fgets(line, sizeof(line), stdin); // read input
sscanf(line, "%s", &password); // store password
printf ("\nAre you sure? Do you want this password? Enter Y or N: \n");
fgets(line, sizeof(line), stdin); //read input
sscanf(line, "%c", &answer); // store answer
printf ("\nAnswer is %c \n", answer); // print answer
if (answer == 'Y') //
printf ("Confirmed.");
else
{
clearPassword(password);
printf ("OK. Thank you.");
}
return 0;
}

want to call fgets() multiple times based on users need

User enters '1' or '0' choice to continue getting string using fgets(). So when the user enters the choice, fgets reads it from console. I am storing it in another variable. But fgets gets the choice and stores it in messages. I have tried using fflush(stdin) after receiving the choice. Please help me out.
int main() {
int choice=1;
char *message;
int i=0;
while (choice == 1) {
fflush(stdout);
printf("Enter the message: ");
fflush(stdout);
message = fgets(message,200,stdin);
while (message[i]!='\n') {
i++;
}
message[i] = '\0';
send_message(message);
printf("\nType '1' to continue or '0' to quit: ");
scanf("%d",&choice);
fflush(stdin);
}
}
It looks like you're trying to scanf() to read the user's input -- this is inherently dangerous. (See https://www.reddit.com/r/learnprogramming/comments/1d0w4x/c_scanf_d_but_error_if_user_enters_a_character/).
I'd recommend either using %s for your format string, or better yet, build a subroutine to do safe input and parse it the old-fashioned way, such as something along these lines:
/* getsafe() - Generic input using the preferred input method rather than gets() */
#include <stdio.h>
#include <string.h>
char *getsafe(char *inpstr,int inpsiz) {
char *seachr; /* Result of search via strchr() */
if (inpstr==NULL) {
return(NULL);
}
if (fgets(inpstr,inpsiz,stdin)==NULL) {
return(NULL);
}
seachr=strchr(inpstr,'\n');
if (seachr!=NULL) *seachr=0;
return(inpstr);
}
That way you can specify the buffer length and provide a string (array of characters) of sufficient length as to prevent buffer overruns (security issue), and then parse the [0] position in that array for your answer.
#define ANSSIZ 80 /* Maximum allowed size of user answer */
char usrans[ANSSIZ]; /* User Answer */
printf("Enter 'y' or 'n': ");
getsafe(usrans, ANSSIZ-1);
There's a lot of problems with this - It probably belongs on Code Review
However, here is a critique on some of the major problems
int main() {
int choice=1;
char *message; // This is a pointer, but is not malloc'ed. You might want "char message[200]" instead?
int i=0; // This is the only time "i" is set to 0. It needs to be reset at the start of the loop
while (choice == 1) {
fflush(stdout); // No need for this
printf("Enter the message: ");
fflush(stdout);
message = fgets(message,200,stdin);
while (message[i]!='\n') { // Why not use strlen?
i++; // "i" can keep growing forever if there is no newline (if someone entered 199 characters before pressing enter)
}
message[i] = '\0'; // fgets does this for you - The past loop was pointless
send_message(message);
printf("\nType 'y' to continue or 'n' to quit: "); // You forgot to flush here!
scanf("%d",&choice); // I don't think this will result in a 0 or 1 output... %d is for a digit, and you're asking the user for y or n.
fflush(stdin); // This is invalid and unneeded - You can't flush stdin
}
}

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]);

Comparing strings in C using strcmp

I am trying to learn to program in C but am having trouble with manipulating strings as C treats strings as arrays.
My aim was to make a program that stores the users first name and surname.
Here is my progress:
#include <stdio.h>
int main(int argc, const char * argv[]) {
//defining the variables
char first_name[100];
char surname[100];
char ch[2];
// Asking for the first name and storing it
printf("What's your first name?\n");
scanf("%s", first_name);
// Prints the first name
printf("Hey %s!\n",first_name);
//Asks the user if they want to store their surname
printf("Would you like to tell me your second name? This is optional so type 'Y' for yes and 'N' for no.\n");
scanf("%s", ch);
//validate if they want to store it or not
if (ch == "Y"){
printf("What is your surname?\n");
scanf("%s", surname);
printf("Your whole name is %s %s", first_name, surname);
}
return (0);
}
However, with this code, I get an error because my IDE(xCode) tells me to use the strcmp function. I then edited the code to become this:
if (strcmp(ch, "Y")){
printf("What is your surname?\n");
scanf("%s", surname);
printf("Your whole name is %s %s", first_name, surname);
}
However variable ch is not a literal and so is not comparable.
Sidenote
I did try to compare two literals too, just to see how it works:
char *hello = "Hello";
char *Bye = "Bye";
if (strcmp(hello, Bye)){
printf("What is your surname?\n");
scanf("%s", surname);
printf("Your whole name is %s %s", first_name, surname);
}
But even this gave an error:
Implicitly declaring library function 'strcmp' with type 'int (const *char, const *char)'
I believe I am not able to do this due to my lack of experience so it would be much appreciated if you could help me understand what I'm doing wrong and how I can fix the problem.
You need to include the appropriate header:
#include <string.h>
Also note that your desired logic probably calls for:
if (!strcmp(hello, Bye))
Instead of:
if (strcmp(hello, Bye))
Since strcmp returns 0 in case of equality.
There are several issues you should correct concerning how you handle input with scanf. First always, always validate the number of successful conversions you expect by checking the return for scanf. Next, as mentioned in the comment, there is NO need to include <string.h> in your code to make a one-letter comparison. Use a character comparison instead of a string comparison. Lastly, always limit your input to the number of characters available (plus the nul-terminating character.
Putting the bits together, you could do something like the following:
#include <stdio.h>
#define MAXN 100
int main (void) {
char first_name[MAXN] = "", surname[MAXN] = "";
int ch;
printf ("What's your first name?: ");
if (scanf ("%99[^\n]%*c", first_name) != 1) {
fprintf (stderr, "error: invalid input - first name.\n");
return 1;
}
printf ("Hey %s!\n", first_name);
printf("Enter surname name? optional (Y/N) ");
if (scanf("%c%*c", (char *)&ch) != 1) {
fprintf (stderr, "error: invalid input - Y/N\n");
return 1;
}
if (ch != 'y' && ch != 'Y') /* handle upper/lower case response */
return 1;
printf ("Enter your surname?: ");
if (scanf (" %99[^\n]%*c", surname) != 1) {
fprintf (stderr, "error: invalid input - surname\n");
return 1;
}
printf ("\nYour whole name is : %s %s\n", first_name, surname);
return 0;
}
Example Use/Output
$ ./bin/firstlast
What's your first name?: David
Hey David!
Enter surname name? optional (Y/N) Y
Enter your surname?: Rankin
Your whole name is : David Rankin
Look it over and let me know if you have any questions.
There are two problems here. Firstly you need to see what value is returned by the strcmp and secondly you must use the approprate hedder.
You must use:
#include <string.h>
Secondly, you must edit your if-else statement so it is like this:
if (strcmp(ch, "Y") == 0){
printf("What is your surname?\n");
scanf("%s", surname);
printf("Your whole name is %s %s", first_name, surname);
}
We do this because the strcmp function returns a negative value if ch is smaller than "Y", or a positive value if it is greater than "Y" and 0 if both strings are equal.

Calling scanf() after another string input function creates phantom input

Here's a small program:
#include <stdio.h>
int main() {
char str[21], choice[21]; int size;
while(1){
printf("$ ");
fgets(str, 20, stdin);
printf("Entered string: %s", str);
if(str[0] == 'q') {
printf("You sure? (y/n) ");
scanf("%s", choice);
if(choice[0] == 'y' || choice[0] == 'Y')
break;
}
}
return 0;
}
It reads a string using fgets(). If the string starts with a q, it confirms if the user wants to quit, and exits if the user types y.
When I run it and type q, this happens:
$ q
Entered string: q
You sure? (y/n) n
$ Entered string:
$
Note the $ Entered string:. Clearly, fgets() got an empty character or something as input, even though I didn't type anything.
What's going on?
As described in other answer scanf call leaves the newline in the input buffer you can also use getchar() after scanf like this :
scanf("%20s", choice);// always remember( & good) to include field width
// in scanf while reading
Strings otherwise it will overwrite buffer in case of large strings `
getchar(); //this will eat up the newline
Besides , you should also use fgets like this :
fgets(str,sizeof str, stdin); //Its better
It because the scanf call reads a character, but leaves the newline in the buffer. So when you next time call fgets is finds that one newline character and reads it resulting in an empty line being read.
The solution is deceptively simple: Put a space after the format in the scanf call:
scanf("%s ", choice);
/* ^ */
/* | */
/* Note space */
This will cause scanf to read and discard all training whitespace, including newlines.
Use a 'char' of a specific size char choice [1]
OR
char c[1];
c = getchar();
if(c[0] == 'y' || c[1] == 'y'){
// DO SOMETHING
}

Resources