I was writing a C program that would read and merge 3 files together (program not complete yet), however, as I was testing I realized the program compiles but the screen on the console remains blank!
Any help is appreciated, especially why is it blank?
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("test");
//open three files for merging
FILE *fp1 = fopen("american0.txt","r");
FILE *fp2 = fopen("american1.txt","r");
FILE *fp3 = fopen("american2.txt","r");
printf("test");
//open file to store the result
FILE *fpm = fopen("words.txt", "w");
//creating an array to save the files data
char c;
char mergedFile[50];
//checking to make sure files are being read
if(fp1 == NULL && fp2 == NULL && fp3 == NULL && fpm == NULL)
{
printf("Could not open one or all of the files.\n");
printf("Exiting program!");
exit(0);
}
printf("test");
//initializing counter values
//inserting data from file into an array
while ((c = fgetc(fp1)) != EOF)
{
fputc(c, mergedFile);
}
while ((c = fgetc(fp2)) != EOF)
{
fputc(c, mergedFile);
}
while ((c = fgetc(fp3)) != EOF)
{
fputc(c, mergedFile);
}
printf("%s",mergedFile[0]);
printf("test");
return 0;
}
Error --> fputc requires a file pointer as it's second argument rather than an array: int fputc ( int character, FILE * stream );
Points to be taken care of:
The size of array should be large enough to contain all the data from these files.
Take care of the format specifier and what it requires in a char array.
What if size of array is less than total size of all files? - Error handling
What if files to be read/written into are in some other directory?
Here is a minimal corrected version:
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 //ADDED NEW
int main()
{
//open three files for merging
FILE *fp1 = fopen("american0.txt","r");
FILE *fp2 = fopen("american1.txt","r");
FILE *fp3 = fopen("american2.txt","r");
//open file to store the result
FILE *fpm = fopen("words.txt", "w");
//creating an array to save the files data
int c;
int i=0;
char mergedFile[MAX]={0}; //MODIFIED & INITIALIZED
//checking to make sure files are being read
if(fp1 == NULL && fp2 == NULL && fp3 == NULL && fpm == NULL)
{
printf("Could not open one or all of the files.\n");
printf("Exiting program!");
exit(0);
}
//initializing counter values
//inserting data from file into an array
while (((c = fgetc(fp1)) != EOF)&&(i<MAX)) //MODIFIED
{
mergedFile[i++]=c; //MODIFIED
}
while (((c = fgetc(fp2)) != EOF)&&(i<MAX)) //MODIFIED
{
mergedFile[i++]=c; //MODIFIED
}
while (((c = fgetc(fp3)) != EOF)&&(i<MAX)) //MODIFIED
{
mergedFile[i++]=c; //MODIFIED
}
printf("%s",mergedFile); //MODIFIED
return 0;
}
Related
I am trying to make a program in C, that reads a text file and replace \r\n with \n to the same file converting the line ending from DOS to UNIX. I use fgetc and treat the file as a binary file. Thanks in advance.
#include <stdio.h>
int main()
{
FILE *fptr = fopen("textfile.txt", "rb+");
if (fptr == NULL)
{
printf("erro ficheiro \n");
return 0;
}
while((ch = fgetc(fptr)) != EOF) {
if(ch == '\r') {
fprintf(fptr,"%c", '\n');
} else {
fprintf(fptr,"%c", ch);
}
}
fclose(fptr);
}
If we assume the file uses a single byte character set, we just need to ignore all the '\r' characters when converting a text file form DOS to UNIX.
We also assume that the size of the file is less than the highest unsigned integer.
The reason we do these assumptions, is to keep the example short.
Be aware that the example below overwrites the original file, as you asked. Normally you shouldn't do this, as you can lose the contents of the original file, if an error occurs.
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
// Return a negative number on failure and 0 on success.
int main()
{
const char* filename = "textfile.txt";
// Get the file size. We assume the filesize is not bigger than UINT_MAX.
struct stat info;
if (stat(filename, &info) != 0)
return -1;
size_t filesize = (size_t)info.st_size;
// Allocate memory for reading the file
char* content = (char*)malloc(filesize);
if (content == NULL)
return -2;
// Open the file for reading
FILE* fptr = fopen(filename, "rb");
if (fptr == NULL)
return -3;
// Read the file and close it - we assume the filesize is not bigger than UINT_MAX.
size_t count = fread(content, filesize, 1, fptr);
fclose(fptr);
if (count != 1)
return -4;
// Remove all '\r' characters
size_t newsize = 0;
for (long i = 0; i < filesize; ++i) {
char ch = content[i];
if (ch != '\r') {
content[newsize] = ch;
++newsize;
}
}
// Test if we found any
if (newsize != filesize) {
// Open the file for writing and truncate it.
FILE* fptr = fopen(filename, "wb");
if (fptr == NULL)
return -5;
// Write the new output to the file. Note that if an error occurs,
// then we will lose the original contents of the file.
if (newsize > 0)
count = fwrite(content, newsize, 1, fptr);
fclose(fptr);
if (newsize > 0 && count != 1)
return -6;
}
// For a console application, we don't need to free the memory allocated
// with malloc(), but normally we should free it.
// Success
return 0;
} // main()
To only remove '\r' followed by '\n' replace the loop with this loop:
// Remove all '\r' characters followed by a '\n' character
size_t newsize = 0;
for (long i = 0; i < filesize; ++i) {
char ch = content[i];
char ch2 = (i < filesize - 1) ? content[i + 1] : 0;
if (ch == '\r' && ch2 == '\n') {
ch = '\n';
++i;
}
content[newsize++] = ch;
}
I've been trying to merge the contents of two .txt files into a third .txt file that combines the output. All I know how to do (and all I have been able to find answers for), however, is to merge them by putting the contents of the first file first, and the second file second. However, I would prefer the output to list the first line of the first file, then the first line of the second file -- followed on a new line by the second line of the first file and the second line of the second file.
To make this clearer visually, the code is currently appearing as:
file1-line1
file1-line2
file1-line3
file2-line1
file2-line2
file2-line3
... When I'd like it to appear as:
file1-line1 file2-line1
file1-line2 file2-line2
file1-line3 file2-line3
The code I have is very basic and executes the first example fine:
int main()
{
FILE *pointer1 = fopen("file1.txt", "r");
FILE *pointer2 = fopen("file2.txt", "r");
FILE *pointer3 = fopen("combined.txt", "w");
int ch;
if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
{
puts("Could not open files");
exit(0);
}
while ((ch = fgetc(pointer1)) != EOF)
fputc(ch, pointer3);
while ((ch = fgetc(pointer2)) != EOF)
fputc(ch, pointer3);
printf("Merged file1.txt and file2.txt into combined.txt");
fclose(pointer1);
fclose(pointer2);
fclose(pointer3);
return 0;
}
Is there a way to output the described situation? I am aware that E0F refers to the end of a file, and is likely causing an issue. Is there a similar condition for an end of a line (like E0L)?
Edit: Changed char ch to int ch.
First, if you have a Unix-like system, the paste command already does that. Next as you want to process lines, you should use fgets. Here you have to loop over input files one line at a time, copy the lines to the output file without the newline, and add the new line after copying everything.
As the processing for both input files is the same, and as I am lazy, I wrote a function to only write it once. In the end code could be:
FILE *copyline(FILE *in, FILE *out) {
char line[256];
if (in != NULL) {
for (;;) { // loop if the line is larger that sizeof(line)
if (NULL == fgets(line, sizeof(line), in)) { // EOF on file1
fclose(in);
in = NULL;
break;
}
size_t end = strcspn(line, "\n");
if (end != 0) fwrite(line, 1, end, out); // smth to write
if (end != strlen(line)) break; // \n found: exit loop
}
}
return in;
}
int main()
{
FILE *pointer1 = fopen("file1.txt", "r");
FILE *pointer2 = fopen("file2.txt", "r");
FILE *pointer3 = fopen("combined.txt", "w");
const char sep[] = " "; // a separator between lines of both file
if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
{
puts("Could not open files");
exit(0);
}
for (;;) {
pointer1 = copyline(pointer1, pointer3);
fwrite(sep, strlen(sep), 1, pointer3);
pointer2 = copyline(pointer2, pointer3);
if (pointer1 == NULL && pointer2 == NULL) break;
fputc('\n', pointer3); // if smth was written, add a newline
printf(".");
}
printf("Merged file1.txt and file2.txt into combined.txt");
fclose(pointer3);
return 0;
}
Here's one way to approach it:
#include <err.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(int argc, char **argv)
{
if( argc < 3 ) {
printf("usage: %s file1 file2\n", basename(argv[0]));
}
FILE *pointer1 = xfopen(argv[1], "r");
FILE *pointer2 = xfopen(argv[2], "r");
FILE *current = pointer1;
int ch;
while( ( ch = fgetc(current)) != EOF ) {
if( ch == '\n' ) {
if( current == pointer1 ) {
int k;
current = pointer2;
if( (k = fgetc(current)) != EOF ) {
ungetc(k, current);
ch = ' ';
}
} else {
current = pointer1;
}
}
putchar(ch);
}
if( ferror(current) ) {
err(EXIT_FAILURE, "Error reading %s",
current == pointer1 ? argv[1] : argv[2]);
}
current = current == pointer1 ? pointer2 : pointer1;
while( (ch = fgetc(current)) != EOF) {
putchar(ch);
}
fclose(pointer1);
fclose(pointer2);
return 0;
}
#include <stdio.h>
int main()
{
FILE *pointer1 = fopen("file1.txt", "r");
FILE *pointer2 = fopen("file2.txt", "r");
FILE *pointer3 = fopen("combined.txt", "w");
char ch1, ch2;
if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
{
puts("Could not open files");
return 0;
}
do
{
char c1 = fgetc(pointer1);
char c2 = fgetc(pointer2);
if (feof(pointer1) || feof(pointer2))
break;
while(c1!='\n')
{
fputc(c1,pointer3);
c1=fgetc(pointer1);
if(feof(pointer1)) break;
}
fputc(' ',pointer3);
while(c2!='\n')
{
fputc(c2,pointer3);
c2=fgetc(pointer2);
if(feof(pointer2)) break;
}
fputc('\n',pointer3);
} while (1);
printf("Merged file1.txt and file2.txt into combined.txt");
fclose(pointer1);
fclose(pointer2);
fclose(pointer3);
return 0;
}
This works like you want.
Output: Combined file.txt
file1-line1 file2-line1
file1-line2 file2-line2
file1-line3 file2-line3
I currently have to add, and make it so it goes in an order like this
content of file 1
content of file 2
content of file 1
content of file 2
its currently only writing the contents of one text file into the output file, i cant see where i'm going wrong so any help is greatly appreciated.
**** Edit, hi done some digging and found that this exact question has already been answered, didnt want to get in trouble with mods and couldnt delete, thanks all
You are not storing the stream pointers returned by fopen() and you are not interleaving lines from file1 and file2. Here is how to fix these issues:
...
// file 3
printf("Please enter the name of the output file : ");
if (scanf("%s", file3) != 1) {
printf("input error\n");
exit(1);
}
FILE *OpenFile = fopen(file1, "r");
FILE *OpenFile2 = fopen(file2, "r");
FILE *OpenFile3 = fopen(file3, "w");
if (OpenFile == NULL || OpenFile2 == NULL || OpenFile3 == NULL) {
perror("Error opening files");
printf("Press any key to exit!\n");
exit(1);
}
int c1 = 0, c2 = 0;
while (c1 != EOF || c2 != EOF) {
if (c1 != EOF) {
/* copy a line from file1 */
while ((c1 = fgetc(OpenFile)) != EOF && c1 != '\n') {
fputc(c1, OpenFile3);
}
fputc('\n', OpenFile3);
}
if (c2 != EOF) {
/* copy a line from file2 */
while ((c2 = fgetc(OpenFile)) != EOF && c2 != '\n') {
fputc(c2, OpenFile3);
}
fputc('\n', OpenFile3);
}
}
printf("The two files were successfully merged into %s\n", file3);
fclose(OpenFile);
fclose(OpenFile2);
fclose(OpenFile3);
return 0;
You need to alternate your fgetc calls, not do each loop all at once.
int file2_ok = 1, file_ok = 1;
while (file_ok && file2_ok) {
if (file2_ok) {
c = fgetc(OpenFile2);
if (c == EOF) {
file2_ok = 0;
} else {
fputc(c, OpenFile3);
}
}
if (file_ok) {
c = fgetc(OpenFile);
if (c == EOF) {
file_ok = 0;
} else {
fputc(c, OpenFile3);
}
}
}
This assumes that the two files have the same number of characters. The question doesn't indicate how they should be merged if they don't match up evenly.
This merges alternates lines of two text files. The input files and the output file are program arguments.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
FILE *OpenFile;
FILE *OpenFile2;
FILE *OpenFile3;
char buffer[10000]; // hopeful
int finished = 0;
if(argc < 4) {
exit(1);
}
OpenFile = fopen(argv[1], "rt"); // "t" is for MSVC
OpenFile2 = fopen(argv[2], "rt");
OpenFile3 = fopen(argv[3], "wt");
if(OpenFile == NULL || OpenFile2 == NULL || OpenFile3 == NULL) {
exit(1);
}
while(finished != 3) {
if(fgets(buffer, sizeof buffer, OpenFile) != NULL) {
fputs(buffer, OpenFile3);
}
else {
finished |= 1;
}
if(fgets(buffer, sizeof buffer, OpenFile2) != NULL) {
fputs(buffer, OpenFile3);
}
else {
finished |= 2;
}
}
fclose(OpenFile);
fclose(OpenFile2);
fclose(OpenFile3);
return 0;
}
Input file 1:
File 1 line 1
File 1 line 2
File 1 line 3
File 1 line 4
Input file 2:
File 2 line 1
File 2 line 2
Output file 3:
File 1 line 1
File 2 line 1
File 1 line 2
File 2 line 2
File 1 line 3
File 1 line 4
The solution could be more efficient if it took notice of the finished status instead of calling fgets after any file has reached EOF.
I've run into a problem solution to which I can't find.
I'm combining two text files into a third one and I want to keep track of the data I'm moving. So far, the code does one thing and absolutely ignores other.
Here is the code:
// enable standard c i/o functions
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Open two files to be merged
FILE *fp1 = fopen("test1.txt", "r");
FILE *fp2 = fopen("test2.txt", "r");
// Open file to store the result
FILE *fp3 = fopen("results.txt", "w+");
char c;
int count2ch = 0; // count meter for characters
int count1ch = 0; // count meter for characters
int totalch = 0; // holds number of total ammount of characters
int count1wd = 0; // count meter for words
int count2wd = 0; // count meter for words
int totalWD = 0;// holds total ammount of words
// Check files
if (fp1 == NULL || fp2 == NULL || fp3 == NULL)
{
puts("Could not open file");
exit(0);
}
// COUNTING CHARACTERS
// count characters file one
while (1)
{
c = fgetc(fp1);
if (c == EOF)
break;
count1ch++;
}
// count characters file two
while (1)
{
c = fgetc(fp2);
if (c == EOF)
break;
count2ch++;
}
//MERGING FILES
// Copy contents of first file to file3.txt
while ((c = fgetc(fp1)) != EOF)
fputc(c, fp3);
// Copy contents of second file to file3.txt
while ((c = fgetc(fp2)) != EOF)
fputc(c, fp3);
// COUNTING WORDS
//count words file one
while ((c = fgetc(fp1)) != EOF)
{
if (c == ' ')
count1wd++;
}
//count words file two
while ((c = fgetc(fp2)) != EOF)
{
if (c == ' ')
count2wd++;
}
// count total ammount of words
totalWD = count1wd + count2wd;
// count total ammount of characters
totalch = count1ch + count2ch;
printf("Merged file1.txt and file2.txt into file3.txt \n");
printf("Total number of characters moved: %d\n", totalch);
printf("The ammount of chars in your first file is : %d\n", count1ch);
printf("The ammount of chars in your second file is : %d\n", count2ch);
printf("Total number of words moved: %d\n", totalWD);
printf("The ammount of words in your fist file is : %d\n", count1wd);
printf("The ammount of words in your second file is : %d\n", count2wd);
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
Now, it just combines two files into the third one and that's it. If I move the counting words or characters section above the merging section, the code will do whatever comes first.
Here's your code refined. The only differences are simplified variable names, the print statements moved to a function, and most importantly, the addition of the rewind() function to rewind your file pointers after use. The formatting is also my style, so if you want to change that then feel free.
#include <stdio.h>
#include <stdlib.h>
void printCtrs(int, int, int, int, int, int);
void printCtrs(int ttlCh, int c1ch, int c2ch, int ttlWD, int c1wd, int c2wd){
printf("Merged file1.txt and file2.txt into file3.txt \n");
printf("Total number of characters moved: %d\n", ttlCh);
printf("The ammount of chars in your first file is : %d\n", c1ch);
printf("The ammount of chars in your second file is : %d\n", c2ch);
printf("Total number of words moved: %d\n", ttlWD);
printf("The ammount of words in your fist file is : %d\n", c1wd);
printf("The ammount of words in your second file is : %d\n", c2wd);
}
int main(){
// Open files for reading/writing
FILE *fp1, *fp2, *fp3;
fp1 = fopen("test1.txt", "r");
fp2 = fopen("test2.txt", "r");
fp3 = fopen("results.txt", "w+");
// Declaring counters
char c;
int ttlCh = 0, c1ch = 0, c2ch = 0,
ttlWD = 0, c1wd = 0, c2wd = 0;
// If any files fail to open, abort
if (fp1 == NULL){
puts("Could not open file fp1");
exit(0);
}
if (fp2 == NULL){
puts("Could not open file fp2");
exit(0);
}
if (fp3 == NULL){
puts("Could not open file fp3");
exit(0);
}
// Read through files 1 and 2 and count characters
while (c = fgetc(fp1) != EOF){ c1ch++; }
rewind(fp1); // Reset file pointer 1 to start of file
while (c = fgetc(fp2) != EOF){ c2ch++; }
rewind(fp2); // Reset file pointer 2 to start of file
// Write file 1 and 2 to 3
while ((c = fgetc(fp1)) != EOF){ fprintf(fp3, "%c", c); }
while ((c = fgetc(fp2)) != EOF){ fprintf(fp3, "%c", c); }
// Count total words in 1 and 2
while ((c = fgetc(fp1)) != EOF){
if (c == ' '){ c1wd++; }
}
while ((c = fgetc(fp2)) != EOF){
if (c == ' '){ c2wd++; }
}
ttlWD = c1wd + c2wd;
ttlCh = c1ch + c2ch;
// Print counters
printCtrs(ttlCh, c1ch, c2ch, ttlWD, c1wd, c2wd);
// Close all files after use
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
I have created a stock inventory program for a jewelry store.
However, I cannot seem to figure out how to search for a specific word in a file containing the items (in a table form) and delete the entire line which the word was on.
For example, I can delete earring from the list but not the quantity as well which would be a few spaces away on the same line.
#include <stdio.h>
int main() {
FILE *fp1, *fp2;
//consider 40 character string to store filename
char filename[40];
char c;
int del_line, temp = 1;
//asks user for file name
printf("Enter file name: ");
//receives file name from user and stores in 'filename'
scanf("%s", filename);
//open file in read mode
fp1 = fopen(filename, "r");
c = getc(fp1);
//until the last character of file is obtained
while (c != EOF) {
printf("%c", c);
//print current character and read next character
c = getc(fp1);
}
//rewind
rewind(fp1);
printf(" \n Enter line number of the line to be deleted:");
//accept number from user.
scanf("%d", &del_line);
//open new file in write mode
fp2 = fopen("copy.c", "w");
c = getc(fp1);
while (c != EOF) {
c = getc(fp1);
if (c == '\n')
temp++;
//except the line to be deleted
if (temp != del_line) {
//copy all lines in file copy.c
putc(c, fp2);
}
}
//close both the files.
fclose(fp1);
fclose(fp2);
//remove original file
remove(filename);
//rename the file copy.c to original name
rename("copy.c", filename);
printf("\n The contents of file after being modified are as follows:\n");
fp1 = fopen(filename, "r");
c = getc(fp1);
while (c != EOF) {
printf("%c", c);
c = getc(fp1);
}
fclose(fp1);
return 0;
}
Your code has several issues:
You read the filename with an unprotected call to scanf, if the name typed by the user exceeds 39 characters, you invoke undefined behavior. Make the buffer larger as filenames tend to be long nowadays and protect the format this way:
char filename[256];
if (scanf("%255s", filename) != 1) {
/* end of file reached, deal with this error */
...
}
Your method for reading a file byte by byte is incorrect: c should be defined as an int otherwise you cannot reliably detect EOF. The standard idiom for this is:
int c;
//until the last character of file is obtained
while ((c = getc(fp1)) != EOF) {
//print current character and read next character
putchar(c);
}
In the copy phase, you drop the first character of the file.
You ignore errors. Not only do you invoke undefined behavior, you may actually erase the file after failing to copy its contents.
You ask for a line number from the user, but you do not show the line numbers in the echo phase. Doing so would help.
Here is a improved version:
#include <stdio.h>
int main(void) {
FILE *fp1, *fp2;
//consider 255 character string to store filename
char filename[256];
int c, last, del_line, lineno;
//asks user for file name
printf("Enter file name: ");
//receives file name from user and stores in 'filename'
if (scanf("%255s", filename) != 1) {
perror("missing filename");
return 1;
}
//open file in read mode
fp1 = fopen(filename, "r");
if (fp1 == NULL) {
perror("cannot open file");
return 1;
}
//until the last character of file is obtained
last = '\n';
lineno = 0;
while ((c = getc(fp1)) != EOF) {
if (last == '\n') {
printf("%4d: ", ++lineno);
}
//print current character and read next character
putchar(c);
last = c;
}
rewind(fp1);
printf("\nEnter line number of the line to be deleted: ");
//accept number from user.
if (scanf("%d", &del_line) != 1) {
perror("missing line number");
return 1;
}
if (del_line < 1 || del_line > lineno) {
printf("no such line: %d\n", del_line);
return 1;
}
//open new file in write mode
fp2 = fopen("copy.c", "w");
if (fp2 == NULL) {
perror("cannot open copy.c");
return 1;
}
lineno = 1;
while ((c = getc(fp1)) != EOF) {
//except the line to be deleted
if (lineno != del_line) {
//copy all lines in file copy.c
putc(c, fp2);
}
if (c == '\n')
lineno++;
}
//close both files.
fclose(fp1);
if (fclose(fp2)) {
perror("write error to copy.c");
return 1;
}
// remove original file (unsafe)
// uncomment this if your system does not allow rename
// to overwrite existing files
// if (remove(filename)) {
// perror("cannot remove source file");
// return 1;
// }
//rename the file copy.c to original name
if (rename("copy.c", filename)) {
perror("cannot rename file");
return 1;
}
printf("\nThe contents of file after being modified are as follows:\n");
fp1 = fopen(filename, "r");
if (fp1 == NULL) {
perror("cannot re-open modified file");
return 1;
}
while ((c = getc(fp1)) != EOF) {
putchar(c);
}
fclose(fp1);
return 0;
}