Comparing strings in C using strcmp - c

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.

Related

If statements in C [duplicate]

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.");
}
}

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

condition check on scanf ()or get on input

I have to print first, middle and last name in abbreviation from a full-name input from from user,e.g ram kumar shahu as r.k. shahu.Problem is that if I get only first name and last name then I should print like r. shahu.
Below is my code so far.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char fname[10],mname[10],lname[10];
printf("Enter the name:\n");
if(lname==NULL)
{
scanf("%s %s ",fname,mname);
}
else
scanf("%s %s %s",fname,mname,lname);
if(lname==NULL)
{
printf("%c.%s",fname[0],mname);
}
else
printf("%c.%c.%s",fname[0],mname[0],lname);
return 0;
}
char fname[10],mname[10],lname[10];
char line[30];
int state;
printf("Enter the name:\n");
fgets(line, sizeof line, stdin);
state = sscanf(line, "%9s %9s %9s", fname, mname, lname);
if(state == 2){
printf("%c.%s\n",fname[0], mname);
} else if(state == 3){
printf("%c.%c.%s\n",fname[0], mname[0], lname);
}
To start with, you are dealing with a case where you don't know the length of the input. I would suggest you to take the following approach.
Read the whole input from user using fgets()
Start tokenizing based on fixed delimiter , maybe a space. You can use strtok()
If token count is 2, the tokens are considered as first and last name
If token cout is 3, they are first, middle and last names.
Then, you can print out the first element from all the tokens required (1 or 2). That is, in case 3, you print the first element of the first token and the complete second token, in case of 4, you print the first elements from first and second token and the third in full.

Why can't I input values?

I can't input values without an error popping up, even though the code is correct.
#include <stdio.h>
int main()
{
char name[100];
printf("Enter your name: ");
scanf_s("%s", name);
printf("Your Name is: %s", name);
return 0;
}
As soon as I input a value to the name and press enter, an error message pops up and says:
Unhandled exception at 0x0FC13FD4 (msvcr120d.dll) in Project8.exe: 0xC0000005: Access violation writing location 0x00D40000.
What is causing this and how can it be fixed?
You should use fgets instead
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
if (fgets(name, sizeof(name), stdin) == NULL)
return 1;
printf("Your Name is: %s", name);
return 0;
}
Try this
if (scanf_s("%99s", name, _countof(name)) == 1)
printf("Your Name is: %s", name);
Two things
scanf_s() is a buffer overflow safe function, and it expects a length argument for "%s" specifier.
You should only proceed to printf() if you actually succeeded scannig the value, for which the check (scanf(...) == 1) is there.
The 1 there, means one of the input parameters matched by the specifiers, since in this case there is only one of them, then it will mean a full match.
Also, I am almost sure that the _countof() macro, is defined as sizeof(x) / sizeof(x[0]) so this should also do it
if (scanf_s("%99s", name, sizeof(name)) == 1)
printf("Your Name is: %s", name);
since in this case sizeof(name[0]) == sizeof(char) == 1.
Your code could work if you used the standard scanf() function, i.e.
if (scanf("%99s", name) == 1)
printf("Your Name is: %s", name);

scanf not responding?

Ive recently begun learning C and am trying to write a password data protection program. Im writing a function which should test to see if a file, password.txt exists if it doesnt it will get a null value and then ask the user to set a master password and to repeat. However it doesnt allow the user to repeat the password. Any tips? - Cheers (Keep in mind just C not C++)
/*Headers*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_LENGTH 99
int main(void){
/*Variable Declaration*/
char password[] = "Lakaka";
masterPassword();
printf("Welcome to Fort-Knox.");
getchar();
return 0;
}
int masterPassword(void){
/*Password Comparison Variables*/
char password[MAX_LENGTH];
char password1[MAX_LENGTH];
FILE*fp;
if (fp == NULL){
printf("Choose a master password:\n");
scanf("%c", password);
printf("Please repeat password:\n");
scanf("%c", password1);
if (password == password1){
printf("Password Accepted.");
fp = fopen("password.txt", "w+");
printf("File Created");
fclose(fp);
return 0;
}
}
}
Use %s not %c as format specifier, when reading a string. %c only reads a single character.
Your formatting specifier is wrong.
This is also wrong:
if (password == password1)
this will only compare the arrays converted to pointers. You need to compare character-by-character, by calling strcmp():
if( strcmp(password, password1) == 0 )
{
printf("match!\n");
}
use "%s" instead of "%c"
%c is for only 1 character
%s is for string
scanf("%s", password);
scanf("%s", password1);
you need to do
scanf("%s", password);
and to compare use :
strncmp(password,password1,MAX_LENGTH)
it´s always more safe :)...

Resources