in the code below:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
FILE *fp ;
fp = fopen("out.txt", "r+");
int count = 1;
char ch ;
char userInput[5] ;
int lineNumber = 0;
while (lineNumber!= -1){
fgets(userInput, sizeof(userInput), stdin);
lineNumber = atoi(userInput);
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n') //counts number of lines
count++;
if(count == lineNumber)
{
fprintf(fp, "writed %d\n", count);
fseek(fp, 0, SEEK_SET);
}
}
}
return 0;
}
I want to write a string in the line which the user gives me,i store the user answer in userInputand then convert it to the int and store it in lineNumber.
when i try to write fore example in line 90 (my file has 100 lines) two error i get:
1.the file reduce to a 91-line file (instate of remain 100 lines)
2.although i seek to first of file,no more lines written in the next loops and user inputs.
Reading a file (to count its lines) and then turning around and writing to it is tricky. Among other things, you have to do something like an fseek between the reading and the writing. So try interchanging the order of the fseek and fprintf calls:
fseek(fp, 0, SEEK_SET);
fprintf(fp, "writed %d\n", count);
Also, be aware that unless the new text you're writing ("writed ###") is exactly the same length as whatever line used to be there, the line structure of the remainder of the file is likely to get garbled.
See also this question in the C FAQ list.
Related
I want to write a program in C which just reads a file, stores it into an array and then prints the array. Everything works fine but when the text file has more than one line, I always just get the last line printed out.
This is my Code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
FILE * stream;
char dateiname[255];
stream = fopen("heute.txt", "r");
if(stream == NULL){
printf("Error");
}else {
while(!feof(stream)){
fgets(dateiname, 255, stream);
}
fclose(stream);
}
printf("%s\n", dateiname);
}
Thanks for help!
Everything works fine but when the text file has more than one line, I always just get the last line printed out
Reason: For every iteration, the data gets replaced with the next line data, and at the end dateiname will read only the last line.
while(!feof(stream))
Usage of feof() is not recommended. Please see this link for more information :https://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1046476070
Please see the following code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *stream;
char dateiname[1024];
int i = 0;
stream = fopen("heute.txt", "r");
if (stream == NULL)
{
printf("Error");
}
else
{
while (fgets(dateiname, sizeof(dateiname), stream) != NULL)
{
printf("Line %4d: %s", i, dateiname);
i++;
}
}
return 0;
}
If you want to just read and print the contents of the file you no need to worry about the size of the file and how many number of lines you have in file.
you can just run fgets() in the while and print each line until we reach NULL
But if you want to store them, we need to calculate the size of the file.
So we need to use functions like stat or fstat to get the size of the file and allocate memory dynamically then just read that many bytes.
I'm developing a basic implementation of the game hangman.
I have a text file of the most 1000 common English language words and I'd like to just choose one of those at random to be the word in my game.
I know I need to use fopen and fscanf to get the word into a string in my program, but how do I choose which string to read in?
Would I have to import the whole list into an array and then choose one from there? Or is there a way I can just select which word to scan in?
You don't need to read all the words into your program just to select one.
You can instead seek to a random point in the word file, creep along until your see a newline (or whatever separates words), use fgets() or scanf() to read in one word and close the file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void random_word(const char *file_name, char *buffer, size_t length) {
FILE *file = fopen(file_name, "r");
if (file == NULL) {
fprintf(stderr, "Can't open %s!\n", file_name);
exit(EXIT_FAILURE);
}
(void) fseek(file, 0L, SEEK_END);
long size = ftell(file);
int c = EOF;
while (c == EOF || fgets(buffer, length, file) == NULL) {
long offset = random() % size;
(void) fseek(file, offset, SEEK_SET);
while ((c = getc(file)) != EOF && c != '\n');
}
buffer[strlen(buffer) - 1] = '\0'; // remove trailing \n
(void) fclose(file);
}
int main() {
srandom(time(NULL));
char buffer[1024];
for (int i = 0; i < 10; i++) {
random_word("/usr/share/dict/words", buffer, sizeof(buffer));
(void) puts(buffer);
}
return 0;
}
EXAMPLE
> ./a.out
boloman
disentrance
guanase
decorable
snibbled
redemandable
Cluniac
balneal
turbidimetry
catechistically
>
This code doesn't need to be complex nor efficient as it's a rare event, processing-wise, that you select a new word and it happens on a human time frame, not a high speed processing one.
The easy way is to put in in an array, then get a random index.
The more complex, but efficient, is to read an index of each word, save to another file, and then, just read the sector where that word is stored.
Really, just put it in an array.
file looks like this:
abcd
efgh
ijkl
I want to read the file using C so that it read the last line first:
ijkl
efgh
abcd
I cannot seem to find a solution that does not use an array for storage. Please help.
edit0:
Thanks for all the answers. Just to let you know, I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?
It goes like this:
Seek to one byte before the end of the file using fseek. There's no guarantee that the last line will have an EOL so the last byte doesn't really matter.
Read one byte using fgetc.
If that byte is an EOL then the last line is a single empty line and you have it.
Use fseek again to go backwards two bytes and check that byte with fgetc.
Repeat the above until you find an EOL. When you have an EOL, the file pointer will be at the beginning of the next (from the end) line.
...
Profit.
Basically you have to keep doing (4) and (5) while keeping track of where you were when you found the beginning of a line so that you can seek back there before starting your scan for the beginning of the next line.
As long as you open your file in text mode you shouldn't have have to worry about multibyte EOLs on Windows (thanks for the reminder Mr. Lutz).
If you happen to be given a non-seekable input (such as a pipe), then you're out of luck unless you want to dump your input to a temporary file first.
So you can do it but it is rather ugly.
You could do pretty much the same thing using mmap and a pointer if you have mmap available and the "file" you're working with is mappable. The technique would be pretty much the same: start at the end and go backwards to find the end of the previous line.
Re: "I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?"
You'll run into the same sorts of problems but they'll be worse. Files in C are inherently sequential lists of bytes that start at the beginning and go to the end; you're trying to work against this fundamental property and going against the fundamentals is never fun.
Do you really need your data in a plain text file? Maybe you need text/plain as the final output but all the way through? You could store the data in an indexed binary file (possibly even an SQLite database) and then you'd only have to worry about keeping (or windowing) the index in memory and that's unlikely to be a problem (and if it is, use a "real" database); then, when you have all your lines, just reverse the index and away you go.
In pseudocode:
open input file
while (fgets () != NULL)
{
push line to stack
}
open output file
while (stack no empty)
{
pop stack
write popped line to file
}
The above is efficient, there is no seek (a slow operation) and the file is read sequentially. There are, however, two pitfalls to the above.
The first is the fgets call. The buffer supplied to fgets may not be big enough to hold a whole line from the input in which case you can do one of the following: read again and concatenate; push a partial line and add logic to the second half to fix up partial lines or wrap the line into a linked list and only push the linked list when a newline/eof is encountered.
The second pitfall will happen when the file is bigger than the available ram to hold the stack, in which case you'll need to write the stack structure to a temporary file whenever it reaches some threshold memory usage.
The following code should do the necessary inversion:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fd;
char len[400];
int i;
char *filename = argv[1];
int ch;
int count;
fd = fopen(filename, "r");
fseek(fd, 0, SEEK_END);
while (ftell(fd) > 1 ){
fseek(fd, -2, SEEK_CUR);
if(ftell(fd) <= 2)
break;
ch =fgetc(fd);
count = 0;
while(ch != '\n'){
len[count++] = ch;
if(ftell(fd) < 2)
break;
fseek(fd, -2, SEEK_CUR);
ch =fgetc(fd);
}
for (i =count -1 ; i >= 0 && count > 0 ; i--)
printf("%c", len[i]);
printf("\n");
}
fclose(fd);
}
The following works for me on Linux, where the text file line separator is "\n".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readfileinreverse(FILE *fp)
{
int i, size, start, loop, counter;
char *buffer;
char line[256];
start = 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
buffer = malloc((size+1) * sizeof(char));
for (i=0; i< size; i++)
{
fseek(fp, size-1-i, SEEK_SET);
buffer[i] = fgetc(fp);
if(buffer[i] == 10)
{
if(i != 0)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && (buffer[loop] == 10))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
start = i;
printf("%s\n",line);
}
}
}
if(i > start)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && ((buffer[loop] == 10) || (buffer[loop] == 0)))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
printf("%s\n",line);
return;
}
}
int main()
{
FILE *fp = fopen("./1.txt","r");
readfileinreverse(fp);
return 0;
}
Maybe , The does the trick , It reverse content of the file in whole
just like a string
Define a variable of type string with size of your file
Get Contents of the file and store in the variable
Use strrev() to reverse the string.
You can later on display the output or even write it to a file. The code goes like this:
#include <stdio.h>
#include <String.h>
int main(){
FILE *file;
char all[1000];
// give any name to read in reverse order
file = fopen("anyFile.txt","r");
// gets all the content and stores in variable all
fscanf(file,"%[]",all);
// Content of the file
printf("Content Of the file %s",all);
// reverse the string
printf("%s",strrev(all));
fclose(file);
return 0;
}
I know this question has been awnsered, but the accepted awnser does not contain a code snippet and the other snippets feel too complex.
This is my implementation:
#include <stdio.h>
long file_size(FILE* f) {
fseek(f, 0, SEEK_END); // seek to end of file
long size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
return size;
}
int main(int argc, char* argv[]) {
FILE *in_file = fopen(argv[1], "r");
long in_file_size = file_size(in_file);
printf("Got file size: %ld\n", in_file_size);
// Start from end of file
fseek(in_file, -1, SEEK_END); // seek to end of file
for (int i = in_file_size; i > 0; i--) {
char current_char = fgetc(in_file); // This progresses the seek location
printf("Got char: |%c| with hex: |%x|\n", current_char, current_char);
fseek(in_file, -2, SEEK_CUR); // Go back 2 bytes (1 to compensate)
}
printf("Done\n");
fclose(in_file);
}
I am trying to find out a way to select the last line of a text file using C (not c++ or c#, just C) and I am having a difficult time finding a way to do this, if anyone could assist me with this problem I would be very grateful, thanks! (btw for a good example of what i am trying to do, this would be similar what to tail -n 1 would be doing in bash)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(int argc, char *argv[])
{
FILE *fd; // File pointer
char filename[] = "./Makefile"; // file to read
char buff[1024];
if ((fd = fopen(filename, "r")) != NULL) // open file
{
fseek(fd, 0, SEEK_SET); // make sure start from 0
while(!feof(fd))
{
memset(buff, 0x00, 1024); // clean buffer
fscanf(fd, "%[^\n]\n", buff); // read file *prefer using fscanf
}
printf("Last Line :: %s\n", buff);
}
}
I'm using Linux.
CMIIW
No direct way, but my preferred method is:
Go to the end of the file
Read last X bytes
If they contain '\n' - you got your line - read from that offset to the end of the file
Read X bytes before them
back to 3 until match found
If reached the beginning of the file - the whole file is the last line
E.g.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef max
#define max(a, b) ((a)>(b))? (a) : (b)
#endif
long GetFileSize(FILE *fp){
long fsize = 0;
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);//reset stream position!!
return fsize;
}
char *lastline(char *filepath){
FILE *fp;
char buff[4096+1];
int size,i;
long fsize;
if(NULL==(fp=fopen(filepath, "r"))){
perror("file cannot open at lastline");
return NULL;
}
fsize= -1L*GetFileSize(fp);
if(size=fseek(fp, max(fsize, -4096L), SEEK_END)){
perror("cannot seek");
exit(1);
}
size=fread(buff, sizeof(char), 4096, fp);
fclose(fp);
buff[size] = '\0';
i=size-1;
if(buff[i]=='\n'){
buff[i] = '\0';
}
while(i >=0 && buff[i] != '\n')
--i;
++i;
return strdup(&buff[i]);
}
int main(void){
char *last;
last = lastline("data.txt");
printf("\"%s\"\n", last);
free(last);
return 0;
}
If you are using *nix operating system, you can use the command 'last'. See 'last' man page for details.
If you want integrate the functionality inside another program, you can use 'system' call to execute 'last' and get it's result.
A simple and inefficient way to do it is to read each line into a buffer.
When the last read gives you EOF, you have the last line in the buffer.
Binyamin Sharet's suggestion is more efficient, but just a bit harder to implement.
file looks like this:
abcd
efgh
ijkl
I want to read the file using C so that it read the last line first:
ijkl
efgh
abcd
I cannot seem to find a solution that does not use an array for storage. Please help.
edit0:
Thanks for all the answers. Just to let you know, I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?
It goes like this:
Seek to one byte before the end of the file using fseek. There's no guarantee that the last line will have an EOL so the last byte doesn't really matter.
Read one byte using fgetc.
If that byte is an EOL then the last line is a single empty line and you have it.
Use fseek again to go backwards two bytes and check that byte with fgetc.
Repeat the above until you find an EOL. When you have an EOL, the file pointer will be at the beginning of the next (from the end) line.
...
Profit.
Basically you have to keep doing (4) and (5) while keeping track of where you were when you found the beginning of a line so that you can seek back there before starting your scan for the beginning of the next line.
As long as you open your file in text mode you shouldn't have have to worry about multibyte EOLs on Windows (thanks for the reminder Mr. Lutz).
If you happen to be given a non-seekable input (such as a pipe), then you're out of luck unless you want to dump your input to a temporary file first.
So you can do it but it is rather ugly.
You could do pretty much the same thing using mmap and a pointer if you have mmap available and the "file" you're working with is mappable. The technique would be pretty much the same: start at the end and go backwards to find the end of the previous line.
Re: "I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?"
You'll run into the same sorts of problems but they'll be worse. Files in C are inherently sequential lists of bytes that start at the beginning and go to the end; you're trying to work against this fundamental property and going against the fundamentals is never fun.
Do you really need your data in a plain text file? Maybe you need text/plain as the final output but all the way through? You could store the data in an indexed binary file (possibly even an SQLite database) and then you'd only have to worry about keeping (or windowing) the index in memory and that's unlikely to be a problem (and if it is, use a "real" database); then, when you have all your lines, just reverse the index and away you go.
In pseudocode:
open input file
while (fgets () != NULL)
{
push line to stack
}
open output file
while (stack no empty)
{
pop stack
write popped line to file
}
The above is efficient, there is no seek (a slow operation) and the file is read sequentially. There are, however, two pitfalls to the above.
The first is the fgets call. The buffer supplied to fgets may not be big enough to hold a whole line from the input in which case you can do one of the following: read again and concatenate; push a partial line and add logic to the second half to fix up partial lines or wrap the line into a linked list and only push the linked list when a newline/eof is encountered.
The second pitfall will happen when the file is bigger than the available ram to hold the stack, in which case you'll need to write the stack structure to a temporary file whenever it reaches some threshold memory usage.
The following code should do the necessary inversion:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fd;
char len[400];
int i;
char *filename = argv[1];
int ch;
int count;
fd = fopen(filename, "r");
fseek(fd, 0, SEEK_END);
while (ftell(fd) > 1 ){
fseek(fd, -2, SEEK_CUR);
if(ftell(fd) <= 2)
break;
ch =fgetc(fd);
count = 0;
while(ch != '\n'){
len[count++] = ch;
if(ftell(fd) < 2)
break;
fseek(fd, -2, SEEK_CUR);
ch =fgetc(fd);
}
for (i =count -1 ; i >= 0 && count > 0 ; i--)
printf("%c", len[i]);
printf("\n");
}
fclose(fd);
}
The following works for me on Linux, where the text file line separator is "\n".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readfileinreverse(FILE *fp)
{
int i, size, start, loop, counter;
char *buffer;
char line[256];
start = 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
buffer = malloc((size+1) * sizeof(char));
for (i=0; i< size; i++)
{
fseek(fp, size-1-i, SEEK_SET);
buffer[i] = fgetc(fp);
if(buffer[i] == 10)
{
if(i != 0)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && (buffer[loop] == 10))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
start = i;
printf("%s\n",line);
}
}
}
if(i > start)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && ((buffer[loop] == 10) || (buffer[loop] == 0)))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
printf("%s\n",line);
return;
}
}
int main()
{
FILE *fp = fopen("./1.txt","r");
readfileinreverse(fp);
return 0;
}
Maybe , The does the trick , It reverse content of the file in whole
just like a string
Define a variable of type string with size of your file
Get Contents of the file and store in the variable
Use strrev() to reverse the string.
You can later on display the output or even write it to a file. The code goes like this:
#include <stdio.h>
#include <String.h>
int main(){
FILE *file;
char all[1000];
// give any name to read in reverse order
file = fopen("anyFile.txt","r");
// gets all the content and stores in variable all
fscanf(file,"%[]",all);
// Content of the file
printf("Content Of the file %s",all);
// reverse the string
printf("%s",strrev(all));
fclose(file);
return 0;
}
I know this question has been awnsered, but the accepted awnser does not contain a code snippet and the other snippets feel too complex.
This is my implementation:
#include <stdio.h>
long file_size(FILE* f) {
fseek(f, 0, SEEK_END); // seek to end of file
long size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
return size;
}
int main(int argc, char* argv[]) {
FILE *in_file = fopen(argv[1], "r");
long in_file_size = file_size(in_file);
printf("Got file size: %ld\n", in_file_size);
// Start from end of file
fseek(in_file, -1, SEEK_END); // seek to end of file
for (int i = in_file_size; i > 0; i--) {
char current_char = fgetc(in_file); // This progresses the seek location
printf("Got char: |%c| with hex: |%x|\n", current_char, current_char);
fseek(in_file, -2, SEEK_CUR); // Go back 2 bytes (1 to compensate)
}
printf("Done\n");
fclose(in_file);
}