I'm trying to convert the case from a file and write into another. The file I'm trying to convert has spaces and a few lines. The converted form is written with no spaces and no line breaks. Does anyone know how I can alter my code, so that it includes the spaces and line breaks from the original file?
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main(void)
{
FILE *fp1, *fp2;
fp1 = fopen("exercise2.txt", "r");
fp2 = fopen("exercise2_converted.txt", "w");
int singleline;
if (fp1 == NULL)
{
printf("Error opening fp1!\n");
return 0;
}
if (fp2 == NULL)
{
printf("Error opening fp2!\n");
fclose(fp1);
return 0;
}
do
{
singleline = fgetc(fp1);
if (islower(singleline))
{
singleline = toupper(singleline);
fputc(singleline, fp2);
}
else if (isupper(singleline))
{
singleline = tolower(singleline);
fputc(singleline, fp2);
}
} while (singleline != EOF);
fclose(fp1);
fclose(fp2);
return 0;
}
Overall beginner's solution:
...
do
{
singleline = fgetc(fp1);
if (singleline == EOF)
break; // end of file => game over quit loop immediately
// convert char if neessary
if (islower(singleline))
{
singleline = toupper(singleline);
}
else if (isupper(singleline))
{
singleline = tolower(singleline);
}
// output the char
fputc(singleline, fp2);
} while (1);
...
There are shorter solutions, but these are harder to read and to understand for beginners.
Related
int main()
{
char ch;
int word_count = 0, in_word = 0;
char file_name[MAX_LEN];
/* Pointer for both the file*/
FILE *fpr, *fpw;
/* Opening file INPUT.txt in “r” mode for reading */
start:
printf("Enter a file name: ");
scanf("%s", file_name);
fpr = fopen(file_name, "r");
/* Ensure INPUT.txt opened successfully*/
if (fpr == NULL)
{
system("cls");
printf("Could not open the file %s\n", file_name);
goto start;
}
while ((ch = fgetc(fpr)) != EOF) {
{
printf("%c",ch);
}
if(ch == ' ' || ch == '\t' || ch == '\0' || ch == '\n') {
if (in_word) {
in_word = 0;
word_count++;
}
} else {
in_word = 1;
}
}
printf("In the file %s:\n", file_name);
printf("Number of words: %d.\n", word_count);
/* Opening file OUTPUT.txt in “w” mode for writing*/
fpw= fopen("OUTPUT.txt", "w");
/* Ensure OUTPUT.txt opened successfully*/
if (fpw == NULL)
{
puts("Output file cannot be opened");
}
/*Read & Write Logic*/
while ((ch = fgetc(fpr)) != EOF)
{
fputc(ch, fpw);
}
/* Closing both the files */
fclose(fpr);
fclose(fpw);
return 0;
}
Why is it not printing in the output.txt file? And how can I also print the words in the output file?
There must be a conflict between the while function before printing the input. Or maybe there is something reading before the output then having conflict with another one, when I remove the while function (count words) it shows the product in the output.
You read from fpr until you reach EOF, then try to read from it again.
You need to rewind the file to the beginning for the second fgetc() loop to produce anything.
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;
}
I am trying to read from files and write to a temp file. However, I am stuck in an infinite loop right now. The function below is called multiple times by a recursive function that goes through directories to read files.
My approach is that I would read each word from one file, then those words to another file.
The function I have works fine if I just print out each word. It prints out each word in each file in all directories. However, when I try to start writing to a temp file (the code commented out), I am stuck in the while loop.
On the other hand, if I just call the function once in a test program where I just read from one file in the current directory, and write to a temp file, it's fine.
This is what I have (fileName when passed in is actually the absolute path, and I do ../tmp so it does not get caught in the recursion function):
void fileReadWrite(char *pattern, char *before, char *replace, char *fileName) {
FILE *file = fopen(fileName, "r");
if (file != NULL) {
int ch, word = 0;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch) || ispunct(ch)) {
if (word) {
word = 0;
putchar('\n');
}
}
else {
word = 1;
putchar(ch);
/*
FILE *f = fopen("../tmp", "wb"); // create and write
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Some text"); // Or fprintf(f, ch);
fclose(f);
*/
}
}
fclose(file);
}
}
There's nothing in your code that suggests an infinite loop. However, if fileName is very large, you could be opening and closing "..\tmp" millions of times. As Joachim Pileborg points out in the comments, you should open that file just once at the beginning of your function, and close it again at the end.
If you want to convince yourself that you are not in an infinite loop, print out the value of ch on each iteration.
Okay so I did this and it worked. But I don't understand why though. Can someone explain it please?
void fileReadWrite(char *pattern, char *before, char *replace, char *fileName) {
FILE *file = fopen(fileName, "r");
FILE *f = fopen("../tmp", "wb"); // MOVE HERE
if (file != NULL) {
int ch, word = 0;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch) || ispunct(ch)) {
if (word) {
word = 0;
putchar('\n');
}
}
else {
word = 1;
putchar(ch);
/*
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Some text"); // Or fprintf(f, ch);
*/
}
}
fclose(file);
fclose(f); // MOVE HERE
}
}
void main()
{
FILE *fp1;
char ch;
int count = 0;
fp1 = fopen("Text.txt","r");
if(fp1==NULL){
printf("Failed to open file. Bye\n");
exit(1);
}
printf("Text file exists");
fclose(fp1);
}
example of an input file(Text.txt)-
3
nameA
nameB
nameC
I would like to check if the very first character of this input file is a number. If its missing a number than program will stop
Include ctype.h and then there are functions that do type checks. Alternatively check if the value of the char is in the appropriate ASCII range.
This would solve your problem
void main()
{
FILE *fp1;
char ch;
int count = 0;
fp1 = fopen("Text.txt","r");
if(fp1==NULL){
printf("Failed to open file. Bye\n");
exit(1);
}
printf("Text file exists");
ch = fgetc(fp1);
if (ch < '0' || ch > '9') {
fclose(fp1);
printf("Exit: First character is not a number\n");
return; // first character of the input file is not number so exit
}
fclose(fp1);
}
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fp1;
char ch, line[128];
int count = 0, num;
fp1 = fopen("Text.txt","r");
if(fp1==NULL){
printf("Failed to open file. Bye\n");
exit(1);
}
printf("Text file exists\n");
if(fgets(line, sizeof(line), fp1)){
if(1==sscanf(line, "%d", &num)){
while(num-- && fgets(line, sizeof(line), fp1)){
printf("%s", line);
}
} else {
printf("The beginning of the file is not numeric. Bye\n");
exit(1);
}
} else {
printf("No contents of the file. Bye\n");
exit(1);
}
fclose(fp1);
return 0;
}
I wrote the following code to copy the text file to another:
FILE *fpr, *fpw;
int ch;
fpr = fopen("M.txt","r");
fpw = fopen("P.txt","w");
if(fpr == NULL)
printf("File open failed!");
else
{
while(1)
{
ch = fgetc(fpr);
if(ch == EOF)
break;
fputc(ch, fpw);
}
fclose(fpr);
fclose(fpw);
printf("Successfully copied!");
}
It worked perfectly. Then I changed int ch to char ch it also worked for me. But when i used the following code for copying a .exe file, file copying is not working correctly.
FILE *fpr, *fpw;
char ch;
fpr = fopen("M.exe","rb");
fpw = fopen("P.exe","wb");
if(fpr == NULL)
printf("File open failed!");
else
{
while(1)
{
ch = fgetc(fpr);
if(ch == EOF)
break;
fputc(ch, fpw);
}
fclose(fpr);
fclose(fpw);
printf("Successfully copied!");
}
I changed char ch to int ch then it's working fine! Why this happens with binary files not with text file? What happens when char ch was used in the case of binary?
Please help...
Thank you for your feed back in advance.
It's because EOF is probably 0 or 255 for char which can show up in middle of binary file but can't in text file(that's why only text file work for char). However EOF is -1 for int which can't show up in middle of a file no matter what(only 0-255 inclusive can).
Since fgetc() can return the integer corresponding to any character plus a distinct value EOF, you cannot store its result in a char and then test for EOF reliably. You must use an int as you did originally.
fgetc() and fputc() are designed for handling textual data, not binary data. Use fread() and fwrite() instead.
FILE *fpr, *fpw;
unsigned char b[1024];
bool ok = false;
fpr = fopen("M.exe","rb");
if (fpr == NULL)
printf("File open M.exe failed!");
else
{
fpw = fopen("P.exe","wb");
if (fpw == NULL)
printf("File open P.exe failed!");
else
{
int read;
while(1)
{
read = fread(b, 1, 1024, fpr);
if (read < 1)
{
if (read == 0)
ok = true;
break;
}
if (fwrite(b, read, 1, fpw) != 1)
break;
}
fclose(fpw);
}
fclose(fpr);
}
if (ok)
printf("Successfully copied!");