how to write non-char* by using write() function? - c

it's possible to write non-char* by using write() function? I need to print a unsigned long and I have no idea how to do it. In other words, pass a unsigned long in buf parameter.

It's usually preferable to use the standard C functions where available since they're more portable. If you can, and you want to output it as text, you should look at fprintf rather than fwrite. The former will format it for you, the latter is meant for writing raw memory blocks.
For example:
int val = 42;
fprintf (fh, "%d", val); // should check return value.
will output the text "42".
If you do want to write out the binary representation, fwrite is the means for that:
int val = 42;
fwrite (&val, sizeof (val), 1, fh); // should check return value.
That will write out the binary representation so that the bytes 0, 0, 0 and 42 are written to the file (depending on what the memory layout is for an int variable of course - it may vary depending on the implementation).
That's if you're able to use file handles rather than descriptors, otherwise the f* functions are no good for you. There may be valid reasons why you want to work with the lower levels.
So, if all you have is a descriptor for write, you'll need to format the variable into a string first, with something like:
char buff[100];
sprintf (buff, "%d", val);
write (fd, buff, strlen (buff)); // should check return value.
That's assuming you want it as text. If you want it as a binary value, it's similar to the way we've done it above with the fwrite:
write (fd, &val, sizeof (val)); // should check return value.

Related

Why the write function does not print the 'asd' integer variable? [duplicate]

I'm a noob on C and trying to use write() function to show an integer.
These is my code:
int n = 7;
write(1, &n, 4);
I want to show 7, but the program shows nothing or other strange character when I set n to a big number.
What am I missing?
Objects like int are represented in memory with various bits. The write routine transmits exactly those bits of memory to its destination.
Terminals are not designed to display arbitrary bits of memory. They do not interpret the bits to mean an int or other object and then display that interpretation. Generally, we transmit characters to terminals. More specifically, we send codes that represent characters. Terminals are designed to receive these codes and display little pictures of writing (characters, glyphs, emoji, whatever).
To make a terminal display “7”, we need to send it the code for “7”. A common code system for characters is ASCII (American Standard Code for Information Interchange). The ASCII code for “7” is 55. So, if you do this:
char x = 55;
write(1, &x, 1);
then the terminal will draw “7” on its display, if ASCII is being used.
So write is the wrong routine to use to display int values for a human to read. Instead, you normally use printf, like this:
printf("%d", n);
The f in printf stands for formatted. It examines the bits that represent the value in n and formats the represented value as characters intended for humans to read, and then it writes those characters to standard output.
If you want to use write to transmit characters to the terminal, you can use sprintf to get just the formatting part of printf without the printing part. For starters, this code will work:
char buffer[80]; // Make space for sprintf to work in.
int LengthUsed = sprintf(buffer, "%d", n); // Format n in decimal.
write(1, buffer, LengthUsed); // Write the characters.
(More sophisticated code would adapt the buffer size to what is needed for the sprintf.)
void ft_putnbr_fd(int nu, int fd)
{
long int n;
n = nu;
if (n < 0)
{
ft_putchar_fd('-', fd);
n = n * (-1);
}
if (n < 10)
{
ft_putchar_fd(n + '0', fd);
}
else
{
ft_putnbr_fd(n / 10, fd);
ft_putchar_fd(n % 10 + '0', fd);
}
}
When you want to print it out on the command prompt only use printf() instead:
int n = 7;
printf("%i",n);
Is there a special intention for using the write() function?
If so, please add more of your code.
When you say something like
int n = 7;
write(fd, &n, sizeof(int));
you are taking the individual bytes corresponding to the integer n and writing them out to the file descriptor fd.
And that works just fine, unless what you wanted was a human readable representation of the integer n. That's the representation you'd get if you had instead written
printf("%d\n", n);
It's printf's job, when you use a format specifier like %d, to create a human-readable string of characters corresponding to a data object.
So if you want to print an int in a human-readable way, printf is definitely your best bet. If for some reason you can't use printf, you can use sprintf to create an in-memory string, then use write to write that out:
char tmpbuf[30];
sprintf(tmpbuf, "%d", n);
write(fd, tmpbuf, strlen(tmpbuf));
If for some reason you can't use sprintf, you might be able to use itoa:
char tmpbuf[30];
itoa(n, tmpbuf, 10);
write(fd, tmpbuf, strlen(tmpbuf));
However, the itoa function is not standard. If you don't have it or can't use it, your last resort would be to convert an integer to its string representation yourself, by hand. That's such a common question that I'm not going to provide Yet Another answer to it here, but see the linked question, or this one.
You didn't ask, but if there's ever the related problem of printing a floating point number using write, there are some hints in the comments at this question.
Write function is a system call. It is used to write the content of a buffer to a declared output or to a stream. You should not use write.
Instead, you must be using printf(" ", ...). In your case:
printf("%d", n);
or
print("%d\n",n);
if you want to write it on a line and do an end line(jump the next).
For more information about printf see: printf

