Comparing two strings in C in a loop - c

I am writing a code to see whether or not the user's input is equivalent to an already stated string. The program loops until the input is the same as the string, using the strcmp function, but for some reason the program does not compare the strings and therefore the loop malfunctions. The code is below:
int main()
{
char passcode[3]="ZZZ";
char input[3];
int check;
while(check!=0)
{
printf("What is the password?\n");
gets(input);
check=strcmp(passcode, input);
}
printf("You crack the pass code!");
return 0;
}

The main problem is here:
char passcode[3]="ZZZ";
char input[3];
A string in C consists of a sequence of characters followed by a null byte. passcode is not large enough to hold the null byte for the string it's initialized with. So when you try to use it as a string by passing it to strcmp it reads past the end of the array. Doing so invokes undefined behavior.
Similarly, input isn't big enough to hold a string big enough to compare against.
You're also not initializing check, so the first time you enter the loop it's value is unknown.
Another problem is the use of gets. This function is dangerous because it does not check if the string the user entered can fit into the given buffer. If is is too big, this again invokes undefined behavior.
Make your arrays larger to hold the user's input as well as the target string, and use fgets instead of gets. You should also change the while loop to do..while since you need to enter the loop at least once.
#include <stdio.h>
int main()
{
char passcode[]="ZZZ"; // array is automatically sized
char input[50];
int check;
do {
printf("What is the password?\n");
fgets(input, sizeof(input), stdin);
check=strcmp(passcode, input);
} while (check!=0);
printf("You crack the pass code!");
return 0;
}

The suggested code above does not recognize the input. It likely wont work and will stuck within the while loop. I would suggest to make it much easier using scanf for the input and then compare the string as you did with strcmp. If input is correct then let in and break out of the while loop. Try this:
#include <stdio.h>
int main()
{
char input[3];
printf ("\nHit the pass code!\npass code: ");
while (input != "ZZZ") {
scanf ("%s",&input);
if (strcmp(input, "ZZZ") == 0){
printf ("\nYou crack the pass code!!\n\n");
break;
} else {
printf ("Wroooong!\n pass code: ");
}
}
return 0;
}

I see what is going on. Your input string is only three three bytes and you are reading using the unsafe gets. The gets is putting the input of ZZZ into the input variable as expected but it is putting the terminating null in the first byte of passcode.
Change the size of your input buffer to 999 and things will work a lot better.

Related

Input Validation for a String in C

I'm trying to make a loop that does not stop until the user inputs a string. For ex. if the user inputs a number or a letter it will say Invalid input until the user enters a string.
But for some strange reason, when I run my code and I input a string, the program continues to loop the block of code. Here's the output
#include <stdio.h>
int main() {
char name[100];
char letter[100];
lt:
printf("\033[0;33m");
printf("\nEnter your Name:\ni.e. Miguel\n");
printf("\033[0m");
scanf("%s", name);
if (name != letter) {
printf("\033[0;31m");
printf("Invalid input");
printf("\033[0m");
goto lt;
}
return0;
}
I've tried the goto function to loop the code but seems like that isn't working.
Uninitialized variables:
char letter[100];
letter is used uninitialized in your code. It's contents are indeterminate. Variables declared with automatic storage aren't implicitly initialised to 0.
Comparing strings:
if (name != letter)
This only compares the pointer addresses (and I believe it invokes undefined behavior), not the contents of the what those pointers point to.
The C standard library provides a function strcmp that compares two strings.
Note: It's declared in string.h.
Buffer overflow vulnerability:
scanf("%s", name);
is similar to using gets (in terms of limiting input). scanf will happily continue to read from stdin until it sees a whitespace, ignore everything to the right hand side of the whitespace, (which leads to more problems down the road) and potentially overflow the buffer.
You could use a field width to limit input:
scanf("%99s", name);
Or even better, use fgets.
fgets(name, sizeof(name), stdin);
It will read at most n - 1 characters and null-terminate the string.
Side-note: fgets will store the \n character in the buffer, which might not be what you want. Here's one way to remove it¹:
name[strcspn(name, "\n\r")] = '\0';
scanf returns the number of successful conversions:
Ignoring the return value of scanf gainsays the 6th commandment of Henry Spencer's "The Ten Commandments for C Programmers":
If a function be advertised to return an error code in the event of
difficulties, thou shalt check for that code, yea, even though the
checks triple the size of thy code and produce aches in thy typing
fingers, for if thou thinkest ``it cannot happen to me'', the gods
shall surely punish thee for thy arrogance.
if (scanf("%99s", name) != 1) {
handle the error here..
}
Using goto:
While that is a legal use, it's discouraged. goto should not be used for such purposes.
Instead, as #SimonGoater suggested, use a while loop.
if the user inputs a number or a letter it will say Invalid input
until the user enters a string.
So the requirements are:
Names should be greater than 1 character.
Names shouldn't have any numbers in them. (But my friends have names with numbers, and even special characters. :-( )
Note:
You can't have a string with one char, unless that char is a null-byte.
Possible Solutions:
As strlen doesn't include the null-terminator, we can use it to calculate the length of the string, and if it equals 1, handle the error accordingly.
Iterate through the buffer character by character, and if you find a number or a special character, handle the error accordingly.
[1] You might want to give this a read for more:
https://codereview.stackexchange.com/q/67608
#include <stdio.h>
#include<conio.h>
#include<string.h>
int main(){
char name[100];
char letter[100]="amir";
lt:
printf("\033[0;33m");
printf("\nEnter your Name:\ni.e. Miguel\n");
printf("\033[0m \n");
scanf("%s",name);
if(strcmp(name, letter) != 0){
printf("\033[0;31m");
printf("Invalid input");
printf("\033[0m");
goto lt;
}
return 0;
}

