fgets to read particular size - c

I'm trying to write a program that reads a certain amount of characters from a file name given from command line. Here is what I have:
#include <stdio.h>
int main(int argc, char **argv)
{
int i = 0;
FILE *f;
char* fileName = argv[1];
char buf[40];
f = fopen(fileName, "r");
while(!feof(f)){
fgets(buf, 10, f);
printf("%s\n", buf);
}
fclose(f);
return 1;
}
Say in this particular case I need first 10 chars, then the next 10 chars, etc until the file is over. However, when I run this code it doesn't actually give me the right output. I tried 11 as well since the documentation said fgets() reads n-1 characters, but that doesn't work either. Some stuff at the beginning is read, but nothing afterwards is and it just gives me a bunch of blanks. Any idea what is wrong?
Thanks

The function you are looking for is fread, like this:
fread(buf, 10, 1, f);

It works almost ok if you remove the \n from your printf format string (assuming that you want to basically echo a whole file as is).
I would also loop based on fgets(...) != NULL since feof() will return a true value after fgets errors and hits EOF, so your last buffer-full will be printed twice. You could make a small change to your code as so:
#include <stdio.h>
int main(int argc, char **argv)
{
int i = 0;
FILE *f;
char* fileName = argv[1];
char buf[40];
f = fopen(fileName, "r");
while(fgets(buf, 10, f))
printf("%s", buf);
fclose(f);
return 0;
}
Also, as others have stated, while I took too long to answer, fread may be a better alternative since fgets won't necessarily read 10 chars; it'll stop at every newline and you don't care about reading a line at a time.

fgets is intended to read a line, up to a maximum length. If you want to read 10 characters at a time, regardless of line breaks, you probably want to use fread instead:
Either way, you definitely do not want to use while (!feof(f)). You probably want something like:
int main(int argc, char **argv) {
char buf[40];
FILE *f;
if (NULL == (f=fopen(argv[1], "r"))) {
fprintf(stderr, "Unable to open file\n");
return EXIT_FAILURE;
}
size_t len;
while (0 < (len=fread(buf, 10, 1, f)))
printf("%*.*s\n", len, len, buf);
return 0;
}

Related

How to write strings in different places of a file in C

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.

How to read line by line after i read a text into a buffer?

First , I read a text into a buffer by calling fread, and then I want to read it line by line, how to do it? I try to use a sscanf , but it seems not to work.
char textbuf[4096];
char line[256];
FILE *fp;
fp = fopen(argv[1],"r");
memset(textbuf, 0, 4096);
fread(textbuf, 1, 4096, fp);
I know using fgets is a good way. I just want to know weather this method can do the same thing.
Try this:
fgets(textbuf, sizeof(textbuf), fp);
For read line by line you can use: fgets(line, 128, fp) or getline(&line, &size, fp);
EDIT
If you want to read it from a variable, look at strtok() function:
char * line = strtok(strdup(buffer), "\n");
while(line) {
printf("%s", line);
line = strtok(NULL, "\n");
}
You can find the location of the end-of-line character using strchr() like this:
char *eol = strchr(line, '\n');
Everything before *eol is the first line. Then advance from line to eol + 1, remove any subsequent \r or \n characters, and repeat the process until strchr() returns NULL to indicate there are no more newline characters. At that point, move any remaining data to the beginning of the buffer and read the next chunk from the file.
If you're concerned about efficiency you can avoid moving the data by using 2 buffers and alternating between them, but even the naive method is probably faster than fgets() if the file has many lines.
how about strtok
char *line;
line = strtok(texbuf, '\n');
You said "I know using fgets is a good way. I just want to know weather this method can do the same thing.", of course you can, you just re-implement fgets as in the c library. The c library doesn't actually read line by line, it reads in a whole chunk and gives you a line when you call fgets.
Not an efficient way, but a sample of the kind of things you have to do.
#include <stdio.h>
typedef struct my_state {
unsigned char * buf;
int offset;
int buf_size;
int left;
FILE * file;
} my_state_t;
int takeone(my_state_t * state) {
if ((state->left - state->offset)<=0) {
if (feof(state->file)) return -1;
state->left = fread(state->buf,1,state->buf_size,state->file);
state->offset = 0;
if (state->left == 0) return -1;
}
return state->buf[state->offset++];
}
int getaline(my_state_t * state, char * out, int size) {
int c;
c = takeone(state);
if (c < 0) return 0;
while (c >=0 && size > 1) {
*out++ = c;
--size;
if (c == '\n') break;
c = takeone(state);
}
*out=0;
return 1;
}
int main(int argc, char ** argv){
FILE *fp;
char textbuf[4096];
char line[256];
my_state_t fs;
fs.buf=textbuf;
fs.offset=0;
fs.buf_size=4096;
fs.left=0;
fp = (argc>1)? fopen(argv[1],"rb") : stdin;
fs.file = fp;
while (getaline(&fs,line,256)) {
printf("-> %s", line);
}
fclose(fp);
}

