Files in C, how to do input - c

This is my output function
void output(int n){
FILE *fp;
fp = fopen("sqrt.txt", "w");
for(int i = 1; i < n; ++i){
fprintf(fp, "%.2f\n", sqrt(i));
}
fclose(fp);
}
I'm required to make an input function (it reads the output function) that prompts the user to enter the name of the file to be opened. I need the contents of the file to be printed. If it is an invalid file name, the program should exit.
How to start this exercise?

To read a file in C, you use the fopen function almost just like what you had before, except passing it read rather than write. To read the file after it's been opened, you can use fread or fscanf. The file can be closed as usual with fclose.
If you want to read from the user rather than from a file, you can use fread with stdin instead of a file or (for the equivalent of fscanf) scanf.

fopen return a pointer that can be null: if it is, that mean your process was not able to open the file. So you have to check the return value of fopen to know if the file exist (I am not sure, but if the file exist and the return value is NULL, that means you probably have not the necessary right).
Hope it can help.

Related

Reading from file in C using fread

I'm learning how to read content from a file in C. And I manage to scrape through the following code.
#include <stdio.h>
#include <stdlib.h>
void read_content(FILE *file) {
char *x = malloc(20);
// read first 20 char
int read = fread(x,sizeof(char),20,file);
if (read != 20) {
printf("Read could not happen\n");
}
else {
printf("the content read is %s",x);
}
free(x);
return;
}
int main(int argc,char *argv[]) {
FILE *fp;
fp = fopen("test.txt","w+");
read_content(fp);
fclose(fp);
return 0;
}
But for some reason (which I'm not able to understand) I see the read bytes count as 0.
The problem is that you open the file with the w+ mode. There are two possibilities:
if the file doesn't exist, it will be created empty. Reading from it immediately gives end of file resulting in fread() returning 0.
if the file does exist, it will be truncated i.e. changed into an empty file. Reading from it immediately gives end of file resulting in fread() returning 0.
If you just want to read from the file (as per your example), open it in mode r. If you want to read and write without destroying its existing content, use mode r+.
Whatever mode you choose, always check that fopen() returns non null and print the error if it returns null (this is not the cause of your problem but is best practice).
From Man Page w+ flag:
Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated.
You are probably trying to open a file which doesn't exist at the path you provided, or is read-only as #WhozCraig suggested in comment. This means a new file is being created, an empty file! hence you are seeing 0 bytes read.
To sum up, The fopen is failing, in that case you need to check the return value if it is equal to -1.
To find what was the error, you can check the errno as it is set to
indicate the error.
If you are only intending to read, open the file with r flag instead of w+
The problem lies within this line of code:
fp = fopen("test.txt","w+")
the "w+" mode, clear the previous content of the file and the file will be empty when you just going to read the file without writing anything to it. Hence, it is printing "Read could not happen" because you are trying to read an empty file.
I would suggest you to use "r+" mode, if you are willing to read and then write into the file. Otherwise, r mode is good enough for simple reading of a file.

Reading a File in C: different behavior for "r" and "a+" flags

I want to open a file, read its contents, and then append a line to the file. I thought I should use the "a+" flag for the task.
I have a function which opens a file and returns a pointer to this file.
FILE* open_weekly_disk_file(char* filename){
FILE* weekly_log;
weekly_log = fopen(filename, "a+");
//weekly_log = fopen(filename, "r");
if(! weekly_log){
printf("The attempt to open the weekly log failed!\n");
return NULL;
} else{
return weekly_log;
}
}
Then I have a function which calls the function above and uses scanf to read contents from the file:
void sample_function(char* filename){
FILE* log;
char token[100], current_read[100];
int limit;
log = opened_weekly_disk_file(filename);
// The problem happens here
for(limit=0; limit < TOKEN_NUMBER; limit++){
if(fscanf(log, "%s%s", &token, &current_read) == 2){
printf("%s %s\n", token, current_read);
}
}
...
}
This code works when I use:
weekly_log = fopen(filename, "r");
But does not work when I change the "r" flag to "a+". I get a Segmentation fault right before the for loop.
That is because the mode spec "a" opens a file for appending, with the file pointer at the end. If you try to read from here, there is no data since the file pointer is at EOF. You should open with "r+" for reading and writing. If you read the whole file before writing, then the file pointer will be correctly positioned to append when you write more data.
If this is not enough, please explore ftell() and fseek() functions.
from this SO QA
from the man page:
a+
Open for reading and appending (writing at end of file). The file is
created if it does not exist. The initial file position for reading is
at the beginning of the file, but output is always appended to the end
of the file.
Answer:
There is just one pointer which initially is at the start of the file
but when a write operation is attempted it is moved to the end of the
file. You can reposition it using fseek or rewind anywhere in the file
for reading, but writing operations will move it back to the end of
file.
So, the problem is not the fact that the file is opened in append mode, because it is not, as far as reading from it is concerned.
The problem lies in what your code does in those three dots
log = opened_weekly_disk_file(filename);
...
The code quite probably writes to the file, making the file cursor move to the end of it before the reading occurs.

fscanf not reading in file

I am trying to read in a file and it tells me it cant find the file. I built i have a built in checker that looks to see if the file is there. I have the data file in my debug folder. Am I reading the file incorrectly? I am also using codeblocks for the IDE.
Here is my function calling my file:
char fileData[3];
int bound = 96;
//file pointer and file info
FILE *ips;
ips = fopen("data.txt", "r");
if (ips == NULL)
printf("Please check file!\n"); //this is the output I get
else {
//for loop to scan through file, and retrive the letters
int i;
for(i=0; i<bound; i++)
fscanf(ips, "%c", &fileData);
addBoggleData(head1, fileData);
}
//closes the file system
close(ips);
}
you stated the file failed to open.
Since the fopen() file name parameter has no path info.
and you stated the file is in the debug directory.
1) the execution and the file must be in the same directory
2) in this case, both the executable and the data file must be in the debug directory.
You are passing the wrong parameter to fscanf(), you should pass the address of the ith element, like this
fscanf(ips, "%c", &fileData[i]);
and to be able to tell whether the data was read succesfully, you must check the return value of fscanf(), like
if (fscanf(ips, "%c", &fileData[i]) != 1)
{
warningReadingFailure();
}
Also, the fileData array is way too small, you need to make it at least as big, as the number of bytes you intend to read from the file, i.e.
int bound = 96;
char fileData[bound];

