Why is my program stopping before reading the txt file? - c

My code keeps closing before reading the file, I made a comment where it closes. Does anyone know why it wont work? I showed it to my lecturer but she couldn't figure it out and then she had to leave so I was wondering if anyone here could figure it out!
#include <stdio.h>
#include <stdlib.h>
#define RESULT_MAX = 100;
#define RESULT_MIN = 0;
int main()
{
int studentId;
char firstName[20];
char lastName[20];
int result;
FILE *fPtr;
if ((fPtr = fopen("student.txt", "w")) == NULL)
{
printf("File could not be opened\n");
//exit(0);
}
else
{
printf("Enter the Id, first name, last name and result\n");
scanf("%d %s %s %d", &studentId, firstName, lastName, &result);
while(!feof(stdin) )
{
fprintf(fPtr, "%d %s %s %d\n", studentId, firstName, lastName, result);
scanf("%d %s %s %d", &studentId, firstName, lastName, &result);
}
fclose(fPtr);
}//else end
// MY PROGRAM ENDS HERE AND WONT CONTINUE!
if ((fPtr = fopen("student.txt", "r")) == NULL)
{
printf("File could not be opened\n");
//exit(0);
}
else
{
printf("Id, first name, last name, result ");
fscanf(fPtr, "%d %s %s %d", &studentId, firstName, lastName, &result);
while(!feof(fPtr) )
{
printf("%d %s %s %d \n", studentId, firstName, lastName, result);
fscanf(fPtr, "%d %s %s %d", &studentId, firstName, lastName, &result);
}//end while
fclose( fPtr );
}//end if
}

the problem is actually the line: 'while(!feof(stdin) )'
because feof() only becomes valid when the program
tries to read past the end of the 'stdin' file.
This is something that cannot be accomplished
suggest
modifying the program to:
1) read into a local buffer[] array, in a loop,
2) using fgets() as the loop control
3) have a leading 'q' (or similar) as an indication of having read all input
4) output a prompt for every input line
5) if going to parse the fields, parse them using
strtok()/atoi() strncpy() strncpy() atoi()
or perhaps
sscanf()
6) check first char of input buffer[] for the end marker (the 'q' above)
to exit the input loop before parsing
there is a similar problem with the
loop reading the file
I.E. do not use feof() for loop control
rather use fgets()
to differentiate each line of input written to the file, modify
the fprintf(fPtr, ... ) format string to include a trailing '\n'

Related

Values lossing in fscanf

The IDE I used is Clion.
I wanna read the Line-separated data stored in .txt file.
Each line contains firstname, surname, gender, ID and age, which are str, str, str, int and int.
StudentList.txt
Olivia SWANSON F 29001 20
Emma ONEILL F 7900 19
I try to use fscanf to read the data.
FILE *fp;
char fname[20];
char sname[20];
char gender[1];
int ID;
int age;
fp = fopen("C:\\Users\\Catlover\\Desktop\\DSA\\Program2\\StudentList.txt", "r");
while(fscanf(fp, "%s %s %s %d %d", fname, sname, gender, &ID, &age)!= EOF)
{
printf("%s,%s,%s,%d,%d\n", fname, sname, gender, ID, age);
}
fclose(fp);
return 0;
But the result it return looks like a little bit weird becasue it doesn't output the second value.
Result is
Olivia,,F,29001,20
Emma,,F,7900,19
Something shocks me is that the same code runned in PellesC lead to the correct result.
I used to learn C++ so there may exists some important rules in C but I didn't notice. Can anyone show that for me?
"%s" without width
Never use "%s" in a *scanf() without a width to indicate the max number of non-white-space characters to read and save. Recall that after reading, a null character is appended. Example: if the buffer size is 100, code can only read up to 99.
char gender[1]; is too small for "F".
Wrong check
fscanf(fp, "%s %s %s %d %d", ...) can return other values than 5 or EOF. As only 5 is acceptable, test against that.
Test open success
If fopen() fails, fscanf(), fclose() are bad
Other issues exist too*
But lets use start with fixing the above.
char fname[20 + 1];
char sname[20 + 1];
char gender[1 + 1];
int ID;
int age;
FILE *fp = fopen("C:\\Users\\Catlover\\Desktop\\DSA\\Program2\\StudentList.txt", "r");
if (fp) {
while(fscanf(fp, "%20s %20s %1s %d %d", fname, sname, gender, &ID, &age) == 5) {
printf("%s,%s,%s,%d,%d\n", fname, sname, gender, ID, age);
}
fclose(fp);
}
return 0;
You need to have space to accommodate null byte also.
char gender[1];
to
char gender[2];

