Program:
#include<stdio.h>
#include<string.h>
char *f_gets(char *s, int n, FILE *iop)
{
int c=0;
char *cs;
cs = s;
while (--n > 0 && (c = getc(iop)) != EOF)
{
if ((*cs++ = c) == '\n')
break;
}
*cs = '\0';
return (c == EOF && cs == s) ? NULL : s;
}
main(int argc, char *argv[])
{
FILE *fp1,*fp2;
char s2[100],s1[100];
if (argc <= 2 )
printf("2 argument needed \n");
else
if((fp1=fopen(argv[1],"r"))== NULL && (fp2=fopen(argv[2],"r"))==NULL)
printf("cat: can't open The file\n");
else
{
while(1)
{
f_gets(s1,100,fp1); // 1st iteration
f_gets(s2,100,fp2); // 2nd iteration
if(!strcmp(s1,s2))
printf("%s %s",s1,s2);
}
fclose(fp1);
fclose(fp2);
}
}
Output:
$ ./a.out a b
Segmentation fault (core dumped)
$
In the above program, the segfault occurs when we call the f_gets at second time. Even I twice check the program it is hard to
find the problem. Does any one explain why it produce the problem .
Your second file is not open at the time when you make the call.
The problem is that you are calling fopen from the path with short circuiting:
if((fp1=fopen(argv[1],"r"))== NULL && (fp2=fopen(argv[2],"r"))==NULL)
Because of a mistake in your code, when fp1 opens fine, fp2 will always remain closed. This is because (fp1=fopen(argv[1],"r"))== NULL will evaluate to 0, and ensure that (fp2=fopen(argv[2],"r"))==NULL will never be called.
You could fix this by replacing && with ||, but a better approach would be opening one file at a time.
if((fp1=fopen(argv[1],"r"))== NULL && (fp2=fopen(argv[2],"r"))==NULL)
means, "if the program failed to open both fp1 and fp2". You could solve this by using || instead. But preferably don't write long and complex expressions, since they add nothing but an increased chance of writing bugs.
Instead, do this:
fp1=fopen(argv[1],"r");
if(fp1 == NULL)
{
// error handling
}
fp2=fopen(argv[2],"r");
if(fp2 == NULL)
{
fclose(fp1);
// error handling
}
And as a bonus: just because we re-wrote the program into something readable, we now also spotted a second bug. In case the program opened fp1 but failed to open fp2, it never closed fp1 before aborting.
Related
I have a function that gets a string from the user and then does the following
void TraverseFile(char *inFile, char *outFile)
{
FILE *pIn;
FILE *pOut;
pIn = fopen(inFile, "r");
char c;
if (pIn == NULL)
{
printf("File not found");
}
pOut = fopen(outFile, "w");
if (pOut == NULL)
{
fclose(pIn);
printf("The write file cannot be opened.\n");
exit(1);
}
else{
while(1) //while it is not the end of input file
{
c= putchar(tolower(fgetc(pIn)));
if (feof(pIn)) break;
fputc(c,pOut);
}
fclose(pOut);
}
fclose(pIn);
}
Two things are happening: the while loop is giving me a segmentation fault. I think after input is because fgetc() returns in an int and I want to convert to a char. And the creation of the second file has a weird dot next to the txt name (see picture).
At least these problems
Missing .h
Add
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
Wrong type
fgetc() returns an int to handle the typical 257 different return values. #Avi Berger
// char c;
int c;
Using a char value that is negative and not EOF is undefined behavior with tolower(). By saving in int, c will have a value in the unsigned char range or EOF.
while(!feof(pIn)) wrong
Why is “while( !feof(file) )” always wrong?
int c;
while((c = fgetc(pIn)) != EOF) {
c = tolower(c);
fputc(c,pOut);
}
Error lacks exit
When pIn == NULL, no point in continuing. #Retired Ninja
if (pIn == NULL) {
printf("File not found");
exit(1); // Add
}
Without an early exit, fclose(pIn); is undefined behavior as pIn==NULL.
Bad file name
OP has "creation of the second file has a weird dot next to the txt name". Certainly due to improper filename formation like insufficient buffer size for the name.
I'm trying to solve this question regarding moving data from a file to another in C. Running the program gives a segmentation error 11. I've attached a picture of the question. Exercise 4
I believe there is a problem in opening the files, I entered inside the terminal the C code script name: code.c file1.txt file2.bin -b. The files are included in the path.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char** argv){
size_t k;
char read1[100] = {};
FILE* s;
FILE* d;
if (argc < 4) {
printf("NA");
exit(1);
}
if (strcmp(argv[4], "-b") == 0) {
printf("binary file output\n");
d = fopen(argv[3], "wb");
if (d == NULL) {
printf("cant open d");
exit(1);
}
} else {
if (strcmp(argv[4], "-t") == 0) {
printf("textual file output\n");
d = fopen(argv[3], "w");
} else {
printf("error");
exit(1);
}
}
s = fopen(argv[2], "r");
if (s == NULL) {
printf("cant open s");
exit(2);
}
k = fread(read1, sizeof(char),100, s);
while (k != 0) {
fwrite(read1, k,1, s);
k = fread(read1, sizeof(char),100, s);
}
fwrite(read1, k,1, s);
fclose(s);
fclose(d);
return 1;
}
I expect to move all the data from file 1 to file 2, and file2 output can be binary or textual depending on the user input stream. Ignored the 'hexadecimal' case.
You seem to want to write a program that takes the name of an input file, an output file and a flag (-b or -t), so I guess you're calling your program like this:
program infile outfile [-b|-t]
Those are 3 arguments. They will be argv[1], argv[2] and argv[3] respectively. You should not access argv[4]. Your program will segfault on strcmp(argv[4], "-b"). All your argv[x] should be shifted back by one. The check if (argc < 4) is ok though.
Another thing that can cause segmentation fault is reading from a FILE* that is not valid. You're not checking if d == NULL after the second fopen(). You should do that, and exit with an error in case it's NULL.
Other than this, other problems with your code are:
You should not call fwrite after exiting the while loop. You know that k == 0 when out of the loop. It is not harmful, but it's useless and will print nothing.
You should reorder the arguments of fwrite like this: fwrite(read1, 1, k, s).
Your last return 1 statement makes no sense, you should return 0, not 1, for sucessful program execution.
You don't need to initialize the array with char read1[100] = {}; since you don't use it before overwriting its content. Doing char read[100]; is just fine.
PS: you should learn to use GDB to debug your programs. Problems like this one are very easy to spot using GDB by just stepping through the instructions one by one.
I'm trying to run a program that finds the word count for a file. Every time I compile the program it gives me a Segmentation Fault(Core Dumped). Can't figure out why.
#include <stdio.h>
int main(int argc, char* argv[]){
int wc = 1;
FILE *input = fopen(argv[1],"r");
char c = fgetc(input);
while(c != EOF){
if(c == ' '){
wc++;
}
else
c = fgetc(input);
}
fclose(input);
printf("Word Count = %d", wc);
return 0;
}
You're probably segfaulting because you're not passing in a file name on the command line. When you do that, argv[1] is NULL, so fopen is dereferencing a NULL pointer.
You pass the file name to your program on the command line like this:
./my_program file_to_test
To prevent the core dump, you should check that an argument was passed in by checking the value of argc. You should also check the return value of fopen to ensure the file was opened:
if (argc < 2) {
printf("no file name given");
exit(1);
}
FILE *input = fopen(argv[1],"r");
if (input == NULL) {
perror("fopen failed");
exit(1);
}
Then you have another problem:
if(c == ' '){
wc++;
}
else
c = fgetc(input);
When you find a space character, you don't attempt to read the next character. So c doesn't change once a space is read, leading to an infinite loop.
You need to get rid of the else and always call fgetc:
if(c == ' '){
wc++;
}
c = fgetc(input);
Also, the fgetc function returns an int (actually an unsigned char cast to an int), so you should declare c as an int. Otherwise, checking it against EOF can fail.
I created a function to print the contents of a file:
void readFile(char* filename)
{
int c ;
file = fopen(filename, "r");
printf("The contents of the file are:\n");
while((c = fgetc(file)) != EOF)
{
printf("%c", c);
}
return;
}
where file is a global variable. GDB gives output as follows:
_IO_getc (fp=0x0) at getc.c:39
39 getc.c: No such file or directory.
(gdb) bt
#0 _IO_getc (fp=0x0) at getc.c:39
#1 0x000000000040075e in readFile ()
#2 0x00000000004006d4 in main ()
However, the file is present and I get the SEGFAULT after printing the contents of the file. It might be because the buffer here (c) is small but I am not sure. Also, I don't know how do I fix this even if that were the case. Can anyone suggest how do I proceed?
EDIT
I call the readFile function only once. Here is my calling function:
int main(int argc, char* argv[])
{
char * filename;
filename = argv[1];
readFile(filename);
printf("File Handler: %ld", (long)file);
fclose(file);
return 0;
}
You're passing in a filename that doesn't exist or for some other reason cannot be opened. Get rid of the segfault by checking for errors (you'll need to #include <errno.h> and <string.h> too for this:
void readFile(char* filename)
{
int c ;
file = fopen(filename, "r");
if (file == NULL) {
printf("Cannot open file '%s' : %s\n", filename, strerror(errno));
return;
}
printf("The contents of the file are:\n");
while((c = fgetc(file)) != EOF)
{
printf("%c", c);
}
return;
}
Most likely your file is NULL and you are still trying to read it.
I simulated this behaviour (SEG fault) when I deleted this file.
If file exists then your code works fine.
Check what path you are passing.. If you are using single \ try with \\ and see if this works. First \ will work as escape sequence and final path will be send as D:\temp\use.dat to fopen.
readFile("D:\\temp\\user.dat");
Before you do anything with a file, you must ensure that you opened it successfully. This is done by checking that the file pointer received by calling fopen is not NULL.
Once you do this, you read using whatever function you choose until it returns a value that indicates failure to read — a NULL pointer for fgets, 0 or EOF for fscanf, or EOF for fgetc.
In any case, you challenge these return values in two ways. The first way is to check for read errors using ferror. The other way is to check whether the end of the file was reached using feof.
A complete program that should work, based upon your code:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
enum { OPEN_ERROR = 1, READ_ERROR };
enum { PARAM_EXIT = 1, OPEN_EXIT, READ_EXIT };
FILE *file = NULL;
int readFile(char* filename)
{
int c;
file = fopen(filename, "r");
if (file == NULL)
return OPEN_ERROR;
printf("The contents of file '%s' are:\n", filename);
while((c = fgetc(file)) != EOF)
printf("%c", c);
/*
* fgetc returns EOF on end of file and when an error occurs.
* feof is used to determine whether the end of the file was reached.
* Otherwise, we encountered a read error.
*/
if (feof(file))
c = 0;
else
c = READ_ERROR;
return c;
}
int main(int argc, char *argv[])
{
int status = 0;
if (argc == 1) {
fprintf(stderr, "usage: %s file\n", argv[0]);
return PARAM_ERROR;
}
/* Check that <program ""> wasn't used... */
if (argv[1][0] == '\0') {
fprintf(stderr, "error: empty filename detected, exiting. . .\n");
return PARAM_ERROR;
}
switch (readFile(argv[1])) {
case 0:
break;
case OPEN_ERROR:
fprintf(stderr, "error: file open failed - %s\n", strerror(errno));
status = OPEN_EXIT;
break;
case READ_ERROR:
fprintf(stderr, "error: file read failed - %s\n", strerror(errno));
status = READ_EXIT;
break;
default:
fprintf(stderr, "error: unknown error occurred, aborting...\n");
abort();
}
if (file != NULL)
fclose(file);
return status;
}
Of course, normally you would close the file in the same function in which it was opened (e.g. something like filep = openFile(...); readFile(filep); fclose(filep);, except error handling would be used of course).
I am completely changing my answer
Actually, the file that I was reading was open in gedit (which might explain why I was getting "NULL" even after printing the file contents. I closed the file and removed my NULL comparison code and it works perfectly fine.
Ok, from everybody's comments I got to know that you basically get a SEGFAULT when you read the contents of file that has NULL contents. I just made a simple fix in my while loop:
while((c != EOF))
{
printf("%c", c);
c = fgetc(file);
if(c == NULL)
break;
}
Problemo solved! (Although, the compiler gives me a warning of "comparison between pointer and integer".)
I use below code to read a char from file and replace it with another,
but I have an error.loop in going to end of file.
What is wrong?
I tested this code on linux (netbeans IDE) and it was correct and worked beautiful but when I tried to use VS 2008 in windows , I found a non end loop.
//address = test.txt
FILE *fp;
fp=fopen(address,"r+");
if(fp == 0)
{
printf("can not find!!");
}
else
{
char w = '0'; /// EDIT : int w;
while(1)
{
if((w = fgetc(fp)) != EOF)
{
if((w = fgetc(fp)) != EOF)
{
fseek(fp,-2,SEEK_CUR);
fprintf(fp,"0");
}
}
else
{
break;
}
}
}
fclose(fp);
You are storing the result of fgetc in a char, instead of an int.
char w = '0'; /* Wrong, should be int. */
Incidentally, this problem is mentioned in the C FAQ.
If type char is unsigned, an actual
EOF value will be truncated (by having
its higher-order bits discarded,
probably resulting in 255 or 0xff) and
will not be recognized as EOF,
resulting in effectively infinite
input.
EDIT
Reading your question again, it's highly fishy the way you seek back two characters and write one character. That could well lead to an infinite loop.
EDIT2
You (likely) want something like this (untested):
while ((w = getc(fp)) != EOF) {
fseek(fp, -1, SEEK_CUR);
fprintf(fp, "0");
fflush(fp); /* Apparently necessary, see the answer of David Grayson. */
}
The fopen documentation on cplusplus.com says:
For the modes where both read and
writing (or appending) are allowed
(those which include a "+" sign), the
stream should be flushed (fflush) or
repositioned (fseek, fsetpos, rewind)
between either a reading operation
followed by a writing operation or a
writing operation followed by a
reading operation.
We can add an fflush call after the fprintf to satisfy that requirement.
Here is my working code. It creates a file named example.txt and after the program exits that file's contents will be 000000000000n.
#include <stdio.h>
int main(int argc, char **argv)
{
FILE * fp;
int w;
fp = fopen("example.txt","w");
fprintf(fp, "David Grayson");
fclose(fp);
fp = fopen("example.txt","r+");
while(1)
{
if((w = fgetc(fp)) != EOF)
{
if((w = fgetc(fp)) != EOF)
{
fseek(fp,-2,SEEK_CUR);
fprintf(fp,"0");
fflush(fp); // Necessary!
}
}
else
{
break;
}
}
fclose(fp);
}
This was tested with MinGW in Windows.