how does work setvbuf() in C [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
can someone explain me how does int setvbuf(FILE *stream, char *buffer, int mode, size_t size) C function works?
I think it sets a buffer for a file stream and stores data in the buffer allocated by setvbuf in size_t size chunks of data, am I right? And when the buffer is full it is flushed?
sorry I am new here

I assume you did search google, but you need some help understanding what you have found:
I am quoting interchangeably gnu documentation and cppreference:
int setvbuf (FILE *stream, char *buf, int mode, size_t size)
After opening a stream (but before any other operations have been
performed on it), you can explicitly specify what kind of buffering
you want it to have using the setvbuf function. The facilities listed
in this section are declared in the header file stdio.h.
The arguments description:
stream - the file stream to set the buffer to
buffer - pointer to a buffer for the stream to use
mode - buffering mode to use. It can
be one of the following values:
_IOFBF full buffering
_IOLBF line buffering
_IONBF no buffering
size - size of the buffer
If you switch for the c documentation in cppreference you will find the following example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int file_size;
char buffer[BUFSIZ];
FILE * fp = fopen("test.txt","w+");
if (setvbuf(fp,buffer,_IOFBF,BUFSIZ) != 0)
{
perror("setvbuf()");
fprintf(stderr,"setvbuf() failed in file %s at line # %d\n", __FILE__,__LINE__-3);
exit(EXIT_FAILURE);
}
/* Exhibit the contents of buffer. */
fputs ("aaa",fp);
printf("%s\n", buffer);
fputs ("bbb",fp);
printf("%s\n", buffer);
fputs ("ccc",fp);
printf("%s\n", buffer);
file_size = ftell(fp);
printf("file_size = %d\n", file_size);
fflush (fp); /* flush buffer */
printf("%s\n", buffer);
fputs ("ddd",fp);
printf("%s\n", buffer);
fputs ("eee",fp);
printf("%s\n", buffer);
rewind(fp); /* flush buffer and rewind file */
char buf[20];
fgets(buf,sizeof buf,fp);
printf("%s\n", buf);
fclose(fp);
return 0;
}
Output:
aaa
aaabbb
aaabbbccc
file_size = 9
aaabbbccc
dddbbbccc
dddeeeccc
aaabbbcccdddeee
Pay attention for the following things:
What happens when you fflush the FILE *fp.
What buffer contains after fputs string to fp.
What happens when you rewind(fp), reread from the file all you have been written.
Don't be afraid of documentation/ manual pages, if you get used to them and read them you will be a great developer, moreover now you are familiar with http://en.cppreference.com/, which is very good source to get start with new API functions, good luck.

Related

