I want to copy my in file on to my out file. - c

In this code I opened my files in my open_file function. Then the process_file function needs to copy the text from my in file and Copy it to an out file. Right now it produces a new file but it is blank. It does not give me any error messages. I do not know what is wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LEN 100
FILE* open_file(char prompt[], char mode[]);
FILE* process_file(FILE* in, FILE* out);
int main(int argc, const char * argv[]) {
FILE* in = NULL;
FILE* out = NULL;
printf("MAD-LIBS Text Processor\n");
printf("The Program will open a mad-libs file, ask you to fill various words, and produce a funny story.\n");
open_file("Enter mad-lib file name:\n", "r");
open_file("Enter file name for resulting story:\n", "w");
process_file(in, out);
fclose(in);
fclose(out);
return 0;
}
/* open_file = prompts user for file name & and attempts to open it, if it fails it prompts the user again. */
FILE* open_file(char prompt [], char mode[]) {
char filename[255];
FILE* in;
do {
printf("%s", prompt);
scanf("%s", filename);
in = fopen(filename, mode);
if (in == NULL) {
printf("Unable to open file: %s. Try Again!\n", filename);
}
} while(in == NULL);
return in;
}
/* process_file = processes entire input file and writes it to output file */
FILE* process_file(FILE* in, FILE* out) {
char content[MAX_LEN];
char NewContent[MAX_LEN];
//gets whats in file in
while(fgets(content, content[MAX_LEN], in) != NULL) {
fputs (content, stdout);
strcat(NewContent, content);
}
// copies it
while (fgets(content, content[MAX_LEN], in) != NULL) {
fprintf(out, "%s", content);
}
printf("Successfully copied file\n");
return in;
}

You never assign the FILE* from open_file function to your variable, so it never gets processed.
in = open_file("Enter mad-lib file name:\n", "r");
out = open_file("Enter file name for resulting story:\n", "w");