How to write, read and delete a file in a single script in C programming

I created a file and filled it with some entries. However, I want to read this file and show it on the screen. Also, after showing the entries, I want it to be deleted with my permission. But I am stuck at this point please help me.
EDIT: Code is updated but still couldn't figure it out how to do :/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char name[20], surname[20], city[30], country[30], gender[15];
int count = 0;
int main() {
FILE *f1;
f1 = fopen("C:\\FurkanArslan.txt", "r+");
while (count < 10) { // every step provides 5 new data, so 5*10 will provide 50 data in total.
printf("\n*Please enter required information: \n");
printf("Name :"); scanf("%s", name);
printf("Surname:"); scanf("%s", surname);
printf("Country:"); scanf("%s", country);
printf("City :"); scanf("%s", city);
printf("Gender :"); scanf("%s", gender);
fprintf(f1, " %s | %s | %s | %s | %s\n\n", name, surname, gender, city, country);
count++;
}
fclose(f1);
printf("\n<<<<<%d data has been successfully saved!>>>> \n", count * 5);
printf("-------------------------------------\n");
f1 = fopen("C:\\FurkanArslan.txt", "r");
char c, answer;
while ((c = fgetc(f1)) != EOF)
putchar(c); // In this part I displayed file on the screen.
printf("\n\n <<<< %d entries are displayed on the screen! >>>>", count * 5);
printf("\n\nWould you like to remove your file [Y/N] ?");
scanf(" %c", &answer);
if (answer == 'y' || answer == 'Y') {
remove("f1");
printf("\n\n***File successfully removed!");
}
return 0;
}
In order to show the content of a file you have to open it and read it letter by letter, after that, you can use the putchar function to output the current character
FILE *fp = fopen("path/to/file.txt","r");
char c;
while((c=fgetc(fp))!=EOF)
putchar(c);
fclose(fp);
after that to remove a file you need to use the remove function, which receives the name of the file as paramter.
remove("my_file.txt");
There are multiple issues in your code:
there is no need to make the variables and arrays global, just define them in the body of the main() function.
you should tell scanf() the maximum number of characters to store in the destination array with a length specifier in the format string (eg: "%19s") and check for conversion success.
the variable c used in the reading loop must have type int for proper detection of EOF. fgetc() returns a positive byte value if successful and the special negative value EOF at end of file.
you do not need to reopen the file after writing to it. Sine you opened it for update mode, you can just seek back to the beginning of the file with rewind(f1) or fseek(f1, 0L, SEEK_SET).
the file is open for read and update mode ("r+"): it will fail if the file does not exist. You should open it in write and update mode with "w+" to create or truncate it.
you should check that fopen succeeds at opening the file, otherwise you invoke undefined behavior passing a null stream pointer to fprintf.
to remove the file, remove() takes the filename as its argument. You must close the file before attempting to remove it.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const char *filename = "C:\\FurkanArslan.txt";
char name[20], surname[20], city[30], country[30], gender[15];
int count = 0;
FILE *f1 = fopen(filename, "w+");
if (f1 == NULL) {
printf("Cannot open file %s.\n", filename);
return 1;
}
while (count < 10) { // every step provides 5 new data, so 5*10 will provide 50 data in total.
printf("\n*Please enter required information: \n");
printf("Name :"); if (scanf("%19s", name) != 1) break;
printf("Surname:"); if (scanf("%19s", surname) != 1) break;
printf("Country:"); if (scanf("%29s", country) != 1) break;
printf("City :"); if (scanf("%29s", city) != 1) break;
printf("Gender :"); if (scanf("%14s", gender) != 1) break;
fprintf(f1, " %s | %s | %s | %s | %s\n\n", name, surname, gender, city, country);
count++;
}
printf("\n<<<<< %d data has been successfully saved to %s! >>>>\n",
count * 5, filename);
printf("-------------------------------------\n");
rewind(f1);
int c;
while ((c = fgetc(f1)) != EOF)
putchar(c);
printf("\n\n <<<< %d entries are displayed on the screen! >>>>\n", count);
fclose(f1);
printf("\nWould you like to remove your file [Y/N] ?");
char answer;
if (scanf(" %c", &answer) == 1 && (answer == 'y' || answer == 'Y')) {
if (remove(filename)) {
printf("\n\n***Error removing file %s: %s\n",
filename, strerror(errno));
} else {
printf("\n\n***File %s successfully removed!\n", filename);
}
}
return 0;
}

reading in a large amount of lines in C (csv files)