Read from stdin in the fastest way in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have to write a program in C in which I have to read some values from stdin and also to do it with the quickest function in C. The stdin is preloaded in a form like this:
int,int\n
char\n
int,int,int\n ex...
I'm asking for help because scanf is too slow for the time requirement of the project and also because I have some difficulties to read because of the ',' that I don't really need and that causes me problems.
I've tried with gets or getchar, but I didn't manage to make it work.
The fastest way to read stdin ("standard in" - 0 file descriptor) is to use read function from <unistd.h.>:
char buff[1024] = {0}; /* zero-initialize */
ssize_t res = read(0, &buff, sizeof(buff));
/* res is amount of bytes read; -1 if error */
Here is an example of program which reads 1024 bytes of stdin and echoes it to stdout (file descriptor: 1) (no error handling for simplicity):
#include <unistd.h>
#define BUFSIZ 1024
int main() {
char buff[BUFSIZ] = {0}; /* zero-initialize */
ssize_t nread = read(0, buff, BUFSIZ);
/* pass amount of bytes read as a byte amount to write */
write(1, buff, nread);
return 0;
}
This is the fastest way to read from stdin because read is native libc wrapper for a kernel syscall. By the way, you can use -O3, or even -Ofast compiler options to make it optimize the code.
Also, keep in mind that read and write are not guaranteed to read/write exactly as many bytes as you want, you should call it in a loop like this:
size_t to_write = sizeof(buff); /* example, can be result of read() */
int fd = 1;
size_t nwrote = 0;
while ((nwrote += write(1, buff, to_write) < to_write) {
/* pointer arithmetic to create offset from buff start */
write(fd, buff+nwrote, to_write - nwrote);
}

How does fwrite() work [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have to use fwrite() instead of fputc(), but I can't understand how it works.
I have tried to use it but it writes in binary. This is the code:
while ((c = fgetc(f1)) != EOF)
{
if (fwrite(&f3, sizeof(f3), 1, f3) == EOF)
{
printf("valore iniziale di errno = %d\n",errno);
perror("errore:");
exit(1);
}
}
f1 is the file where some text is written and f3 is the file where I want to write the content of f1 but I see only binary text.
How fwrite "works"
You can start by looking at the fwrite manual. It's signature is:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
So, let's break down each argument:
ptr is the source location of your data (where you data is).
size is the size of each element of data. fwrite writes in chunks of size bytes each time it loops.
nmemb is the number of loops fwrite will perform.
stream is the file descriptor (FILE*) of your output file.
So, with that in mind, imagine this:
// our dear string
char *str = "#SO";
// open a bogus file to write
FILE *fp = fopen(foo, "wb");
// call fwrite and store returned value
size_t ret = fwrite(str, 3, 1, fp);
This code will do the following (other than not compiling): Starting at location pointed by str, it will write 3 bytes in the file pointed by fp 1 time. However, if you did it like this:
size_t ret = fwrite(str, 1, 3, fp);
That would tell fwrite to write 1 byte to the file for every iteration it does, and it would do 3 iterations.
In your case, you read a character from f1 and want to write it to f3. Therefore, you should have something like this:
ret = fwrite(&c, sizeof(c), 1, f3);
That will read the binary character from f1 and copy it to f3.
Note that this might not be (and probably is not) the way fwrite works internally. What I presented here is the mental model I use to remember its arguments. If you actually read fwrite source code, you may find a very different implementation.
Example
So, a simple program to copy from f1 to f2 is:
#include <stdio.h>
int main(void)
{
char c;
FILE *f1 = fopen("foo.txt", "rb");
FILE *f2 = fopen("bar.txt", "wb");
size_t ret;
while((ret = fread(&c, sizeof(c), 1, f1)))
ret = fwrite(&c, sizeof(c), 1, f2);
fclose(f1);
fclose(f2);
return 0;
}

C reading a file with null in it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm working on a data file that contains a fixed number of characters followed by a colon and then a number. All of the first four characters can be anything from all nulls to all (char)255s.
However, when trying to read it, I'm having trouble determining the EOF.
If I use posix's read(2) like so:
ssize_t letters_read = read(fd, buf, 4);
Then letters_read is set to 0. The man page says that means I've reached an EOF; however, this is simply not true.
If I use fread(3) in a similar way, then I still get zero as a return value. Even when sending the file to feof(3), it says I'm at the end of file.
Now, if I just ignore the return values, then I'm able to continue reading the file and get further results.
How would I be able to read all four nulls and still be able to know when I've reached an eof?
A small excerpt of the file looks like this:
4
(null)(null)(null)(null):4
(null)(null)(null)(null):40
(null)(null)(null)(null):402
Af*8:3004
UPDATE
As per request, here is how I'm going about collecting data:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
void process_characters(char *data);
int main(int argc, char *argv[])
{
char *input_file = argv[1];
int opt = 0;
int input_fd = open(input_file, O_RDONLY);
FILE *temp_fd = fopen(input_file, "r");
unsigned long character_size = 0;
fscanf(temp_fd, "%l", character_size);
char data[character_size];
//gobble up the first line
do
{
read(input_fd, data, 1);
printf("%i\n", data[0]);
} while(data[0] != '\n');
size_t characters_read = 0;
characters_read = read(input_fd, data, character_size);
//while(feof(temp_fd) != 0)
while(characters_read != 0)
{
//fread(data, sizeof(char), character_size, temp_fd);
process_characters(data);
///gobble up the garbage
do
{
read(input_fd, data, 1);
printf("%i\n", data[0]);
}while(data[0] != 10);
characters_read = read(input_fd, data, character_size);
}
fclose(temp_fd);
close(input_fd);
return EXIT_SUCCESS;
}
This code:
unsigned long character_size = 0;
fscanf(temp_fd, "%l", character_size);
... has an invalid format specified, and needs to provide the variable address rather than its value. "%l" does not specify a type to read. Perhaps you want "%lu" which is for an unsigned long integer, which is how character_size is defined. character_size should be &character_size.
However, there is no such (decimal) value at the beginning of the sample file you have provided, so it is unclear what this fscanf line is really supposed to do.
(You claimed that using read as follow returns 0:
ssize_t letters_read = read(fd, buf, 4);
However, there is no such line in your code).

'fseek() + output' Behaves Strange on C Standard I/O Library Memory Streams

I'm reading the APUE and trying out the memory stream in stdio.h. However, I feel very confused on the mechanism of auto-writing \0 .
Here is what APUE said on 5.14 Memory Streams:
A null byte is written at the current position in the stream whenever we increase the amount of data in the stream’s buffer and call fclose, fflush, fseek, fseeko, or fsetpos
I did some experiment using the following code, to test what means Increase the amount of data in the stream's buffer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BSZ 48
int main(){
FILE *fp;
char buf[BSZ];
memset(buf, 'a', BSZ-2);
buf[BSZ-2] = '\0';
buf[BSZ-1] = 'X';
printf("Initial buffer content: %s\n", buf);
if ((fp = fmemopen(buf, BSZ, "w+")) == NULL){
fputs("fmemopen failed\n", stderr);
exit(-1);
}
fprintf(fp, "hello, world");
/* Confused Point Here !!! */
fflush(fp); //works as expected
//fseek(fp, 12, SEEK_SET); //strange behavior
printf("after fflush/fseek: %s\n", buf);
fprintf(fp, "hello, world2");
fclose(fp);
printf("after fclose: %s\n", buf);
exit(0);
}
Both flush() and fseek() will auto-write a '\0' after the first output of "hello, world".
The behaviors are different after the second output of 'hello, world' and call fclose():
When I use the flush(), the second output of "hello, world" is followed by a '\0', which is what I expected:
Initial buffer content: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
after fflush/fseek: hello, world
after fclose: hello, worldhello, world2
However, when I switch to fseek(fp, 12, SEEK_SET), the second output of "hello, world" is not followed by a '\0' any more:
Initial buffer content: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
after fflush/fseek: hello, world
after fclose: hello, worldhello, world2aaaaaaaaaaaaaaaaaaaaa
This means the memory stream doesn't treat the second output as increasing the amount of data.
I did this experiment on SUSE Linux Enterprise Server 11 (x86_64) SP1
Do you have any ideas about that? Or it is actually a bug of the system?
Thanks ahead.
[Too long for a comment:]
A null byte is written at the current position in the stream whenever we increase the amount of data in the stream’s buffer and call fclose, fflush, fseek, fseeko, or fsetpos
Documentation differs regarding the above quote from APUE:
The Linux man-page says:
When a stream that has been opened for writing is flushed (fflush(3))
or closed (fclose(3)), a null byte is written at the end of the
buffer if there is space. [...] The stream's file position can be changed with fseek(3) or fseeko(3). Moving the file position past the end of the data already written fills the intervening space with zeros.
POSIX says:
When a stream open for writing is flushed or closed, a null byte shall be written at the current position or at the end of the buffer, depending on the size of the contents.
So POSIX ins't as explitic as the Linux doc at all reagrding what to do on fseek*s.

Is it legal to use freopen and after it fopen ?

Suppose I have a string char* str.
I print it to the buffer in the following way:
char buf[MAX_LEN];
freopen("tmp","w",stdout);
printf("%s\n",str);
fflush(stdout);
fp = fopen(tmp,"r");
if (fp == NULL) return;
fgets(buf,MAX_LEN,fp);
fclose(fp);
fclose(stdout);
May this code cause invalid stream buffer handle?
Is it legal to use freopen and after it fopen?
Based on constrains of my system I can't use fprintf and sprintf.
In theory, it's perfectly legal and works fine. It's even its main use case, according to its man page :
The freopen() function opens the file whose name is the string
pointed to by path and associates the stream pointed to by stream with
it. The original stream (if it exists) is closed. The mode argument
is used just as in the fopen() function. The primary use of the
freopen() function is to change the file associated with a standard
text stream (stderr, stdin, or stdout)
In practice, your code won't work : there are some mistake mainly between "tmp" and tmp & missing headers. This code will work:
#include <stdio.h>
#define MAX_LEN 512
int main() {
const char* str = "data\n";
FILE* fp;
char buf[MAX_LEN];
freopen("tmp","w",stdout);
printf("%s\n",str);
fflush(stdout);
fp = fopen("tmp","r");
if (fp == NULL) return;
fgets(buf,MAX_LEN,fp);
// here, buf gets str's content
fclose(fp);
fclose(stdout);
return 0;
}

Resources