You are not storing the FILE pointers that open_file is returning, so in
and out remain uninitialized.
You have to do:
in = open_file("Enter mad-lib file name:\n", "r");
out = open_file("Enter file name for resulting story:\n", "w");
process_file(in, out);
Also your process_file is wrong. NewContent is not initialized, when you do
strcat(NewContent, content);
this yields undefined behaviour. Declare NewContent like this:
char NewContent[MAX_LEN] = { 0 };
so that it is properly \0-terminated.
Also depending on the size of the file you are copying, MAX_LEN might not be
long enough to hold the whole file. In that case you would overflow the buffer.
It would be better not to use NewContent in the first place and write to out
in the same reading loop:
FILE* process_file(FILE* in, FILE* out) {
char content[MAX_LEN];
//gets whats in file in
while(fgets(content, MAX_LEN, in) != NULL) { //<- your fgets was wrong
fputs (content, stdout);
fprintf(out, "%s", content); // or fputs(content, out);
}
printf("Successfully copied file\n");
return in;
}
And you were calling fgets incorrectly (look at my corrected code)
Also bear in mind, that you did have 2 loop doing while(fgets(...) != NULL.
Well, the first loop ends, that's because fgets returns NULL, most likely
because the whole file was read or there was an I/O error. In either case
subsequent calls of fgets will return NULL as well, so your second loop
would not even be executed at all.

Related

fprint doesn't work in loop

I am trying to repeatedly read a string from the command line and print it to a file. This is my code:
int main ()
{
FILE* fp=fopen("test.txt","w");
char* tofile[10];
while(1){
printf("cat: ");
scanf("%s",tofile);
fprintf(fp,"%s\n",tofile);
}
return 0;
}
It works just fine outside the loop. But inside, it just doesn't print.
The fprintf function returns the correct amount of characters it has to print.
Note: I know there's a similar question out there, but it hasn't been answered yet, and I hope my code can help in this matter since it's simpler.
Well first it doesn't seem that what you want is reading on the command line.
The command line what you write right when you execute your program such as:
./main things that are on the command line
What it seems you want to do is to read on the standard input.
What you should consider is to use the fgets function, as it has a limit of characters to be read, so that you can store them "safely" into a buffer, like your tofile.
As you want to read on the standard input you can use the stdin stream (which is a FILE* that is automatically created for every program)
The line goes
fgets(tofile, 10, stdin);
Your loop becoming :
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
meaning: as long as we can read on the standard input, print "cat :" and store what we just read in the file controlled by the stream pointer fp.
Some important stuff
When you try to open a stream it may fail and you should test it:
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
Right before exiting your main, you should also close the file and check if it has succeeded, like that for example:
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
The whole thing becomes:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
char tofile[10];
printf("cat: ");
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Improvements
I don't know if it is just a little program or it aspires to become a greater program.
In the last case you should consider using defines and not a magical number such as
#define BUFFER_MAX_SIZE 10
char tofile[BUFFER_MAX_SIZE];
while (fgets(tofile, BUFFER_MAX_SIZE, stdin) != NULL) { ... }
This helps for readability and makes the program less apt to debug when modifying such a size. Because with the define all the part of the code needing the size will still be fully functional without modifying them.
Please also keep in mind that your tofile acts as a buffer, and it's really a small buffer that can easily be overflowed.
This will work. fgets() returns the string it reads from the specified file pointer. If this string returns only a newline ("\n"), that means nothing was entered at stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
Edited code.

Weird input from a file using fscanf()

My main objective here is to make use of fscanf() to take in each word from my file and store it into an array location. As it stands, I loop through the file setting each word to a location in wordList[]. I can print out the values as they are put into the array and each seems to be placed correctly. But after the loop, when I attempt to print only one of the values (simply checking that everything went as it should) I get a weird output. When printing the string contained in wordList[5], it prints the first character of every word after location [5], and prints the last word that was collected.
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readFile (FILE *fPtr, char *fileName) {
FILE *newFilePtr;
char wordList[1000];
int i = 0;
newFilePtr = fopen(strcat(fileName, ".out"), "w"); // Blank document created under same file name, but with ".out"
while(fscanf(fPtr, "%s", &wordList[i]) == 1) { // Read in strings from main file into wordList
printf("%s\n", &wordList[i]);
++i;
if (i > 10) // KEEP OUTPUT SHORT FOR STACK OVERFLOW QUESTION
break;
}
printf("%s\n", &wordList[5]); // PRINTS WILD VALUE AT POSITION 5
fclose(newFilePtr);
}
int main (int argc, char *argv[]) {
int lineSize;
char *fileName = argv[2]; // Store name of file for future operations
FILE *fPtr;
if (argc != 3) {
fprintf(stderr, "%s", "ERROR: Incorrect arguments. Please input a line size and a file.\n");
return;
}
lineSize = atol(argv[1]); // Convert string to it's integer equivalent
if (lineSize < 25 || lineSize > 100) {
fprintf(stderr, "%s", "ERROR: Line size not within range.\n");
return;
}
if (fPtr = fopen(fileName, "r")) { // If the file exists, open it for reading
readFile(fPtr, fileName);
puts("FILE OPENED SUCCESS");
fclose(fPtr);
} else {
fprintf(stderr, "%s", "ERROR: File could not be opened.\n");
return;
}
return;
}
And my current output (constrained to just the first 10 values to keep it short):
Mason–Dixon
Line
(or
Mason
and
Dixon's
Line)
was
surveyed
between
1763
DLwsb1763 // Should print "Dixon's" (the string at location 5)
FILE OPENED SUCCESS
The creation of the new file at line 11 is for later use when the file is formatted. For now, i'm only concerned with properly scanning in the values from the original file.

Check duplicates words in a file

I want to check if there are any duplicates in a .txt file. I've wrote a code but it's not running. I'm not sure about opening the norep.txt file in "a+" mode. The idea is to put the first word of my text in the norep.txt file, then compare every word in the text.txt with the words in norep.txt and copy only the words I need in the file.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fd;
FILE *ft;
char aux[30];
char aux1[30];
int len;
fd = fopen("c:\\text.txt", "r");
if (fd == NULL) {
puts("Error");
}
ft = fopen("c:\\norep.txt", "a+");
if (ft == NULL) {
puts("Error");
}
fscanf(fd, "%s", aux);
fprintf(ft, "%s", aux);
rewind(fd);
rewind(ft);
while (!feof(fd)) {
fscanf(fd, "%s", aux);
while (!feof(ft)) {
fscanf(ft, "%s", aux1);
len = strcmp(aux, aux1);
if (len != 0) {
fprintf(ft, "%s", aux);
}
}
rewind(ft);
}
return 0;
}
You should flush the output file before you rewind it.
fflush - flush a stream or fflush
Of course, this will not fix your problem because:
Note below that the manual says that reposition operations are ignored so that your attempt to read will always find the end of file.
append: Open file for output at the end of a file. Output operations
always write data at the end of the file, expanding it. Repositioning
operations (fseek, fsetpos, rewind) are ignored. The file is created
if it does not exist.
What you should probably do is create an internal memory table that keeps all the unique entries and write it out to a new file after all processing is done. As you read the fd file, check the list and add a new entry if it is not already in the list. Then after you have finished processing fd, then and only then write out your list. Of course, this may be too big depending on the size of your data file.
You could append each unique entry to the output file as you go. but you would need to have some method of checking the previous entries without trying to read the output file.
The usual way to go about this is to read the input file word for word, store the necessary information in some way and then, after you have read all information from the file, write the desired output to the output file.
A rough skeleton of that approach might look like this:
int main()
{
const char *infile = "text.txt";
const char *outfile = "norep.txt";
FILE *in;
FILE *out;
char word[30];
// (1) Read all words
in = fopen(infile, "r"); // .. and enforce success
while (fscanf(in, "%29s", word) == 1) {
// store word somewhere
}
fclose(in);
// (2) Determine unique words somehow
// (3) Write out unique words
out = fopen(outfile, "w"); // .. and enforce success
for (i = 0; i < nunique; i++) {
fprintf(out, "%s\n", unique[i]);
}
fclose(out);
return 0;
}
The actual algorithm to fin the unique words is missing from this incomplete skeleton code.
If you really want to test the words in a file for uniqueness without using additional memory beyond the current word, you can open the input file twice, with independent file pointers. Then you can write a loop like so:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
const char *infile = "text.txt";
const char *outfile = "norep.txt";
FILE *in1;
FILE *in2;
FILE *out;
char word1[30];
char word2[30];
in1 = fopen(infile, "r");
in2 = fopen(infile, "r");
out = fopen(outfile, "w");
if (in1 == NULL || in2 == NULL || out == NULL) {
fprintf(stderr, "Could not open all required files.\n");
exit(1);
}
while (fscanf(in1, "%29s", word1) == 1) {
int count = 0;
while (fscanf(in2, "%29s", word2) == 1) {
if (strcmp(word1, word2) == 0) count++;
if (count > 1) break;
}
if (count == 1) fprintf(out, "%s\n", word1);
rewind(in2);
}
fclose(in1);
fclose(in2);
fclose(out);
return 0;
}
This will, of course, re-read the file as often as there are words in the file. Not a good approach to find the unique words in Moby-Dick. I recommend that you look into the memory-based approach.