Segmentation fault while reading file

My file looks like:
123456789
My code gives me segmentation fault:
#include <stdio.h>
int main(){
FILE *f;
char ch[5];
f = open("a.txt", "r");
fgets( ch, 4, f);
ch[4] = NULL;
printf("%s", ch); //Fixed
return 0;
}
I am an absolute beginner. What am I doing wrong. My aim is to read first 4 characters of the file using fgets.
You'll want to do
printf("%s", ch);
For the % format, the argument is a pointer to characters; by passing a single character by value, you're telling printf to interpret that character's ASCII value as a pointer, and that's going to blow up on you; i.e., if the character is a 1, which is ASCII 49, then it's going to look at byte 49 in memory for a string -- and looking down there is generally verboten.
But secondly, I see you're calling open() instead of fopen(). You must use fopen() or you won't get a FILE* as you're expecting.
Both of these individually would likely cause a segfault -- you'll need to fix them both.
try to use "fopen" instead just "open"
Thanks.
Couple of quick changes.
I think you want to use fopen rather than open here, since you used a file pointer.
You need to increase the bytes read to 5, the last one is terminated by a null by fgets.
int main() {
FILE *f;
char ch[5];
f = fopen("a.txt", "r");
fgets( ch, 5, f);
printf("%s", ch);
return 0;
}
try to use
#include <stdio.h>
int main(){
FILE *f;
char ch[5];
f = fopen("a.txt", "r"); //use fopen
fgets( ch, 4, f);
ch[4] = NULL;
printf("%s", ch); // modification here pass the address of an array to printf
return 0;
}
try following example from the refereed site
/* fgets example */
#include <stdio.h>
int main()
{
FILE * pFile;
char mystring [5];
pFile = fopen ("myfile.txt" , "r");
if (pFile == NULL) perror ("Error opening file");
else {
if ( fgets (mystring , 5 , pFile) != NULL )
puts (mystring);
fclose (pFile);
}
return 0;
}
refer http://www.cplusplus.com/reference/clibrary/cstdio/fgets/
you can also use
fgetc() :Get character from stream (function)

How to print content of file after seek

