My program compares two text files and puts the differences in file one in a third text file. However, when my file one's size is larger than my file two's size a 'ÿ' character is placed at the end of the third file. For example suppose file one consists of "I like pickles." and file two consists of "I like dogs." then the third file will consist of "pickles.ÿ". Is there a way to get rid of this? And why is this happening? Here is my program:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int ch1, ch2;
int size1, size2;
FILE *fh1, *fh2, *diffone=stdout;
if( argc<3 ) {
printf("need two file names\n"); return(1);
}
if(!(fh1 = fopen(argv[1], "r"))) {
printf("cannot open %s\n",argv[1]); return(2);
}
if(!(fh2 = fopen(argv[2], "r"))) {
printf("cannot open %s\n",argv[2]); return(3);
}
if(argc>3) {
if(!(diffone = fopen(argv[3], "w+"))) {
printf("cannot open %s\n",argv[3]); return(4);
}
}
fseek(fh1, 0, SEEK_END);
size1 = ftell(fh1);//gets size of fh1
fseek(fh1, 0, SEEK_SET);
fseek(fh2, 0, SEEK_END);
size2 = ftell(fh2);//gets size of fh2
fseek(fh2, 0, SEEK_SET);
while((!feof(fh1)) || (!feof(fh2)))
{
ch1=ch2='-';
if(!feof(fh1)) ch1 = getc(fh1);
if(!feof(fh2)) ch2 = getc(fh2);
if (size2 > size1)
{
if(ch1 != ch2 && (!feof(fh1)))
{
fprintf(diffone,"%c", ch1);
}
}
else
{
if (ch1 != ch2)
{
fprintf(diffone,"%c", ch1);
}
}
}
}
feof() only returns true after fgetc() has returned EOF (-1).
See Why is “while ( !feof (file) )” always wrong?
You are not doing any error checking on fgetc(), and you are not checking for EOF on fh2 when size1 > size2.
Try this instead:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int ch1, ch2;
int eof1 = 0, eof2 = 0;
FILE *fh1, *fh2, *diffone=stdout;
if (argc < 3) {
printf("need two file names\n");
return(1);
}
if (!(fh1 = fopen(argv[1], "r"))) {
printf("cannot open %s\n",argv[1]);
return(2);
}
if (!(fh2 = fopen(argv[2], "r"))) {
printf("cannot open %s\n",argv[2]);
return(3);
}
if (argc > 3) {
if (!(diffone = fopen(argv[3], "w+"))) {
printf("cannot open %s\n",argv[3]);
return(4);
}
}
while(1)
{
if (!eof1) {
ch1 = fgetc(fh1);
if (ch1 == EOF) {
if (ferror(fh1)) {
printf("cannot read from %s\n",argv[1]);
return(5);
}
eof1 = 1;
}
}
else {
ch1 = '-';
}
if (!eof2) {
ch2 = fgetc(fh2);
if (ch2 == EOF) {
if (ferror(fh2)) {
printf("cannot read from %s\n",argv[2]);
return(6);
}
eof2 = 1;
}
}
else {
ch2 = '-';
}
if ((eof1) && (eof2))
break;
if ((ch1 != ch2) || (eof1 != eof2)) {
if (fputc(ch1, diffone) == EOF) {
if (argc > 3) {
printf("cannot write to %s\n",argv[3]);
}
return(7);
}
}
}
return 0;
}
Check EOF after each fgetc().
Avoid using feof(). Recall feof() becomes true after an EOF was first returned from a read.
Instead of
while((!feof(fh1)) || (!feof(fh2))) {
if(!feof(fh1)) ch1 = getc(fh1);
if(!feof(fh2)) ch2 = getc(fh2);
Use
while (1) {
ch1 = fget(fh1);
ch2 = fget(fh2);
if (ch1 == EOF) {
if (ch2 == EOF) break;
ch1 = '-';
}
if (ch2 == EOF) {
ch2 = '-';
}
....
}
This problem occurs when you are trying to fetch from file first and then print
for example-
ch=fgetc(fp2);
while(ch!=EOF)
{
ch = fgetc(fp2);
fputc(ch, fp1);
}
INSTEAD DO-
ch=fgetc(fp2);
while(ch!=EOF)
{
fputc(ch, fp1);
ch = fgetc(fp2);
}
Related
it's a cesar encrypt in process
the problem is when i open a file with the method "openFile"
/* it's been 2 years since I've touched the c language, I'm getting back to it */
i have this code other file :
//method to encrypt a char
char encrypt(char c, int jump) {
int overflow = 0;
char res = c;
char tabChars[26] = {'a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z'};
for(int i=0;i<sizeof (tabChars);i++) {
if(c == tabChars[i]) {
if(i+jump > 25) {
overflow = i+jump - 26;
res = tabChars[overflow];
} else if(i+jump <= 25) {
res = tabChars[i+jump];
}
}
}
return res;
};
void writeInFile(FILE* file) {
//todo
};
// error here
void openFile(char* file) {
FILE* f = fopen(file, "r");
printf("\nopen file : %s\n", file);
char c;
while((c = getc(f)) != EOF) {
putchar(c);
}
fclose(f);
};
and main code :
int jump = 5;
char c = 't';
printf("\nletter change with : --%c--\n",encrypt(c,jump));
char* file = "taget/to/message.txt";
openFile(file); // error here
but i have a error :
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
why doesn't work ? thanks all
with if(f) // works, thx all for your comments
void openFile(char* file) {
FILE* f = fopen(file, "r");
if(f) {
printf("\nopen file : %s\n", file);
char c;
while((c = getc(f)) != EOF) {
putchar(c);
}
fclose(f);
} else {
printf("\nopen error...\n");
}
};
out of function :
I need to write separate functions for opening/closing the file and working with it. Was recommended to not use global variables in it.
I have a function where I need to open the file and print what's in it(open_file), a second to work with the data in it(do_stuff_in_file), and a third to only close the file and exit the program(close_file).
When I try to call do_stuff_in_file or close_file the program just crashes.
I know I'm supposed to use pointers, but I just can't get it right and I don't know where's the mistake.
int open_file(FILE **fr) {
if ((fr = fopen("soldcars.txt", "r")) == NULL) {
printf("File was not opened\n");
return 1;
}
else {
char testchar;
while ((testchar = fgetc(fr)) != EOF) {
ungetc(testchar, fr);
//just printing whats in the file
}
}
return 0;
}
int do_stuff_in_file(FILE **fr, int date) {
if (fr==NULL) {
printf("File not open yet\n");
return 1;
}
else{ fseek(fr, 0, SEEK_SET); } //doing stuff
return 0;
}
int close_file(FILE **fr) {
if (fr==NULL) {
printf("It was not even open yet\n");
return 1;
}
else{
if (fclose(fr) == EOF) {
printf("File was not successfully closed");
return 1;
}
else{
printf("Adios");
exit(1);
}
}
}
int main() {
char input;
int date;
FILE* fr;
fr = NULL;
while ((input = getchar()) != 'c') {
if (input == 'o') open_file(&fr);
else if (input == 'd') {
scanf("%d", &date);
do_stuff_in_file(&fr, date);
}
}
if (input == 'c') {
close_file(&fr);
}
return 0;
}
You need to dereference properly. eg
int open_file(FILE **fr) {
if ((*fr = fopen("soldcars.txt", "r")) == NULL) {
perror( "soldcars.txt" );
return 1;
}
Note *fr = open instead of fr = open. And, in that function, always use *fr, as in fgetc(*fr) vice fgetc(fr). Similarly in the other functions. Because fr is not a FILE *, but *fr is.
This program should read rows and count operators, but counts wrong and can not find out where the errors are.
Help me find out the bugs and fix the program to be able to count rows and operators correctly.I've already tried several ways to fix it and it still counts wrong.
Current output:Broqt na operatorite e:1
Broqt na redovete e:1119
Expected output: Broqt na operatorite e:11
Broqt na redovete e:221
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
void cycleOperatorsCounter(FILE* inputStream, FILE* outputStream);
void counter(FILE* inputStream, FILE* outputStream);
int fileToFile(void);
int fileToScreen(void);
int screenToFile(void);
int screenToScreen(void);
void getFileName(char* fileName, int mode);
int menu() {
int i;
printf("----1. FILE TO FILE \n");
printf("----2. FILE TO SCREEN \n");
printf("----3. KBRD TO FILE \n");
printf("----4. KBRD TO SCREEN \n");
printf("----0. EXIT \n");
do {
printf("SELECT OPTION: ");
fflush(stdin);
scanf("%i", &i);
} while (i < 0 || i> 4);
return i;
}
int main(void) {
while (1) {
system("cls");
switch (menu()) {
case 1: fileToFile();
break;
case 2: fileToScreen();
break;
case 3: screenToFile();
break;
case 4: screenToScreen();
break;
default:
return 0;
}
system("pause");
}
}
void getFileName(char* fileName, int mode) {
while (1) {
fflush(stdin);
if (mode == 1) {
printf("Input file name(.C): ");
gets(fileName);
if (fileName[strlen(fileName) - 2] == '.' && toupper(fileName[strlen(fileName) - 1]) == 'C') {
return;
}
}
else {
printf("Output File: ");
gets(fileName);
return;
}
}
}
int fileToFile(void) {
char inputFileName[256], outputFileName[256];
FILE *inputStream, *outputStream;
getFileName(inputFileName, 1);
if (!(inputStream = fopen(inputFileName, "r"))) {
fprintf(stderr, "Error opening file!\n");
return -1;
}
getFileName(outputFileName, 2);
if (!(outputStream = fopen(outputFileName, "w"))) {
fprintf(stderr, "Error opening file!\a\n");
return -1;
}
cycleOperatorsCounter(inputStream, outputStream);
rewind(inputStream);
counter(inputStream, outputStream);
fclose(inputStream);
fclose(outputStream);
printf("Results saved to \"%s\".\n", outputFileName);
return 0;
}
int fileToScreen(void) {
char inputFileName[256];
FILE* inputStream;
getFileName(inputFileName, 1);
if (!(inputStream = fopen(inputFileName, "r"))) {
fprintf(stderr, "Error opening file!\n");
return -1;
}
cycleOperatorsCounter(inputStream, stdout);
rewind(inputStream);
counter(inputStream, stdout);
fclose(inputStream);
return 0;
}
int screenToFile(void) {
char outputFileName[256];
FILE *outputStream, *tempStream;
char str[999];
tempStream = fopen("temp.tmp", "w");
fflush(stdin);
printf("Napishete \"KRAI\" na nov red, kogato vuvedete teksta\n");
while (1) {
gets(str);
if (!strcmp(str, "KRAI")) {
fclose(tempStream);
tempStream = fopen("temp.tmp", "r");
break;
}
fprintf(tempStream, "%s\n", str);
}
getFileName(outputFileName, 2);
if (!(outputStream = fopen(outputFileName, "w"))) {
fprintf(stderr, "Error opening file!\a\n");
return -1;
}
cycleOperatorsCounter(tempStream, outputStream);
rewind(tempStream);
counter(tempStream, outputStream);
fclose(tempStream);
fclose(outputStream);
printf("Results saved to \"%s\".\n", outputFileName);
return 0;
}
int screenToScreen(void) {
FILE *tempStream;
char str[999];
tempStream = fopen("temp.tmp", "w");
fflush(stdin);
printf("Napishete \"KRAI\" na nov red, kogato vuvedete teksta\n");
while (1) {
gets(str);
if (!strcmp(str, "KRAI")) {
fclose(tempStream);
tempStream = fopen("temp.tmp", "r");
break;
}
fprintf(tempStream, "%s\n", str);
}
cycleOperatorsCounter(tempStream, stdout);
rewind(tempStream);
counter(tempStream, stdout);
fclose(tempStream);
return 0;
}
void cycleOperatorsCounter(FILE* inputStream, FILE* outputStream) {
char str[1000];
int cycleCounter = 0;
unsigned i;
while (fgets(str, sizeof(str), inputStream) != NULL) {
for (i = 0; i < strlen(str); i++) {
if ((str[i-1] == ' ' || str[i-1] == '\n' || str[i-1] == '\t' || i==0) &&
(str[i] == 'i') && (str[i + 1] == 'f') && (str[i+3] == ' ' || str[i+3] ==
'\n' || str[i+3] == '\t')) {
cycleCounter++;
}
if ((str[i-1] == ' ' || str[i-1] == '\n' || str[i-1] == '\t' ||
i==0)
&& (str[i] == 'e') && (str[i + 1] == 'l') && (str[i + 2] == 's')
&& (str[i + 3] == 'e')
&& (str[i+5] == ' ' || str[i+6] == '\n' || str[i+7] ==
'\t')) {
cycleCounter++;
}
}
}
fprintf(outputStream, "Broqt na operatorite za cikul e: %d\n",
cycleCounter);
}
void counter(FILE* inputStream, FILE* outputStream) {
char str[1000];
int Counter = 0;
unsigned i;
while (fgets(str, sizeof(str), inputStream) != NULL) {
for (i = 0; i < strlen(str); i++) {
{
if ((str[i-1] == ' ' || str[i-1] == '\n' || str[i-1] == '\t' || i==0))
{
Counter++;
}
}
}
}
fprintf(outputStream, "Broqt na redovete e: %d\n", Counter);
}
This is prefaced by my top comments.
That is, finding the if and the else is more easily done with strtok and strcmp.
And, to count rows/lines, simply doing fgets and counting or doing fgetc and counting the \n will work.
Hopefully, this will get you farther:
void
cycleOperatorsCounter(FILE *inputStream, FILE *outputStream)
{
char *bp;
char *tok;
char str[1000];
int cycleCounter = 0;
while (fgets(str, sizeof(str), inputStream) != NULL) {
bp = str;
while (1) {
tok = strtok(bp," \t\n");
if (tok == NULL)
break;
bp = NULL;
if (strcmp(tok,"if") == 0) {
cycleCounter++;
continue;
}
if (strcmp(tok,"else") == 0) {
cycleCounter++;
continue;
}
}
}
fprintf(outputStream, "Broqt na operatorite za cikul e: %d\n",
cycleCounter);
}
void
counter(FILE *inputStream, FILE *outputStream)
{
int Counter = 0;
// count number of lines
// NOTE: either of these should work:
#if 1
char str[1000];
while (fgets(str, sizeof(str), inputStream) != NULL)
++Counter;
#else
while (1) {
int chr = fgetc(inputStream);
if (chr == EOF)
break;
if (chr == '\n')
++Counter;
}
#endif
fprintf(outputStream, "Broqt na redovete e: %d\n", Counter);
}
I have a programme that needs the user to input 4 files (no order require). Then I do something to the files differently. Now I used the goto statement, I want to replace the goto statement, but don't know how. And I want to know if these go to have some problem? Here is my code that using goto:
int main(int argc, char **argv){
char *tmp;
int i, flag1=0, flag2=0, flag3=0, flag4=0;
FILE *fp1;
FILE *fp2;
FILE *fp3;
FILE *fp4;
char file1[64];
char file2[64];
char file3[64];
char file4[64];
for( i=1; i<argc; i++){
tmp = argv[i];
if ( strcmp(tmp+8,"F1") == 0 ){
sprintf(file1,argv[i]);
flag1=1;
}
else if (strcmp(tmp+8,"F2") == 0 ){
sprintf(file2,argv[i]);
flag2=1;
}
else if (strcmp(tmp+8,"F3") == 0 ){
sprintf(file3,argv[i]);
flag3=1;
}
else if (strcmp(tmp+8,"F4") == 0 ){
sprintf(file4,argv[i]);
flag4=1;
}
}
if( !(flag1 && flag2 && flag3 && flag4) ){
printf("Must input four files!!\n");
exit(-1);
}
if (access(file1,0) != 0){
GOTO L1;
}
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
L1: if (access(file2,0) != 0 ){
goto L2;
}
if((fp2 = fopen(file2,"r")) == NULL){
exit(-1);
}
do_file_2(fp2);
fclose(fp2);
L2: if (access(file3,0) != 0)
{
goto L3;
}
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
L3: if (access(file4,0) !=0)
{
goto end;
}
if((fp4=fopen(file4,"r"))==NULL)
{
exit(-1);
}
do_file_4(fp4);
fclose(fp4);
end:
return 0;
}
You have "if this condition is true, skip over some code". That's the only thing you're using goto for.
That's exactly what if does (except if skips the code if the condition is false).
You can replace:
L2: if (access(file3,0) != 0)
{
goto L3;
}
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
L3:
with:
if (access(file3,0) == 0)
{
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
}
and similarly for the other uses of goto.
You refactor in steps.
You can take the end label statement and put it directly where it is called. That's easy.
For the others, you can use else statements:
if (access(file1,0) != 0){
//GOTO L1;
}else{
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
}
L1: if (access(file2,0) != 0 ){
//goto L2;
}else{
if((fp2 = fopen(file2,"r")) == NULL){
exit(-1);
}
do_file_2(fp2);
fclose(fp2);
}
L2: if (access(file3,0) != 0)
{
//goto L3;
}else{
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
}
L3: if (access(file4,0) !=0)
{
end:
return 0;
}
if((fp4=fopen(file4,"r"))==NULL)
{
exit(-1);
}
do_file_4(fp4);
fclose(fp4);
Of course, since there is no other statements in the if statements, the if else can be refactored to just be an if.
I have broken down more complex problems like this in the past.
Perhaps an approach like the following which uses loops with arrays would be shorter and more compact. This is a fairly straightforward transformation that consolidates separate variables into arrays. This does use an array of function pointers (see How do Function pointers in C work).
The do_file_1(), do_file_2(), etc. functions are just place holders for the actual functions you are using. This keeps the literal file names ("F1", "F2", etc.) that you specify though I am not sure why you are requiring certain, specific file names.
I also use the strcpy() function to copy the file name argument into the array of file names to open rather than using the sprintf() function.
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
void do_file_1 (FILE *fp)
{
printf ("function do_file_1 called.\n");
}
void do_file_2 (FILE *fp)
{
printf ("function do_file_2 called.\n");
}
void do_file_3 (FILE *fp)
{
printf ("function do_file_3 called.\n");
}
void do_file_4 (FILE *fp)
{
printf ("function do_file_4 called.\n");
}
int main(int argc, char **argv)
{
int i;
char *fileArray[4] = { "F1", "F2", "F3", "F4"};
char fname[4][64] = {0};
void (*funcs[4]) (FILE *fp) = {do_file_1, do_file_2, do_file_3, do_file_4};
for( i = 1; i < argc; i++) {
int j;
for (j = 0; j < 4; j++) {
if ( strcmp(argv[i], fileArray[j]) == 0 ) {
strcpy(fname[j],argv[i]);
break;
}
}
}
if( !(fname[0][0] && fname[1][0] && fname[2][0] && fname[3][0]) ) {
printf("Must input four files!!\n");
exit(-1);
}
for (i = 0; i < 4; i++) {
if (access(fname[i],0) == 0) {
FILE *fp = fopen(fname[i],"r");
if (fp != NULL) {
funcs[i](fp);
fclose(fp);
} else {
break;
}
} else {
break;
}
}
if (i < 4) exit(-1);
return 0;
}
the obvious variant is to change if statements like this:
if (access(file1,0) == 0){
if((fp1 = fopen(file1,"r")) == NULL) exit(-1);
do_file_1(fp1);
fclose(fp1);
}
if (access(file2,0) == 0 ){
if((fp2 = fopen(file2,"r")) == NULL) exit(-1);
do_file_2(fp2);
fclose(fp2);
}
...
You're just using goto's as a way to reverse the if clauses. Reverse them directly and indent what lies between:
if (access(file1,0) != 0){
GOTO L1;
}
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
L1: ...
Becomes:
if (access(file1,0) == 0)
{
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
}
//L1:
int main(int argc, char **argv){
char *tmp;
int i, flag1=0, flag2=0, flag3=0, flag4=0;
FILE *fp1;
FILE *fp2;
FILE *fp3;
FILE *fp4;
char file1[64];
char file2[64];
char file3[64];
char file4[64];
for( i=1; i<argc; i++){
tmp = argv[i];
if ( strcmp(tmp,"F1") == 0 ){
sprintf(file1,argv[i]);
flag1=1;
}
else if (strcmp(tmp,"F2") == 0 ){
sprintf(file2,argv[i]);
flag2=1;
}
else if (strcmp(tmp,"F3") == 0 ){
sprintf(file3,argv[i]);
flag3=1;
}
else if (strcmp(tmp,"F4") == 0 ){
sprintf(file4,argv[i]);
flag4=1;
}
}
if( !(flag1 && flag2 && flag3 && flag4) ){
printf("Must input four files!!\n");
return -1;
}
if (access(file1,0) == 0) {
if((fp1 = fopen(file1,"r")) == NULL){
return -1;
}
do_file_1(fp1);
fclose(fp1);
}
/*L1:*/
if (access(file2,0) == 0 ) {
if((fp2 = fopen(file2,"r")) == NULL){
return -1;
}
do_file_2(fp2);
fclose(fp2);
}
/*L2:*/
if (access(file3,0) == 0) {
if((fp3=fopen(file3,"r"))==NULL) {
return -1;
}
do_file_3(fp3);
fclose(fp3);
}
/* L3: */
if (access(file4,0) == 0) {
if((fp4=fopen(file4,"r"))==NULL) {
return -1;
}
do_file_4(fp4);
fclose(fp4);
}
return 0;
}
But really, no one programer will not do so.
How I can edit a file while copying its content from another
source = fopen("sourceFile.txt", "r");
if( source == NULL )
{
printf("Error in doStepOneAndTwo, can't open file source \n");
return USERERR;
}
target = fopen("targetFile.txt", "w");
if( target == NULL )
{
fclose(source);
printf("Error in doStepOneAndTwo, can't open file target %s \n",str);
return USERERR;
}
while( ( ch = fgetc(source) ) != EOF )
{
fputc(ch, target);
//Here I need to check if ch == "blah" change it to "twoBlah" and save twoBlah to targetFile.txt instead of blah
}
I have problem with the syntax
const char *search_word = "blah";
const char *replace_word = "twoBlah";
const char *p = search_word;
while(1){
ch = fgetc(source);
if(*p == ch){
++p;
if(!*p){//match!
fprintf(target, "%s", replace_word);
p = search_word;
}
} else {
if(p != search_word){
const char *temp = search_word;
while(temp != p)
fputc(*temp++, target);
p = search_word;
}
if(ch == EOF)
break;
fputc(ch, target);
}
}