How to write integers with write() function in C?

I'm a noob on C and trying to use write() function to show an integer.
These is my code:
int n = 7;
write(1, &n, 4);
I want to show 7, but the program shows nothing or other strange character when I set n to a big number.
What am I missing?
Objects like int are represented in memory with various bits. The write routine transmits exactly those bits of memory to its destination.
Terminals are not designed to display arbitrary bits of memory. They do not interpret the bits to mean an int or other object and then display that interpretation. Generally, we transmit characters to terminals. More specifically, we send codes that represent characters. Terminals are designed to receive these codes and display little pictures of writing (characters, glyphs, emoji, whatever).
To make a terminal display “7”, we need to send it the code for “7”. A common code system for characters is ASCII (American Standard Code for Information Interchange). The ASCII code for “7” is 55. So, if you do this:
char x = 55;
write(1, &x, 1);
then the terminal will draw “7” on its display, if ASCII is being used.
So write is the wrong routine to use to display int values for a human to read. Instead, you normally use printf, like this:
printf("%d", n);
The f in printf stands for formatted. It examines the bits that represent the value in n and formats the represented value as characters intended for humans to read, and then it writes those characters to standard output.
If you want to use write to transmit characters to the terminal, you can use sprintf to get just the formatting part of printf without the printing part. For starters, this code will work:
char buffer[80]; // Make space for sprintf to work in.
int LengthUsed = sprintf(buffer, "%d", n); // Format n in decimal.
write(1, buffer, LengthUsed); // Write the characters.
(More sophisticated code would adapt the buffer size to what is needed for the sprintf.)
void ft_putnbr_fd(int nu, int fd)
{
long int n;
n = nu;
if (n < 0)
{
ft_putchar_fd('-', fd);
n = n * (-1);
}
if (n < 10)
{
ft_putchar_fd(n + '0', fd);
}
else
{
ft_putnbr_fd(n / 10, fd);
ft_putchar_fd(n % 10 + '0', fd);
}
}
When you want to print it out on the command prompt only use printf() instead:
int n = 7;
printf("%i",n);
Is there a special intention for using the write() function?
If so, please add more of your code.
When you say something like
int n = 7;
write(fd, &n, sizeof(int));
you are taking the individual bytes corresponding to the integer n and writing them out to the file descriptor fd.
And that works just fine, unless what you wanted was a human readable representation of the integer n. That's the representation you'd get if you had instead written
printf("%d\n", n);
It's printf's job, when you use a format specifier like %d, to create a human-readable string of characters corresponding to a data object.
So if you want to print an int in a human-readable way, printf is definitely your best bet. If for some reason you can't use printf, you can use sprintf to create an in-memory string, then use write to write that out:
char tmpbuf[30];
sprintf(tmpbuf, "%d", n);
write(fd, tmpbuf, strlen(tmpbuf));
If for some reason you can't use sprintf, you might be able to use itoa:
char tmpbuf[30];
itoa(n, tmpbuf, 10);
write(fd, tmpbuf, strlen(tmpbuf));
However, the itoa function is not standard. If you don't have it or can't use it, your last resort would be to convert an integer to its string representation yourself, by hand. That's such a common question that I'm not going to provide Yet Another answer to it here, but see the linked question, or this one.
You didn't ask, but if there's ever the related problem of printing a floating point number using write, there are some hints in the comments at this question.
Write function is a system call. It is used to write the content of a buffer to a declared output or to a stream. You should not use write.
Instead, you must be using printf(" ", ...). In your case:
printf("%d", n);
or
print("%d\n",n);
if you want to write it on a line and do an end line(jump the next).
For more information about printf see: printf