I have an input .csv file which is formatted like so:
10012,85
11981,100
10728,65
Where the first number is a student ID, followed by a grade on an exam. I need to be able to read an indefinite number of these lines, but I'm not sure how to in C. I couldn't format fscanf properly (kept giving me runtime errors/crashes). This is my attempt (note the struct is just how I'll be using the gathered data from the files later):
int main(int argc, char **argv) {
int i = 0;
FILE *inf;
struct List list = SLL_new();
for(int i = 1; i < argc; i++){
inf = fopen(argv[i], "r");
int studentID = 0;
int grade = 0;
if(inf == NULL){
printf("bad");
return 1;
}
fscanf(inf, "%d,%d", &studentID, &grade);
printf("%d, %d", studentID, grade);
}
}
}
This is my output when run with the input file at the top (pre-edit, when I was using fread):
C:\Users\witcher\Documents\NJIT\CS 288>a midterm01.csv
10012,85
11981,100
10728,65δ
I don't think this works with more lines, and regardless, the special character at the end is also confusing to me. I need to read these values as ints, but if I use fread then I need to cast them or something along those lines later.
Your reading ints, and trying to print strings;
fscanf(inf, "%d,%d", &studentID, &grade);
printf("%s, %s", studentID, grade);
Should be
fscanf(inf, "%d,%d", &studentID, &grade);
printf("%d, %d", studentID, grade);
To read the whole file try
while (2 == fscanf(inf, "%d,%d", &studentID, &grade))
{
printf("%d, %d", studentID, grade);
}
fclose(inf);

read string char and int from file in c programming