program crashes due to file format

i was trying this problem from usaco. when i use txt file while using file the program is working fine. but when for the submission requirement i change the format to beads.in and beads.out the program crashes. what;s the problem?
here's my code:
#include <stdio.h>
#include<string.h>
main () {
FILE *fin = fopen ("beads.in", "r");
FILE *fout = fopen ("beads.out", "w");
int n;
char str[400];
char now,rev_now;
int pos,forward,reverse,sum,max=0,i,j,k;
fscanf(fin,"%d\n%s",&n,str);
n--;
for(pos=0;pos<=n;pos++){
now=str[pos];
if(pos==0)k=n;
else k=pos-1;
rev_now=str[k];
forward=2;
int flag1=0,flag2=0,reverse=2;
for(i=pos,j=k;;){
if(i==n)i=-1;
if((str[i+1]==now||str[i+1]=='w')&&flag1==0){
i++;
forward++;
}
else{
flag1=1;
}
if(j==0)j=n+1;
if((str[j-1]==rev_now||str[j-1]=='w')&&flag2==0){
j++;
reverse++;
}
else{
flag2=1;
}
if(flag1==1 && flag2==1)break;
}
sum=forward+reverse;
if(max<sum){max=sum;}
}
fprintf(fout,"%d\n",max);
return 0;
}
are you sure beads.in and beads.out are created already..
According to man page
r Open text file for reading. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
May be beads.in is not created in prior to fopen. It's better if you check the status of the fopen, use perror.
You mention that it works with a text file. I'm guessing that beads.in is not a text file, but rather a binary file. If that is the case, then #KVD's suggestion above to use: fopen ("beads.in", "rb"); and fopen ("beads.out", "wb"); should work. The reason the program would crash with binary input data is because you are asking fscanf to copy data into your str buffer until it encounters a newline character. More than likely, the beads.in file has more than 400 characters which will cause a buffer overflow and start overwriting the program stack.

Having problems with fseek() in C

So, I have this function on my program that is supposed to save a "car_str" structure into the desired place on a file specified as a parameter. But when I run it, it keeps overwriting the first slot again and again, as if fseek didn't point to the specified place on the file. Is there any problem with my code? I think it may be related with the multiplication, since without it the program does well, but I cannot point to the place I want.
void save(int car_nbr)
{
FILE *f;
f = fopen("memory.txt","wb");
if (!f)
{
printf ("error");
}
else
{
car_nbr--;
fseek(f, sizeof(struct car_str)*car_nbr, SEEK_SET);
fwrite(&car,sizeof(struct car_str),1,f);
rewind(f);
fclose(f);
printf("\nsaved");
}
}
you need to fopen with r+b.
if you fail than file not exist, so you can try use "wb"
"w" - write: Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file.
"r+" - read/update: Open a file for update (both for input and output). The file must exist.
f = fopen("memory.txt","r+b");

Resources