Alternatives of fopen, fread for reading from string?

I have a code which integrates with a certain library I cannot modify and reads from file. I need to turn it into reading from string instead of from file.
string str = "I now have the string from file.txt in memory";
// original code:
FILE *file = fopen("file.txt", "rb");
// ...
uint8_t buffer[128];
// ...
var->var1 = buffer;
// ...
var->var2 = fread(buffer, 1, 128, file);
// ...
So a simple question, what's an alternative for fread for reading from string into buffer?
Platform: Windows
If you don't require a FILE *, if you just need to copy counted characters from one buffer (or string) to another, that's what memcpy is for. For example, to a first approximation, you could replace
fread(buffer, 1, 128, file);
with
memcpy(buffer, str, 128);
Now, this will break pretty badly if str does not contain 128 characters. (If your file had less than 128 characters on it, fread would give you less than 128.) So a safer replacement would be
int n = 128;
if(strlen(str) < n) n = strlen(str);
memcpy(buffer, str, n);
There is a function that does precisely what you want: fmemopen. You hand it a pointer to an in-memory string buffer, and a "r" or "w" flag (just like fopen), and it gives you a regular old FILE * that you can read from or write to -- or, in your case, pass to a function that needs a FILE * to read from or write to.
It's available in glibc and therefore in virtually all versions of Linux. I think it's available in some versions of Unix. I don't seem to have it on my Mac. I'm afraid you'll probably have a hard time finding it for Windows.
If i understand your task correctly, you need to get information out of a string as if they would been written from a file. A very comfortable way to solve that is std::stringstream, if you are using C++.

How to wrap fscanf() using only fread() and vsscanf()

I'm porting some code on an embedded platform that uses a C-like API. The original code uses fscanf() to read and parse data from files. Unfortunately on my API I don't have a fscanf() equivalent, so prior to the actual porting I'm trying to obtain the same behavior of fscanf() using fread() and vsscanf() (which I do have). I also have the equivalent of fseek() and ftell().
EDIT: please keep in mind that the access to the embedded filesystem is very limited (fread - fseek - ftell - fgetc - fgets), so I need a solution that works with strings in memory rather than accessing the file in some other way.
The code looks something like this:
int main()
{
[...] /* variable declarations and definitions */
do
{
read = wrapped_fscanf(pFile, "%d %s", &val, str);
} while (read == 2);
fclose(pFile);
return 0;
}
int wrapped_fscanf(FILE *f, const char *template, ...)
{
va_list args;
va_start(args, template);
char tmpstr[50];
fread(tmpstr, sizeof(char), sizeof(tmpstr), f);
int ret = vsscanf(tmpstr, template, args);
long offset = /* ??? */
fseek(f, offset, SEEK_CUR);
va_end(args);
return ret;
}
The problem is that fscanf() moves the pointer to the position in the file stream at the end of the match, whereas with fread() I'm reading a fixed amount of data (in this case 50 bytes) and I should find a way to move the pointer back to the end of the matched string.
Let's assume that the 50-char string I read from the file is the following:
12 bar 13 foo 56789012345678901234567890123456789
fscanf() would match the int 12 , the string bar and the pointer would point right after the "r" in "bar" so I can call it again and read 13 foo
On the other hand fread() puts the pointer after the last char in the 50-element sequence, which is wrong: I still have to read 13 foo but if I call wrapped_fscanf() again the pointer is in the 51st position.
I have to use fseek() to roll back to the end of the first match, but how do I do that? How do I calculate the value of offset ?
vsscanf() returns the number of matches, not the length of the string and I have no way of knowing how many whitespace charachters separate the elements of the match (or do I?)
I.e. I get the same outputs( {var,str,read} == {9,"xyz",2} ) with
9 xyz
and
9 xyz
Is there some trick that I'm not aware of or do I have to find another solution other than wrapping fscanf() with fread() vsscanf() ftell() and fseek()?
Thank you
Supposing that your vsscanf() implementation supports it, your substitute for fscanf() can append a %n field descriptor to the end of the provided format. As long as there is no failure prior to vsscanf() reaching that field, it will store the number of characters consumed up to that point in the corresponding argument. You could then use that result to reposition the stream appropriately. That would require a bit of varargs wrangling and probably some macro assistance, but I think it could be made to work.
You will need some intermediary buffering code, that will grab chunks of data (using fread), and scan your buffer for the pattern. if the pattern is found, truncate the buffer, if the pattern is not found, append some more data. this is effectively what fscanf will do.