How to get inputs accepted in this program?

I can't take inputs except string.
If I give inputs in code itself, program is working.
But when I try to take inputs, its not working.
How do I get it to accept given inputs?
For example, if s were "codebook", and from == 'o' and to == 'e', s would become "cedebeek".
#include<stdio.h>
#define MAX 50
void replace(char *s, char from, char to)
{
int i=0;
while(s[i]!='\0')
{
if(s[i]==from)
{
s[i]=to;
}
i++;
}
}
int main()
{
char str[MAX];
char from;
char to;
printf("Enter the string");
scanf("%[^\n]s",&str[0]);
printf("\nEnter the character to be replaced");
scanf("%c",&from);
printf("\nEnter the character to be replaced with");
scanf("%c",&to);
replace(str, from, to);
printf("\nThe modified string is %s",str);
return(0);
}
There are a couple of problems in the posted code. Since arrays decay to pointers to their first elements in most expressions, there is no need for the address operator & in the call to scanf(); also, the trailing s is not part of the scanset conversion specifier:
scanf("%[^\n]", str);
As pointed out by #M.M in the comments, it is not incorrect to use &str[0] here instead of str, but it is more idiomatic, and I personally find it more clear, to use the less cluttered str.
When scanf() returns, a newline character will be left in the input stream, so you should add a leading space in the next call to scanf() to skip over this \n character before reading the user input:
scanf(" %c",&from);
And this call to scanf() will also leave a \n character in the input stream, so again:
scanf(" %c",&to);
Note that you should really specify a maximum width to avoid buffer overflow when reading user input into a string; there is no easy way to do this with MAX, but you can do:
scanf("%49[^\n]", str);
You could further improve code and ensure that input is as expected by checking the values returned by the calls to scanf().

How do I get the user to input a word for string comparison?

I'm running a while loop so the user can constantly enter expressions, until they indicate they want to quit the program. I'm using strcmp() to compare two strings so as soon as they enter quit the program will stop. But the program keeps going, any Ideas?
#include <stdio.h>
#include <string.h>
int main()
{
int min12=0;
char opper;
int x=0;
int min13;
char *Repeatprog="cont";
char *Repeatprog1="quit";
while (strcmp(Repeatprog,Repeatprog1))
{
printf("enter the integer number \n");
scanf( "%d %c %d", &min12, &opper, &min13);
printf("%d %c %d\n", min12, opper, min13);
printf("Type the word quit to end program\n");
scanf("%s", Repeatprog);
}
printf("Good Bye");
return 0;
}
Remember always that an Array is a Pointer to the first object of the array.
And secondly, in your call to scanf() you only read a character. Not a whole string (represented by %s in C)
So in conclusion, your call to scanf() shouldn't have a pointer and should have a string instead of a character.
scanf("%s", Repeatprog);
or simply
gets (Repeatprog);
EDIT :
As the commenter #EOF said, gets() is not a good idea since it can lead to Undefined Behaviour. That's because the program can read more characters than it should have and lead to overflow, thus it isn't secure.
So I recommend using char *fgets(char *str, int n, FILE *stream)
Note:
Also, your code is using string literals. So if you make any attempt to change the content of the char pointer then it will lead to Undefined Behaviour.
For this note, please thank the guys below me [comments]. I made a huge mistake and I'm sorry.

Reading multiple user input strings inside a loop