Resetting pointer to the start of file

How would I be able to reset a pointer to the start of a commandline input or file. For example my function is reading in a line from a file and prints it out using getchar()
while((c=getchar())!=EOF)
{
key[i++]=c;
if(c == '\n' )
{
key[i-1] = '\0'
printf("%s",key);
}
}
After running this, the pointer is pointing to EOF im assuming? How would I get it to point to the start of the file again/or even re read the input file
im entering it as (./function < inputs.txt)
If you have a FILE* other than stdin, you can use:
rewind(fptr);
or
fseek(fptr, 0, SEEK_SET);
to reset the pointer to the start of the file.
You cannot do that for stdin.
If you need to be able to reset the pointer, pass the file as an argument to the program and use fopen to open the file and read its contents.
int main(int argc, char** argv)
{
int c;
FILE* fptr;
if ( argc < 2 )
{
fprintf(stderr, "Usage: program filename\n");
return EXIT_FAILURE;
}
fptr = fopen(argv[1], "r");
if ( fptr == NULL )
{
fprintf(stderr, "Unable to open file %s\n", argv[1]);
return EXIT_FAILURE;
}
while((c=fgetc(fptr))!=EOF)
{
// Process the input
// ....
}
// Move the file pointer to the start.
fseek(fptr, 0, SEEK_SET);
// Read the contents of the file again.
// ...
fclose(fptr);
return EXIT_SUCCESS;
}
Piped / redirected input doesn't work like that. Your options are:
Read the input into an internal buffer (which you already seem to be doing); or
Pass the file name as a command-line argument instead, and do with it as you please.

fprintf() on a new line of a file

How i can make a new line at the end of a file to fprintf() user inputed text?
My code right now is this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int lines;
int number;
FILE *fp;
printf("Insert random number: ");
scanf("%d", &number);
fp = fopen("textfile.txt", "r");
char ch;
while((ch=fgetc(fp))!=EOF)
{
if (ch=='\n') {
lines++;
}
}
fclose(fp);
fopen("textfile.txt", "ab");
fseek(fp, lines, SEEK_SET);
fprintf(fp,"%d", number);
fclose(fp);
}
You just need to add a '\n' to the fprintf() like this
fprintf(fp,"\n%d", number)
/* ^ */
but you also need a lot of error checking, for instance fopen() returns NULL when it fails to open the file.
Your code is actually very broken, you count the lines in the file opened with "r", i.e. for reading, then you call fopen() with "ab" but discard the return value, you then fseek() the number of lines, and fseek() is for the number of characters not lines, then you write to the closed fp pointer, because
fopen("textfile.txt", "ab"); /* you don't assign the return value anywhere */
fseek(fp, lines, SEEK_SET); /* this is the same pointer you `fclosed()' */
/* ^ this will not seek to the end of the file */
fprintf(fp,"%d", number); /* here `fp' is still invalid */
Test this
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file;
const char *filename = "textfile.txt";
printf("Insert a number: ");
if (scanf("%d", &number) != 1)
{
fpritnf(stderr, "invalid input, expected a number\n");
return -1;
}
file = fopen(filename, "a");
if (file == NULL)
{
fprintf(stderr, "cannot open %s for appending\n", filename);
return -1;
}
fprintf(file, "\n%d", number);
fclose(file);
return 0;
}
You don't need to fseek() if you open with "a" because new content is appended to the end of the file, you need a '\n' before the user input if there was no '\n' in the file or if you want to force the new value in a new line.
You don't need the "b" in the mode string, because you are writing text to the file, and on some platforms the file will have issues when you open it in a text editor.

Resources