write() bad address

I am trying to write out the size in bytes of a string that is defined as
#define PATHA "/tmp/matrix_a"
using the code
rtn=write(data,(strlen(PATHA)*sizeof(char)),sizeof(int));
if(rtn < 0)
perror("Writing data_file 2 ");
I get back Writing data_file 2 : Bad address
What exactly about this is a bad address? The data file descriptor is open, and writes correctly immediately before and after the above code segment. The data to be written to the file data needs to be raw, and not ASCII.
I have also tried defining the string as a char[] with the same issue
The second argument to write() is the address of the bytes you want to write, but you are passing the bytes you want to write themselves. In order to get an address, you must store those bytes in a variable (you can't take the address of the result of an expression). For example:
size_t patha_len = strlen(PATHA);
rtn = write(data, &patha_len, sizeof patha_len);
The arguments to POSIX write() are:
#include <unistd.h>
ssize_t write(int fildes, const void *buf, size_t nbyte);
That's a:
file descriptor
buffer
size
You've passed two sizes instead of an address and a size.
Use:
rtn = write(data, PATHA, sizeof(PATHA)-1);
or:
rtn = write(data, PATHA, strlen(PATHA));
If you are seeking to write the size of the string as an int, then you need an int variable to pass to write(), like this:
int len = strlen(PATHA);
rtn = write(data, &len, sizeof(len));
Note that you can't just use a size_t variable unless you want to write a size_t; on 64-bit Unix systems, in particular, sizeof(size_t) != sizeof(int) in general, and you need to decide which size it is you want to write.
You also need to be aware that some systems are little-endian and others big-endian, and what you write using this mechanism on one type is not going to be readable on the other type (without mapping work done before or after I/O operations). You might choose to ignore this as a problem, or you might decide to use a portable format (usually, that's called 'network order', and is equivalent to big-endian), or you might decide to define that your code uses the opposite order. You can write the code so that the same logic is used on all platforms if you're careful (and all platforms get the same answers).
The second argument to write() is the buffer and third argument is the size:
ssize_t write(int fd, const void *buf, size_t count);
The posted code passes the length which is interpreted as an address which is incorrect. The compiler should have emitted a warning about this (don't ignore compiler warnings and compile with the warning level at the highest level).
Change to:
rtn=write(data, PATHA, strlen(PATHA));
Note sizeof(char) is guaranteed to be 1 so it can be omitted from the size calculation.
The Bad address error has already been answered. If you want to write the size of a string just use printf.
printf("Length: %d\n", strlen(data));
Either that, or you can write a function that will convert an integer to a string and print that out... I prefer printf :)
rtn = write(data, PATHA, strlen(PATHA));
is what you want I think. Arguments are supposed to be
file descriptor (data)
the source buffer (your string constant PATHA)
The number of bytes to pull from that buffer (measured using strlen() on the same PATHA constant)
Also, to be complete, you should always check rtn for how many characters you've written. You're not guaranteed that you write() all the bytes requested on all descriptor types. So sometimes you end up writing it in chunks, determined by the amount it answers that it wrote, vs how many you know you have yet to write still then.

Resources