I need to write a program that asks the user to enter strings, each string ends when the user presses 'Enter'.
The program needs to receive the file name as a parameter, the file should be opened and closed for each operation and for every string entered, the program should append the string to the end of the file (on a new line).
This is my code so far:
int is_file_exists(char *file_name)
{
FILE *file;
if ((file = fopen(file_name,"r"))!=NULL)
{
/* file exists */
fclose(file);
return 1;
}
else
{
//File not found, no memory leak since 'file' == NULL
//fclose(file) would cause an error
return 0;
}
}
int main(int argc, char **argv)
{
char c;
FILE *file;
if (argc >= 2)
{
if (is_file_exists(argv[1]))
{
file = fopen(argv[1], "w");
}
else
{
return 0;
}
}
else
{
file = fopen("file.txt", "w");
}
while ((c = getchar()) != EOF)
{
putc(c, file);
}
return 0;
}
So far the code compiles and file is being created, but nothing is being written inside of it.
Edit: I also need some function pointers, see my comments on selected answer
I think one of the problem was that you were opening and closing a file, and then reopening it subsequently. It is better to just leave it open using a pointer while simultaneously testing that there were no issue to open the file. Another problem was that you were writing in the file, don't you prefer to append text to it? Well it's your decision. As for the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // exit
typedef struct mystruct {
char *exit_word;
void (*exit_fptr)(int); // man exit
int (*strcmp_fptr)(const char *, const char*); // man strcmp
} t_mystruct;
int is_file_exists(char *filename, FILE **file)
{
return (*file = fopen(filename,"a")) > 0;
}
#define BUFF_SIZE 1024
int main(int argc, char **argv)
{
char c;
FILE *file;
t_mystruct s = {.exit_word = "-exit", .exit_fptr = &exit, .strcmp_fptr = &strcmp};
if (argc >= 2) {
if (!(is_file_exists(argv[1], &file)))
return 0;
}
else
file = fopen("file.txt", "a"); // open the file in append mode
char buffer[BUFF_SIZE];
while (42) {
int i = 0;
memset(buffer, 0, BUFF_SIZE);
while ((c = getchar()) != '\n')
buffer[i++] = c;
if (!s.strcmp_fptr(buffer,s.exit_word)) {// exit if user type exit, allow you to fclose the file
fclose(file);
s.exit_fptr(EXIT_SUCCESS); // better to use the define
}
buffer[i] = '\n';
fputs(buffer, file);
}
fclose(file);
return 0;
}
your code can work
remember to press Ctrl+d when finished input. the file will have the content your expected
your code wait for EOF to quit the loop. Ctrl+d is a way to input EOF, or else the program never ends.
putc will write to cache at first, then write to disk. this an optimization mechanism of File System. you can choose to avoid this by DirectIO when open file.
when program terminate normally, file will be closed automatically, then data in cache will be copy to disk;
but when program terminated abnormally, data in cache might be lost.
file should be closed
fclose is needed.
open and close should be organized in pair just as malloc and free.
Related
For example I have a text file includes "I'm having great day!", I want to count each character and word in this file.
in the example "there are 3 a, 1 m" etc.
I'm new at C and know how to open a file, how can find a specific char or word in file but couldn't figure this out. Can you help me pls.
The first thing you need to learn is how to open and process a file one character at a time. You can do this with a program like:
#include <stdio.h>
int main(int argc, char *argv[]) {
// Must provide one argument, the file to process.
if (argc != 2) {
fprintf(stderr, "Usage: myprog <inputFileName>\n");
return 1;
}
// Try to open the file.
FILE *inFile = fopen(argv[1], "r");
if (inFile == NULL) {
fprintf(stderr, "Cannot open '%s'\n", argv[1]);
return 1;
}
// Process file, character by character, until finished.
int ch;
while ((ch = fgetc(inFile)) != EOF) {
putchar(ch); // <accumulate>
}
// Close file and exit.
fclose(inFile);
// <output>
return 0;
}
Then it's a matter of changing the putchar call into whatever you need to do (accumulating character counts) and outputting that information before you exit from the main function.
Full Edit:
I am getting frustrated, I don't know what am I doing wrong in here
I still have so many stuff to do in the code but I can't even open a file to continue my work.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
char letter;
FILE *fp;
fp=fopen("C:\\Users\\LENOVO\\Desktop\\data.txt","r");
if(fp==NULL)
{
printf("error");
getch();
exit(1);
}
while(fscanf(fp,"%d",&letter)!=EOF)
putchar(letter);
getch();
fclose(fp);
}
Picture of the path: http://imgur.com/a/YwFYy
Still prints error
Ok, firstly let's take a look at your file path. There are two ways to acces a file from your local storage:
relative addresses if the file has the same root folder as your application
absolute addresses if the file is in a determined place on your machine's storage
I see that you are trying to use an absolute address to read from your file. Your path is correct but you have to take care about string formatting in C because the \ character could be interpreted as something else.
I would suggest to use this instead ( double back-slash )
input=fopen("C:\\Users\\LENOVO\\Desktop\\data.txt","r");
This will prevent string formatting interpretations.
Secondly, EOF is just a predefined macro constant and i think it is equal to -1 so your while(! (-1) ) code is not a good ideea for reading until the end of the file.
In order to read from a file until you reach the its end i would consider this property of fscanf() :
fscanf() returns EOF when it reaches the end of the file.
while(fscanf(input,"%ch",&letter) != EOF) {
putchar(letter);
}
This way of reading from a file should do the job.
To read everything from a text file and store its contents into a buffer:
First, you should count how many characters there are in the text file:
size_t get_file_len(FILE *fp)
{
size_t num = 0;
while (fgetc(fp) != EOF)
num++;
return (fseek(fp, 0, SEEK_SET) == 0 ? num : 0);
}
Then allocate memory for a buffer large enough and read all the characters:
char *load_text(const char *path)
{
char *buf = NULL;
FILE *fp = NULL;
size_t num = 0;
size_t i = 0;
int c = 0;
/* open the file in text mode */
fp = fopen(path, "r");
if (!fp)
return NULL;
/* if the file was empty or if an error occurred, return error */
if ((num = get_file_len(fp)) == 0) {
fclose(fp);
return NULL;
}
buf = malloc(num + 1);
if (!buf) {
fclose(fp);
return NULL;
}
while ((c = fgetc(fp)) != EOF)
buf[i++] = (char)c;
/* ensure that the string is null-terminated */
buf[i] = '\0';
fclose(fp);
return buf;
}
Also, in C, all escape sequences begin with a '\' (backslash), so if you wanted to write a backslash in a string or a char you should write it as a '\\' (double backslash):
input=fopen("C:\\Users\\LENOVO\\Desktop\\data.txt","r");
pretty simple here :
while(!feof(input)){
fscanf(input,"%c",&letter);
putchar(letter);
}
and remember to close file using fclose(input);
I have to write a program witch reads from a file received by line and then it overwrites it with the read words uppercased.
This is my code
void toUpperCase(char* string) {
int i=0;
while(string[i])
{
string[i]=toupper(string[i]);
i++;
} }
int main(int argc, char** argv) {
if(argc==1)
{
puts("Error: INSERT PATH");
exit(0);
}
char* file=argv[1];
FILE* fd=fopen(file,"r+");
if(fd<0)
{
perror("Error opening file: ");
exit(0);
}
char buffer[30][30];
int i=0;
while(!feof(fd))
{
fscanf(fd,"%s",buffer[i]);
i++;
}
int j=0;
for(j=0; j<i; j++)
{
toUpperCase(buffer[j]);
fwrite(buffer[j],strlen(buffer[j]),1,fd);
}
fclose(fd);
return 0; }
but this program appends the words contained in buffer[][] instead of overwriting the file.
If the file contain was something like pippo pluto foo then, after the execution is pippo pluto fooPIPPOPLUTOFOO instead of PIPPO PLUTO FOO.
Where am i wrong? Thank you
You have to reset the file position indicator using fseek, as fscanf will advance it. Something like
fseek(fd, length_of_read_string, SEEK_CUR);
This allows you to read the file in chunks, but it will be tricky to get right. Or of course reset it to the file start because you read everything in 1 go:
fseek(fd, 0L, SEEK_SET);
I strongly recommend writing the modified data into a new file, and then after the program has run, delete the initial file and rename the new one. That will also take care of another issue with your program, you are reading the entire file into memory before handling it.
If you want to do in-place translation that doesn't change lengths, you can open the source file in two streams and then do read-chunk, write-chunk in lockstep. That has the advantage of being super-easy to convert to a non-in-place version that will work with nonseekable files too (stdin/stdout, pipes, and sockets).
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h> //toupper
inline void upcaseStr(char* str){
for(;*str;str++) { *str=toupper(*str); }
}
int upcaseStream(FILE* in, FILE* out){
char buf[BUFSIZ]; //BUFSIZ is an implementation-defined constant for an optimal buffer size
while(fgets(buf, BUFSIZ, in)){
upcaseStr(buf);
if(fputs(buf, out) == EOF){ return 1; }
}
if(!feof){ return 1; }
return 0;
}
int main(int argc, char **argv)
{
//default in and out
FILE* in = stdin;
FILE* out = stdout;
if(argc == 2) {
in = fopen(argv[1], "r"); //for reading
out = fopen(argv[1], "r+"); //for writing (and reading) starting at the beginning
if(!(in && out)){
fprintf(stderr, "Error opening file %s for reading and writing: %s\n", argv[1], strerror(errno));
}
}
return upcaseStream(in, out);
}
If you do use the in-place version, then in the unlikely event that the if(fputs(buf, out) == EOF){ return 1; } line should return, you're screwed unless you have a backup copy of the file. :)
Note:
You shouldn't name your FILE pointers fd because C people will tend to think you mean "file descriptor". FILE is a struct around a file descriptor. A file descriptor is just an int that you can use for FILE access with the raw system calls. FILE streams are an abstraction layer on top of file descriptors--they aren't file descriptors.
As you read from the file, its internal position indicator gets moved. Once you start writing, you start writing from that position on, which happens to be at the end of the file. So you effectively append the data to the file.
Rewind the handle to reset the position indicator before writing into the file:
rewind(fp);
On a side note, you are reading the file incorrectly:
while(!feof(fd))
{
fscanf(fd,"%s",buffer[i]);
i++;
}
When you reach the end of the file, fscanf will return an error and not read anything, yet you still increment variable i, as if the read was successful. And then you check feof() for end-of-file, but i was already incremented.
Check feof() and return of fscanf() immediately after calling fscanf():
while(1)
{
int read = fscanf(fd,"%s",buffer[i]);
if( read != 1 )
//handle invalid read
if( feof(fd) )
break;
i++;
}
Think about what happens if the string is longer than 29 characters and/or the file contains more than 30 strings. char buffer[30][30];
Welcome to StackOverflow!
Reopening the stream with fopen with the "w" parameter:
fd=fopen(file, "w");
It opens the file and if there are any contents in the file, it clears them.
I am trying to open a .txt file and put its contents in the standard input. I know you can do:
myapp < input.txt
but i want to use the same content several times inside the program and i think that with this method the stdin content is consumed and can not be used again.
I want to test a function that reads from stdin, just as an example of what i am trying:
void myFunction(int number)
{
// The function already writen reads from stdin using the argument.
}
void fillStdin(void)
{
FILE* myFile;
myFile = fopen("myfile.txt", "r");
// Put the content of the file in stdin
fclose(myFile);
}
int main(void)
{
int myArray[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
{
fillStdin();
myFunction(myArray[i]);
}
return 0;
}
No need to modify your code. Just execute your program as this (assuming you are using Unix):
while true; do cat input.txt; done | myapp
This will feed input.txt to your stdin over and over again. Take into account that you will need to figure out when you have reached the end of each recurrence, as stdin will never EOF this way.
you can easily write into stdin like so:
char *buffer = malloc(bufsize * sizeof(char));
... //get file contents etc.
write(STDIN_FILENO, buffer, bufsize); //the important part.
you'll need to include unistd.h and I don't think it's portable.
Here is a simple example of how you can read stdin into a storage buffer, and into a file.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define MAXLINELENGTH 4096
FILE *fin;
char fileName[] = "temp.txt";
void processLine(char *line)
{
fin = fopen(fileName, "a");
fputs(line, stdout);
fputs(line, fin);
fclose(fin);
return;
}
int main()
{
char line[1024];
char input[MAXLINELENGTH];
printf("enter continuous text, and ~ when finished\n");
while (fgets(line, 1024, stdin) != NULL)
{
processLine(line);
if(strstr(line, "~")) //enter a "~" to exit program
return 0;
}
return 0;
}
Once you have the file, you can read from it using fopen() and fgets(), then write it back out to stdout.
I am new to C and I am encountering a problem with stdin I cannot find a solution to. My program either reads from file(s) or reads from stdin if no arguments (files) are provided by the user.
If the user doesn't supply any arguments then it will automatically read from stdin. My program is supposed to take in input (from file or stdin) and then remove the blank lines from it.
My problem arises when the program reads from stdin. Every time the user types something then presses enter the program automatically out puts the results. When I'd prefer enter to just be a newline.
How can I make it so the program waits for the user to hit EOF instead of each enter?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHARS 1024
int main(int argc, char** argv){
int good_file = 0;
if (argc <= 1) {
good_file++;
test(stdin);
}
FILE* files[argc - 1];
int i;
for (i = 0; i < argc - 1; i++) {
if ((files[i] = fopen(argv[i + 1], "r")) == NULL) {
continue;
} else {
good_file++;
test(files[i]);
}
}
if (!good_file) {
fprintf(stderr, "ERROR!\n");
}
}
int test(FILE *file) {
char buffer[NUMCHARS];
while (fgets(buffer, NUMCHARS, file) != NULL)
part2(buffer);
fclose(file);
}
int part2(char *buffer) {
if (!is_all_white(buffer)) {
fputs(buffer, stdout);
}
}
int is_all_white(char *s) {
while (*s) {
if (!('\n' == *s || '\t' == *s || ' ' == *s))
return 0;
s += 1;
}
return 1;
}
I appreciate any feedback!
It isn't an issue with stdin per se - if you want to wait to output your data, you will have to store it. You could write it to a file and read it back afterward. You could use malloc and realloc to store the data in memory. Mainly, if you don't want the data to output on every line, you need not to output it on every line.
Pre process stdin into a temp work file, this will then give you the control you require.
Use function mkstemp.
Be warned stdin is a pipe, where as the fopen files are probably disk files