I am currently trying to solve a problem from CodeChef but I am having troubles with using fgets() inside a loop.
The first input (T) is going to be a positive integer containing the number of user inputs.
Then delimited by newline characters, the user is going to input a string below the length of 10 under any circumstances.
So, I've tried this:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int T;
int diffX, diffY;
char s[SIZE];
scanf("%d", &T);
while (T--){
fgets(s, SIZE, stdin);
printf("%s\n", s);
}
return 0;
}
However, when I attempted to test the code with the following inputs:
3 Hello Hi What
I was only able to input until "Hi" then the program exited successfully (returning 0).
Why is this the case and how can I fix it?
Thank you in advance,
kpark.
fgets() consumes the newline left behind by the first call to scanf(). So, it is consuming 3 lines, but the first line looks like an empty line to the fgets() loop you have.
You can fix this by using fgets() to get the first line too, and parse the string into a number using sscanf().
fgets(s, SIZE, stdin);
sscanf(s, "%d", &T);
/* ... */
It is counting the read of the T as part of the counting. Add a newline in the scanf.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int T;
int diffX, diffY;
char s[SIZE];
scanf("%d\n", &T);
while (T--){
fgets(s, SIZE, stdin);
printf("%s\n", s);
}
return 0;
}
Is your Question is about how to read Multiple Strings in C ?
Then it can be done by 2 ways :-
1.By declaring two dimensional Array of characters.
//Let say we want 6 strings each of them having max 10 characters.
char set[6][10] ;
for(int i=0;i<6;i++)
scanf("%s",set[i])
2.By declaring one dimensional Array of pointers to character (Notice the naming Conventions), in which each of those pointer pointing to a String.
int main(){
int i,numOfStrings;
char temp[30];
printf("Enter Number of strings in set ");
scanf("%d",&numOfStrings);
//Here We have defined array of pointer that will store each string sepratly.
//Arry of pointer to character.
char *setOfStrings[numOfStrings];
for(i=0;i<numOfStrings;i++)
{
printf("Enter string ");
scanf("%s",temp);
setOfStrings[i]= (char*)malloc(sizeof(temp)); //allocted new memory and gave it to array of pointer
strcpy(setOfStrings[i],temp);
}
for(i=0;i<numOfStrings;i++)
{
printf("string = %s \n",setOfStrings[i]);
}
return 0;
}
But that need to understand :
In case of array of pointers we may initialize them with String but Can't take as input from Command line like
char *set[2]={"Dinesh","Kandpal"}; //Its valid but you can't do this from command line
for doing so What we do we will create an space dynamically ,store that address in the one of the element in 1-D array of pointers and then whatever value we have scanned copy that content to the another string to the location that we created using malloc

Problem with scanf and fgets

This is for a homework assignment to sort some given strings. I'm prompting the user for the number of strings they'd like to sort with scanf, allocating an array based on that number, and then getting the strings themselves with fgets.
Everything works fine if the number of strings is hardcoded, but the addition of scanf to let the user decide screws things up. Here's the code:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 20 // Maximum string length.
int main(void)
{
int index, numStrings = 0;
char **stringArray;
printf("Input the number of strings that you'd like to sort: ");
assert(scanf("%d", &numStrings) == 1);
stringArray = (char **)malloc(numStrings * sizeof(char *));
for (index = 0; index < numStrings; index++)
{
stringArray[index] = (char *)malloc(LENGTH * sizeof(char));
assert(stringArray[index] != NULL);
printf("Input string: ");
assert(fgets(stringArray[index], LENGTH, stdin) != NULL);
}
// Sort strings, free allocated memory.
return 0;
}
And here's what the console looks like:
Input the number of strings that you'd like to sort: 3
Input string: Input string: foo
Input string: bar
It skips over the first iteration of the loop, resulting in an empty string at the beginning of the array. My question is, why does it do that, and how can I fix it?
Here's what the console looks with the format string "%d\n" passed to scanf:
Input the number of strings that you'd like to sort: 3
foo
Input string: Input string: bar
Input string: baz
So, I can input all of the strings, but the first prompt for a string is in the wrong place.
You have to tell scanf to clobber the \n by putting \n in the scanf:
scanf("%d\n", &numStrings)
without it, scanf will read the residual newline character [from when the enter button was hit] as the first line in the loop
The real answer (in my humble but ever-so-correct opinion :P) is not to use scanf. Use fgets to read the first line (i.e. the number) and then parse that string yourself with, say, sscanf or strtoul. That way you have the ability to handle errors when someone doesn't input the data in a nice format, and you don't have to hack around scanf's lack of robust whitespace handling.
Also, never used an int to store sizes unless you expect to have a lot of arrays with -4 length. The standard specifies the unsigned type size_t as an unsigned type that is large enough to store object sizes and array indices. Using any other type isn't guaranteed to work.

Resources