Right now, the purpose of the code is to take a user input and compare it to a text file (all in code blocks or C programming). The text file reads as:
Leia 12345
Darth 23456
R2D2 34567
Solo 45678
Jabba 56789
Yoda 67890
The code was able to combine the two strings together, but it wont recognize a correct answer nor will the for loop end after 3 tries like it's supposed to. I believe there is something wrong with my for loop, the reading of the text file, and the string comparison. And I have no idea how to fix it.
#include <stdio.h> /* for printf(), scanf() */
#include <stdlib.h> /* for system() */
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
int main()
{
char name[5];
char pin[6];
FILE *file;
file = fopen("ident.txt", "r"); /*How to open, read, and print a text file */
char name2[11];
int i;
int c;
c = getc(file);
fgets(name2, sizeof(name2), file);
if (file == NULL)
{
printf("Error: could not open file %s", file);
return 1;
}
while (c != EOF)
{
printf("\n\tEnter your name: ");
scanf("%s", name); /*How to convert a user input into strings*/
printf("\n\tEnter your pin number: ");
scanf("%s", pin); /*How to convert a user input into strings*/
strcat(strcat(name, " "), pin); /*How to combine two user input string into one*/
printf("\n\n Entry: %s \n\n", name);
for (i = 0; i = 3; i )
{
if (strcmp(name2, name) == 0)
{
printf("It's a Match");
}
else
{
printf("Invalid Entry. Try Again. \n");
break;
}
}
fclose(file);
}
return 0;
}
CodePudding user response:
A couple of point that may help you:
- It is not completely clear from your questrion what the goal of the program is - but if you're struggling it may be a good idea to try and solve a smaller version of the problem. Try making a smaller file with just one word of text, then prompt the user for input that will be compared against that single word.
- You call
getc(file)
andfgets(name2, sizeof(name2), file)
to read from the file before you check whether it has been oppen successfully - this should happen afterwards. - You generally don't check the string bouds when writing to them (and they are very small). If a user inputs a string that is longer than what the array fits, an overflow could happend and lead to unpredictable bugs. Try replacing
scanf()
withfgets()
or a different function that lets you determine how many characters you will read. - Your for loop looks like this:
(i = 0; i = 3; i )
. Here's what it does:
- Once, when entering the loop, set the variable
i
to 0. - Every time the code inside the loop is executed increase
i
by one. - Before re-entering the loop, set
i
to 3. Ifi
is 0, exit the loop. What you probably want is(i = 0; i < 3; i )
- Every run of the loop will do the same thing - comparing
name2
toname
. If you want to do something else, you should probably keep reading from the file and prompting the user for input inside the loop. - The
while (c != EOF)
loop will never end once entered, if you do not modify the content ofc
inside the loop.
CodePudding user response:
From my comments:
In
for (i = 0; i = 3; i )
, the conditional expression isi = 3;
which is actually an assignment operator and not a comparison operator. This will loop infinitely. Did you mean (e.g.)for (i = 0; i < 3; i )
? But, why have the for loop at all?You only read one line from the text file and then loop on the user prompt/input. I think you want to restructure so that after prompting the user for and getting the name and pin, it is then that you want to loop through all lines of the file to look for a match. But, you'd have to reread the file on each failed user attempt [or store the data in a dynamically allocated array]
When you read a line from the file, you use
fgets
and get the whole line, including the trailing newline character [which you should strip (e.g.)name2[strcspn(name2,"\n")] = 0
. When you prompt the user you're usingscanf
to get the name and pin separately. Combining withstrcat
to get a whole line isn't the best way. You could take file input the same way as you do user input and do two strcmp, one for name and the other for pinYou are doing
break
on yourelse
but you probably want it on yourif
(i.e. you want to stop when there is a match and not a mismatch).
The easiest way to fix this is to put the file read and comparison into a function. Then, main
can loop on the user prompt/input and call the function to do the matching.
Additionally, if the input file can not be opened, the program is printing an error message but trying to print file
(a FILE *
) with "%s"
instead of the file's name (e.g. ident.txt
)
Unfortunately, I had to do a lot of restructuring to get the code to work. There were just so many issues that it's difficult to list them all.
But, here is the refactored and working code:
#include <stdio.h> /* for printf(), scanf() */
#include <stdlib.h> /* for system() */
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
// findmatch -- find match for user name/id in file
int
findmatch(const char *name)
{
FILE *xfin;
const char *filename = "ident.txt";
char buf[100];
int match = 0;
xfin = fopen(filename, "r");
if (xfin == NULL) {
printf("Error: could not open file %s -- %s\n",
filename,strerror(errno));
exit(1);
}
while (fgets(buf,sizeof(buf),xfin) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
// match "name pid"
if (strcmp(buf,name) == 0) {
match = 1;
break;
}
}
fclose(xfin);
return match;
}
int
main(void)
{
int i;
int match;
char name[100];
char pin[100];
// do only so many tries before kicking out user
for (i = 0; i < 3; i ) {
printf("\n\tEnter your name: ");
scanf("%s", name);
printf("\n\tEnter your pin number: ");
scanf("%s", pin);
/* How to combine two user input string into one */
// NOTE: there may be a cleaner way to do this, but the code will work
strcat(strcat(name, " "), pin);
printf("\n\n Entry: %s \n\n", name);
match = findmatch(name);
if (match) {
printf("It's a Match\n");
break;
}
printf("Invalid Entry. Try Again. \n");
}
if (! match) {
printf("Too many retries\n");
exit(1);
}
printf("Doing stuff ...\n");
return 0;
}