I am trying to print the remaining contents of a file after I do a fseek. Right now I am getting nothing returned. What's wrong with my code?
#include <stdio.h>
int main(int argc, char *argv[]){
FILE *fr;
if (fr = fopen (argv[1], "r")){
fseek(fr, 100, SEEK_CUR);
char c[1];
while (fread(c, 1, sizeof(c),fr) > 0)
printf("%s", c);
fclose(fr);
}
else{
perror("File does not exist");
}
}
As the other answers pointed out, you are passing printf a string which may not be NULL terminated. You are also not verifying the file being read is greater than 100 bytes. One last point, in fread() you swapped the size_t size and size_t niters parameters.
Here is an modified version of your program which fixes the above issues (and cleans up the spacing a bit):
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
FILE *fr;
char c[1];
struct stat sb;
// obtains information about the file
if (stat(argv[1], &sb) == -1)
{
perror("stat()");
return(1);
};
// verifies the file is over 100 bytes in size
if (sb.st_size < 101)
{
fprintf(stderr, "%s: file is less than 100 bytes\n", argv[1]);
return(1);
};
// opens the file, or prints the error and exists
if (!(fr = fopen (argv[1], "r")))
{
perror("fopen():");
return(1);
};
fseek(fr, 100, SEEK_CUR);
while (fread(c, sizeof(c), 1, fr) > 0)
printf("%c", c[0]);
fclose(fr);
return(0);
}
You could also improve the efficiency of reading the file by changing char c[1]; to something line char c[1024]; and updating the while statement to:
while (fread(c, sizeof(char), 1023, fr) > 0)
{
c[1023] = '\0';
printf("%s", c);
};
you cannot print with %s as your string needs to be null terminated and you only have one character.
use:
printf("%c",*c);
not all characters are printable, check an ascii table to see which are printable and which not. eg printing a 0 will not print anything on screen, AFAIK
You are reading a byte but trying to print it with %s, which expects a null-terminated string. Changing that to %c (and of course c to *c so that it agrees with the format string!) should fix things.
Especially if the value of the bytes you read is equal to 0, printf with the %s specifier will output absolutely nothing (as it thinks you are repeatedly asking it to print the empty string).
printf("%s",blabla) should print a null-terminated string. for print one char use printf("%c",c[0]).

In C, how should I read a text file and print all strings