student.dat file
----------------
Stu:1 abc ($) - 55 in following order (Stu: %d %s (%c) - %d)
Stu:2 pqr (^) - 82
I am trying to read this file and save highest grade details in the variable in c programming.
my code is below but is not complete!
int main(){
int num, grade;
char id, name[35];
FILE *fp = NULL;
fp = fopen("student.dat", "r");
if (fp != NULL) {
while ((fp != '\n') && (fp != EOF)) {
fscanf(fp, "%d %s %c %d", &num, name, id, &grade);
printf("Student Num: %d", num);
printf("Student Name: %s", name);
printf("Student id: %c", id);
printf("Student grade: %d", grade);
}
fclose(fp);
}else {
printf("Failed to open file\n");
}
}
In C, you have 2 primary ways to read line-oriented input and then parse into individual values (really 3, but we will ignore walking a pair of pointers down the string for now).
The preferred manner is to use a line-oriented input function such as fgets or POSIX getline to read an entire line into a buffer, and then parse the buffer with sscanf which can be done in a more flexible manner than a single call to fscanf.
Nonetheless, you appear dedicated to using fscanf here. The key to using fscanf successfully is to provide a format string that accounts for all characters in the line to be read, or to craft the format string to take advantage of properties of the individual format specifiers to accomplish the same thing (e.g. %s (as well as your numerical conversions) will skip leading whitespace giving you some control to deal with line-endings that would otherwise be left in the input-buffer (either the file or stdin and therefore be the next character available on a subsequent call to fscanf, which if not properly handled, will throw a wrench into your read routine.
Another mandatory step is to validate that all conversions specified were successfully completed during each read. You do that by checking the return value for fscanf which is the match count (a count of the number of successful conversions that took place). If you do not check, you cannot have any type of confidence that your values actually hold the data you think they do.
Putting that together, using your input file, and taking the filename to open as the first argument to the program (and reading by default on stdin if no filename is given), you could do something like the following:
#include <stdio.h>
int main (int argc, char **argv) {
int num =0, grade = 0, max = 0; /* initialize all variables */
char id = 0, name[35];
const char *fmt = " Stu:%d %s (%c) - %d"; /* given format string */
FILE *fp = NULL;
if (!(fp = argc > 1 ? fopen (argv[1], "r") : stdin)) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read each line and validate 4 successful conversions */
while (fscanf (fp, fmt, &num, name, &id, &grade) == 4) {
if (grade > max) max = grade;
printf ("Student Num: %d Name: %-12s id: %c grade: %d\n",
num, name, id, grade);
}
printf ("\n highest grade : %d\n\n", max);
if (fp != stdin) fclose (fp);
return 0;
}
Example Use/Output
$ ./bin/stdntread <dat/stdntread.dat
Student Num: 1 Name: abc id: $ grade: 55
Student Num: 2 Name: pqr id: ^ grade: 82
highest grade : 82
Look over the code, and especially the slight tweak to the format specifier, and let me know if you have any additional questions.
As user3386109 already hinted at: the format string "Stu: %d %s (%c) - %d" should do it. It actually doesn't, you need to add the newline, too.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main()
{
int num, grade, ret;
char id, name[35];
int lineno = 1;
FILE *fp = NULL;
// reset errno, just in case
errno = 0;
fp = fopen("student.dat", "r");
if (fp != NULL) {
for (;;) {
ret = fscanf(fp, "Stu: %d %s (%c) - %d\n", &num, name, &id, &grade);
if (ret != 4 && ret != EOF){
fprintf(stderr,"fscanf() returned %d instead of 4 for line %d\n",ret,lineno);
// unlikely, but cheap to check, so check
if(errno != 0){
fprintf(stderr,"With error %s\n",strerror(errno));
}
exit(EXIT_FAILURE);
}
if (ret == EOF) {
// fscanf() returns EOF for end-of-file _and_ error.
// check for error first
if(errno != 0){
fprintf(stderr,"The error %s occured while reading line %d\n",strerror(errno), lineno);
exit(EXIT_FAILURE);
}
// we are done with the file at this point and can bail out graciously
break;
}
printf("Student Num: %d, ", num);
printf("Student Name: %s, ", name);
printf("Student id: %c, ", id);
printf("Student grade: %d\n", grade);
lineno++;
}
fclose(fp);
} else {
printf("Failed to open file: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
File student.dat generated with
for i in `seq 1 1 100`;do character=$(printf \\$(printf '%03o' $((`shuf -i 40-99 -n 1`))));name=$(cat /dev/urandom | tr -dc 'a-zA-Z' | fold -w 3 | head -n 1); echo Stu:$i $name \($character\) - `shuf -i 10-99 -n 1`;done > student.dat
(Yes, that generation can be done simpler, I'm pretty sure ;-) )
First 10 lines of input (new-line is \n everywhere):
Stu:1 qim (+) - 13
Stu:2 EcF (L) - 61
Stu:3 Ko1 (Q) - 50
Stu:4 Ve7 (,) - 23
Stu:5 NiX (;) - 28
Stu:6 4O8 (C) - 73
Stu:7 00m (]) - 79
Stu:8 uiw (C) - 45
Stu:9 47k (X) - 80
Stu:10 MmJ (A) - 38
(file ends with new-line \n!)
Your while loop have incorrect condition, it'll never become false, File pointer never reaches to \n nor EOF, I had modified your code and now its working properly. Check while condition in code
int num, grade;
char id, name[35];
FILE *fp = NULL;
fp = fopen("student.dat", "r");
if (fp != NULL) {
int ret;
while((ret = fscanf(fp, "%d %s %c %d", &num, name, &id, &grade))!=EOF)
{ printf(" Student Num: %d", num);
printf(" Student Name: %s", name);
printf(" Student id: %c", id);
printf(" Student grade: %d\n", grade);
}
fclose(fp);
}else {
printf("Failed to open file\n");
}

fprintf not working, need to print specific lines of txt file

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
struct info
{
char name[15];
char surname[15];
char gender[15];
char education[15];
} sem;
FILE *fp=NULL;
int i, a;
char tmp[256] = {0x0};
while(1)
{
printf("Enter the value\n");
scanf("%d", &a);
if((fp = fopen("info.txt", "r")) != NULL)
{
switch(a)
{
case 0:
exit(0);
case 1:
for(i=0;!feof(fp);i++)
{
fscanf(fp, "%s %s %s %s", sem.name, sem.surname, sem.gender, sem.education);
printf("%s, %s, %s, %s\n",sem.name,sem.surname,sem.gender,sem.education);
}
break;
case 2:
while (fgets(tmp, sizeof(tmp), fp) != NULL)
{
if (strstr(tmp, "bachelors"))
{
/* Code works fine until this part */
fprintf(fp, "\n%s %s %s %s", sem.name, sem.surname, sem.gender, sem.education);
}
}
break;
default: printf("Default statement");
}
fclose(fp);
}
}
}
If anyone could point me out what im doing wrong, id be very greatful, I added a comment where code runs in to a problem and doesnt display anything. Basicly i have txt file. Program if user so desires needs to find lines in the file where "bachelor" is typed and give me back all of those lines.
You are opening your file in read mode (fp = fopen("info.txt", "r")) and trying to write in it using fprintf() which is not possible.
Use fp = fopen("info.txt", "r+") i.e read and write mode.
If you want to compare strings, you will have to use strcmp(), not an undefined function like "strstr". Also, strcmp returns 0 if two strings have same value. So you also have to check that the return value of strcmp() is zero or not.
Also as I replied to your question yesterday, fprintf() method appends the characters that you've passed as arguments to file. So, in your code, when you find string "bachelor", you just add same line at the end of the file. If you want to see those data in console, you can use printf() method.

Resources