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;
}
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) and fgets(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() with fgets() 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. If i 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 to name. 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 of c inside the loop.
From my comments:
In for (i = 0; i = 3; i++), the conditional expression is i = 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 using scanf to get the name and pin separately. Combining with strcat 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 pin
You are doing break on your else but you probably want it on your if (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;
}
Related
I have a program that reads file A and then copies the contents to file B.
I would like to write to file B every third character. I created a loop that rewrites every third item to a new char array. In file B I get strange characters. What am I doing wrong?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
int i;
char full_string[100];
char reduce_string[100];
char file_name_for_read[128];
char file_name_for_save[128];
printf("Enter file name for read...\n");
scanf ("%s", file_name_for_read);
strcat(file_name_for_read,".txt");
FILE *fileA;
fileA=fopen(file_name_for_read,"r");
printf("Enter file name for save...\n");
scanf ("%s", file_name_for_save);
strcat(file_name_for_save,".txt");
FILE *fileB;
fileB=fopen(file_name_for_save,"w");
while(fgets(full_string, sizeof(full_string), fileA) !=NULL)
{
for(i = 2; i < 100; i+=3)
{
reduce_string[i-=2] = full_string[i+=1];
}
fprintf(fileB, "%s", reduce_string);
}
fclose(fileA);
fclose(fileB);
}
What am I doing wrong?
Several things. At minimum,
In your inner loop, you iterate over the full length of full_string, regardless of how many of those bytes were actually read from the file by the most recent fgets().
In your inner loop, you invoke undefined behavior because the expression reduce_string[i-=2] = full_string[i+=1] has two side effects on the value of i that are unsequenced relative to each other.
In that expression, i - 2 is anyway not the index you want except when i is 2, because you increment i by 3 at each iteration. You'll end up filling some positions and skipping others.
You do not add a null terminator at the end of the data copied into reduce_string.
Your strategy does not anyway result in copying every third character of the file; rather, it copies every third character of each line. These differ unless all the line lengths of the input files are multiples of 3.
reads file A and then copies the contents to file B. I would like to write to file B every third character.
If lines are not important,
seems simple to read 3 characters and write the 3rd one.
for(;;) {
fgetc(fileA);
fgetc(fileA);
int ch = fgetc(fileA);
if (ch == EOF) break;
fputc(ch, fileB);
}
or
int ch;
do {
fgetc(fileA);
fgetc(fileA);
ch = fgetc(fileA);
} while (ch != EOF && fputc(ch, fileB) != EOF);
The easiest way is to use a different index for each array, that way each can go at their own speed.
int i,x;
for(i = 0, x=0; i < 1000; i+=3, x++)
{
reduce_string[x] = full_string[i];
}
fprintf(fileB, "%s", reduce_string);
Check this code out. In your code, you have reduce_string[i-=2] = full_string[i+=1]; — I don't know where you come up with it, but this was not working.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
int i;
char full_string[100];
char reduce_string[100];
char file_name_for_read[128];
char file_name_for_save[128];
printf("Enter file name for read...\n");
scanf ("%s", file_name_for_read);
strcat(file_name_for_read,".txt");
FILE *fileA;
fileA=fopen(file_name_for_read,"r");
printf("Enter file name for save...\n");
scanf ("%s", file_name_for_save);
strcat(file_name_for_save,".txt");
FILE *fileB;
fileB=fopen(file_name_for_save,"w");
while(fgets(full_string, 50, fileA) !=NULL)
{
int cnt = 0;
for(i = 2; i < strlen(full_string)-3; i+=3)
{
reduce_string[cnt++] = full_string[i];
}
fprintf(fileB, "%s", reduce_string);
}
fclose(fileA);
fclose(fileB);
}
The code I am working on needs a vector of doubles as an input and I was trying to make it variable sized, by using this small library I found on git. A first iteration using strings instead of doubles is:
printf("Write vector components (type 'stop' to stop): \n");
int stop = 0;
while (!stop)
{
fgets(c, sizeof(c), stdin);
if (strcmp("stop\n",c)!=0)
{
vector_add(&v, c);
} else {
stop = 1;
}
}
However, when I print the result (for example with 3 inputs and "stop") I get
the vector is:
stop
stop
stop
I have tried to write the first component everytime I input a new one, and the result is that the last one overwrites the first (and by extension, given the final result, every component).
However, this doesn't happen if I use vector_add manually. For example I have tried combining the example from git and my own code and the complete output is:
emil
hannes
lydia
olle
erik
stop
stop
stop
stop
So it only overwrites when reading. I can't even begin to comprehend what is happening. Haven't written any C in 2 years and I'm starting all over again.
Full code (not including vector library):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.c"
void main(int argc, char* argv[]) {
char c[20];
vector v; vector_init(&v);
printf("Write vector components (type 'stop' to stop):\n");
int stop = 0;
while (!stop)
{
fgets(c, sizeof(c), stdin);
if (strcmp("stop\n",c)!=0)
{
vector_add(&v, c);
// printf("%s\n", (char*)vector_get(&v, 0));
} else {
stop = 1;
}
}
printf("The vector is:\n");
for (int i = 0; i < vector_count(&v); i++) {
printf("%s\n", (char*)vector_get(&v, i));
}
} /* main */
vector_add doesn't copy the data, so your string is still stored in the variable c. When you read a new string, it overwrites the old one.
If your string library contains strdup, you can try this:
vector_add(&v, strdup(c));
I need to read all the information from a line in a file before a space and store it as a string, how do I do that?
File example:
Biology A 4.0
Tennis B 1.0
etc (I need the letter and number later and I know how to store them fine, just the dang string is giving me trouble)
So far I have
int main (void)
{
FILE* grades;
char className[10];
char currChar;
int i = 0;
grades = fopen("grades.txt", "r");
if (fgetc(grades) != ' ')
{
currChar = fgetc(grades);
className[i] = currChar;
i++;
}
/* what I want to happen here: if a character is not a space, it is
appended to className. I thought if i was the position in the array,
I could add in one character at a time
*/
printf("%s", className); // check to make sure it worked
}
what the result is: the symbol that looks like a ? in a hexagon
Thanks for any help, I'm open to trying other ways too. I tried using fgets with the length i equal to the number of characters before a space found in a previous while loop, but that printed the part directly after the area I wanted.
Why not just use fscanf ?
Something like :
#include <stdio.h>
int main (void)
{
FILE* grades;
char className[10];
char grade;
float marks = 0;
grades = fopen("grades.txt", "r");
while(fscanf(grades,"%s %c %f", className, &grade, &marks)>0) {
printf("%s %c %f\n", className, grade, marks);
}
}
There is nothing wrong with reading from a file up-to the first space character with fgetc, however, there are several problems with:
if (fgetc(grades) != ' ')
{
currChar = fgetc(grades);
className[i] = currChar;
i++;
}
When you call fgetc(grades) != ' ', a character is read from grades and then the file-position-indicator is advanced to the next character. So when you call fgetc inside the if statement, you read a character and then the file-position-indicator is advanced in preparation for reading the next character. When you then call fgetc again in the body of the if statement (currChar = fgetc(grades);), you read the second character in the file. It seems rather obvious from your question, that your intent was not to skip-a-character and then begin reading with the next.
When you read input with any character-oriented-input function (e.g. getchar, fgetc, etc.) there are three primary things you are responsible for: (1) insuring you do not attempt to write more characters to your storage variable than it will hold; (2) check for any sentinel or terminating character you wish to stop the read with; and (3) checking that you have not reached the end of the input stream.
Putting those pieces together you could do something like:
#include <stdio.h>
#define MAXCN 10
int main (void)
{
FILE* grades = NULL; /* initialize variables */
char className[MAXCN] = {0};
int currChar = 0; /* currChar is an int */
int i = 0;
/* open and validate file */
if ((grades = fopen("grades.txt", "r")) == NULL) {
fprintf (stderr, "error: file open failed 'grades.txt'.\n");
return 1;
}
/* read from grades until 1st space */
while (i + 1 < MAXCN && ((currChar = fgetc (grades)) != ' ' &&
currChar != EOF)) {
className[i++] = currChar;
}
className[i] = 0; /* null-terminate */
printf("\n className: %s\n\n", className);
return 0;
}
Note: when you stop reading on any character, the next read will resume on the next character in the input stream. So you will need to empty any characters that remain (in the line, etc...) if you want to begin your read at any than other than the next character. Also note, when you open a file with fopen, you should validate that the open actually worked before proceeding to read from the file.
Input
$ cat grades.txt
Homeroom grades are include below
Output
$ ./bin/fgetc_grades
className: Homeroom
Hopefully this will help you get started, let me know if you have any additional questions.
Open an existing text file and append new letter
to this file as long as user wants to add new
letter to the file.
Use while loop
Use fopen (“filename”, “a”);
I have no idea where to start on this. I understand how to append a single letter, word or phrase to a file, but I have no idea to do the other operation on top of that. Any help is much appreciated.
OK, so I wanted to work on writing the while loop part separately and just have it print the output to see if I was on the right track...
Here is what I have so far..
What I still need help with is how to end the while loop (by using a specific character)
How to integrate this into the file format and get it to print the characters onto the file.
#include <stdio.h>
int main()
{
int true;
char mychar;
char NUL;
NUL =000;
while(true)
{
printf("\nEnter a letter to append to file A.txt: ");
scanf(" %c", &mychar);
if(mychar == (char)000)
break;
}
return 0;
}
Use a while loop to achieve this :
#include <stdio.h>
int main(void)
{
char c;
FILE *file;
file = fopen("file.txt","a");
//you can use EOF instead if '\n'
while( (c = getc(stdin)) != '\n' )
{
putc(c,file);
}
fclose(file);
return 0;
}
I have a program that has a text file that is variable in length. It must be capable of being printed in the terminal. My problem is that if the code is too large, part of it becomes inaccessible due to the limited scroll of terminal. I was thinking of having a command executed by a character to continue the lines after a certain point, allowing the user to see what they needed, and scroll if they needed. However the closest I have come is what you see here, which prints the text file one line at a time as you press enter. This is extremely slow and cumbersome. Is there another solution?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
FILE *audit;
audit = fopen("checkout_audit.txt", "r");
char length_of_code[60000];
int ch;
while ((ch = fgetc(audit)) != EOF)
{
fgets(length_of_code, sizeof length_of_code, audit);
fprintf(stdout, length_of_code, audit);
getch();
if (ferror(audit))
{
printf("This is an error message!");
return 13;
}
}
fclose(audit);
return 0;
}
The libraries are included as I tried various methods. Perhaps there is something obvious I am missing, however after looking around I found nothing that suited my needs in C.
You can keep a count of something like num_of_lines and keep incrementing it and when it reaches some number(say 20 lines) then do a getchar() instead of doing it for each line.
Make sure you don't use feof() as already suggested. Just for the purpose of how it can be done I am showing the below snippet.
int num_of_lines = 0;
while(!feof(fp))
{
// fgets();
num_of_lines++;
if(num_of_lines == 20)
{
num_of_lines = 0;
getch();
}
}
Putting the same thing in your code:
int main()
{
FILE *audit;
audit = fopen("checkout_audit.txt", "r");
char length_of_code[60000];
int num_of_lines = 0;
int ch;
while (fgets(length_of_code, sizeof length_of_code, audit) != NULL)
{
fprintf(stdout, length_of_code, audit);
if (ferror(audit))
{
printf("This is an error message!");
return 13;
}
num_of_lines++;
if(num_of_lines == 20)
{
num_of_lines = 0;
getch();
}
}
fclose(audit);
return 0;
}
From the man page of fgets()
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.
Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte is stored after the last character in the buffer.
So char length_of_code[60000]; is not a better option.
Try to set the size of array to optimum value which in most case is 80.
Also as fgets fetches line by line you will have to output line by line untill EOF
EDIT:
1. 2nd argument to fprintf should be the format specifier and not length
2. 3rd arg should be a string and not the file pointer
fprintf(stdout, "%s", length_of_code);
Code Snippet:
while (fgets(length_of_code, sizeof(length_of_code), audit))
{
fprintf(stdout, "%s", length_of_code);
getch();
if (ferror(audit))
{
printf("This is an error message!");
return 13;
}
}