I have a text file named test.txt
I want to write a C program that can read this file and print the content to the console (assume the file contains only ASCII text).
I don't know how to get the size of my string variable. Like this:
char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
while (fscanf(file, "%s", str)!=EOF)
printf("%s",str);
fclose(file);
}
The size 999 doesn't work because the string returned by fscanf can be larger than that. How can I solve this?
The simplest way is to read a character, and print it right after reading:
int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
c is int above, since EOF is a negative number, and a plain char may be unsigned.
If you want to read the file in chunks, but without dynamic memory allocation, you can do:
#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;
file = fopen("test.txt", "r");
if (file) {
while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
fwrite(buf, 1, nread, stdout);
if (ferror(file)) {
/* deal with error */
}
fclose(file);
}
The second method above is essentially how you will read a file with a dynamically allocated array:
char *buf = malloc(chunk);
if (buf == NULL) {
/* deal with malloc() failure */
}
/* otherwise do this. Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
/* as above */
}
Your method of fscanf() with %s as format loses information about whitespace in the file, so it is not exactly copying a file to stdout.
There are plenty of good answers here about reading it in chunks, I'm just gonna show you a little trick that reads all the content at once to a buffer and prints it.
I'm not saying it's better. It's not, and as Ricardo sometimes it can be bad, but I find it's a nice solution for the simple cases.
I sprinkled it with comments because there's a lot going on.
#include <stdio.h>
#include <stdlib.h>
char* ReadFile(char *filename)
{
char *buffer = NULL;
int string_size, read_size;
FILE *handler = fopen(filename, "r");
if (handler)
{
// Seek the last byte of the file
fseek(handler, 0, SEEK_END);
// Offset from the first to the last byte, or in other words, filesize
string_size = ftell(handler);
// go back to the start of the file
rewind(handler);
// Allocate a string that can hold it all
buffer = (char*) malloc(sizeof(char) * (string_size + 1) );
// Read it all in one operation
read_size = fread(buffer, sizeof(char), string_size, handler);
// fread doesn't set it so put a \0 in the last position
// and buffer is now officially a string
buffer[string_size] = '\0';
if (string_size != read_size)
{
// Something went wrong, throw away the memory and set
// the buffer to NULL
free(buffer);
buffer = NULL;
}
// Always remember to close the file.
fclose(handler);
}
return buffer;
}
int main()
{
char *string = ReadFile("yourfile.txt");
if (string)
{
puts(string);
free(string);
}
return 0;
}
Let me know if it's useful or you could learn something from it :)
Instead just directly print the characters onto the console because the text file maybe very large and you may require a lot of memory.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *f;
char c;
f=fopen("test.txt","rt");
while((c=fgetc(f))!=EOF){
printf("%c",c);
}
fclose(f);
return 0;
}
Use "read()" instead o fscanf:
ssize_t read(int fildes, void *buf, size_t nbyte);
DESCRIPTION
The read() function shall attempt to read nbyte bytes from the file associated with the open file descriptor, fildes, into the buffer pointed to by buf.
Here is an example:
http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html
Working part from that example:
f=open(argv[1],O_RDONLY);
while ((n=read(f,l,80)) > 0)
write(1,l,n);
An alternate approach is to use getc/putc to read/write 1 char at a time. A lot less efficient. A good example: http://www.eskimo.com/~scs/cclass/notes/sx13.html
You can use fgets and limit the size of the read string.
char *fgets(char *str, int num, FILE *stream);
You can change the while in your code to:
while (fgets(str, 100, file)) /* printf("%s", str) */;
Two approaches leap to mind.
First, don't use scanf. Use fgets() which takes a parameter to specify the buffer size, and which leaves any newline characters intact. A simple loop over the file that prints the buffer content should naturally copy the file intact.
Second, use fread() or the common C idiom with fgetc(). These would process the file in fixed-size chunks or a single character at a time.
If you must process the file over white-space delimited strings, then use either fgets or fread to read the file, and something like strtok to split the buffer at whitespace. Don't forget to handle the transition from one buffer to the next, since your target strings are likely to span the buffer boundary.
If there is an external requirement to use scanf to do the reading, then limit the length of the string it might read with a precision field in the format specifier. In your case with a 999 byte buffer, then say scanf("%998s", str); which will write at most 998 characters to the buffer leaving room for the nul terminator. If single strings longer than your buffer are allowed, then you would have to process them in two pieces. If not, you have an opportunity to tell the user about an error politely without creating a buffer overflow security hole.
Regardless, always validate the return values and think about how to handle bad, malicious, or just malformed input.
You can use getline() to read your text file without worrying about large lines:
getline() reads an entire line from stream, storing the address of the buffer containing the text into *lineptr. The buffer is null-terminated and includes the newline character, if one was found.
If *lineptr is set to NULL before the call, then getline() will allocate a buffer for storing the line. This buffer should be freed by the user program even if getline() failed.
bool read_file(const char *filename)
{
FILE *file = fopen(filename, "r");
if (!file)
return false;
char *line = NULL;
size_t linesize = 0;
while (getline(&line, &linesize, file) != -1) {
printf("%s", line);
free(line);
}
free(line);
fclose(file);
return true;
}
You can use it like this:
int main(void)
{
if (!read_file("test.txt")) {
printf("Error reading file\n");
exit(EXIT_FAILURE);
}
}
I use this version
char* read(const char* filename){
FILE* f = fopen(filename, "rb");
if (f == NULL){
exit(1);
}
fseek(f, 0L, SEEK_END);
long size = ftell(f)+1;
fclose(f);
f = fopen(filename, "r");
void* content = memset(malloc(size), '\0', size);
fread(content, 1, size-1, f);
fclose(f);
return (char*) content;
}
You could read the entire file with dynamic memory allocation, but isn't a good idea because if the file is too big, you could have memory problems.
So is better read short parts of the file and print it.
#include <stdio.h>
#define BLOCK 1000
int main() {
FILE *f=fopen("teste.txt","r");
int size;
char buffer[BLOCK];
// ...
while((size=fread(buffer,BLOCK,sizeof(char),f)>0))
fwrite(buffer,size,sizeof(char),stdout);
fclose(f);
// ...
return 0;
}

Resources