How to write integers with write() function in C? - 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

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 read and print hexadecimal numbers from a file in C

I'm trying to read 14 digit long hexadecimal numbers from a file and then print them. My idea is to use a long long int and read the lines from the files with fscanf as if they were strings and then turn the string into a hex number using atoll. The problem is I am getting a seg value on my fscanf line according to valgrind and I have absolutely no idea why. Here is the code:
#include<stdio.h>
int main(int argc, char **argv){
if(argc != 2){
printf("error argc!= 2\n");
return 0;
}
char *fileName = argv[1];
FILE *fp = fopen( fileName, "r");
if(fp == NULL){
return 0;
}
long long int num;
char *line;
while( fscanf(fp, "%s", line) == 1 ){
num = atoll(line);
printf("%x\n", num);
}
return 0;
}
Are you sure you want to read your numbers as character strings? Why not allow the scanf do the work for you?
long long int num;
while( fscanf(fp, "%llx", &num) == 1 ){ // read a long long int in hex
printf("%llx\n", num); // print a long long int in hex
}
BTW, note the ll size specifier to %x conversion in printf - it defines the integer value will be of long long type.
Edit
Here is a simple example of two loops reading a 3-line input (with two, no and three numbers in consecutive lines) with a 'hex int' format and with a 'string' format:
http://ideone.com/ntzKEi
A call to rewind allows the second loop read the same input data.
That line variable is not initialized, so when fscanf() dereferences it you get undefined behavior.
You should use:
char line[1024];
while(fgets(line, sizeof line, fp) != NULL)
To do the loading.
If you're on C99, you might want to use uint64_t to hold the number, since that makes it clear that 14-digit hexadecimal numbers (4 * 14 = 56) will fit.
The other answers are good, but I want to clarify the actual reason for the crash you are seeing. The problem is that:
fscanf(fp, "%s", line)
... essentially means "read a string from a file, and store it in the buffer pointed at by line". In this case, your line variable hasn't been initialised, so it doesn't point anywhere. Technically, this is undefined behavior; in practice, the result will often be that you write over some arbitrary location in your process's address space; furthermore, since it will often point at an illegal address, the operating system can detect and report it as a segment violation or similar, as you are indeed seeing.
Note that fscanf with a %s conversion will not necessarily read a whole line - it reads a string delimited by whitespace. It might skip lines if they are empty and it might read multiple strings from a single line. This might not matter if you know the precise format of the input file (and it always has one value per line, for instance).
Although it appears in that case that you can probably just use an appropriate modifier to read a hexadecimal number (fscanf(fp, "%llx", &num)), rather than read a string and try to do a conversion, there are various situations where you do need to read strings and especially whole lines. There are various solutions to that problem, depending on what platform you are on. If it's a GNU system (generally including Linux) and you don't care about portability, you could use the m modifier, and change line to &line:
fscanf(fp, "%ms", &line);
This passes a pointer to line to fscanf, rather than its value (which is uninitialised), and the m causes fscanf to allocate a buffer and store its address in line. You then should free the buffer when you are done with it. Check the Glibc manual for details. The nice thing about this approach is that you do not need to know the line length beforehand.
If you are not using a GNU system or you do care about portability, use fgets instead of fscanf - this is more direct and allows you to limit the length of the line read, meaning that you won't overflow a fixed buffer - just be aware that it will read a whole line at a time, unlike fscanf, as discussed above. You should declare line as a char-array rather than a char * and choose a suitable size for it. (Note that you can also specify a "maximum field width" for fscanf, eg fscanf(fp, "%1000s", line), but you really might as well use fgets).

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

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.

Value returned by atoi can not be printed

Before I present the code, a little background: I have a character pointer array by the name math, now, in the while loop I am trying to convert the value in math to an int using atoi and saving it in an int variable ai. There are no compilation errors. However, when I try to print ai it is not printing it. Somehow the program runs without crashing. I can't figure out what the issue is and if there is an issue the program should crash on atoi and if there is no issue then it should print ai.
The code goes like this:
int c1 = 3; //the array contains 3 characters 1 2 3
int c2 = 0;
while(c2 < c1)
{
int ai;
ai = atoi(math[c2]);
// the array is valid, I have checked it time and again so is the content in array
write(STDOUT_FILENO,math[c2],1); //this works fine.
write(STDOUT_FILENO,&ai,sizeof(&ai));
//this doesn't print anything and somehow loop goes on to meet
//the condition.
c2++;
}
Remember that write is not printf. So
write(STDOUT_FILENO,&ai,sizeof(&ai))
will write sizeof(int) pieces of characters, to STDOUT; if we assume a 32-bit int, it will print the characters corresponding in the ASCII codetable to (ai >> 24) & ff, (ai >> 16) & ff, (ai >> 8) & ff and (ai >> 0) & ff, which is possibly four non-printable characters.
If you want to write the integer's string representation to the console, use:
printf("%d", ai);
instead.
Considering your additional information
its a multiprocessed client server modeled code using sockets
You probably have some additional magic in STDOUT_FILENO. Consider using fdopen, fprintf, fflush instead of the (absolutely incorrect) write and (possibly incorrect) printf.
Like so:
FILE* f = fdopen(STDOUT_FILENO, "w");
fprintf(f, "%d", ai);
fflush(f);
...
fclose(f); // also closes the socket
write(STDOUT_FILENO,&ai,sizeof(&ai));
writes the bitpattern of ai to stdout but uses the length of the address of ai and not the length of ai. On modern machines these are usually different values 4 versus 8, so you are writing arbitrary garbage or even produce an access error.
This is probably not what you want, anyhow.
If you want to write your number as a readable string to stdout use something like
write(STDOUT_FILENO, math, strlen(math));
math has already the character representation that you want to see on stdout.
If you really want to pump the bitrepresentation of ai out there use
write(STDOUT_FILENO, &ai, sizeof ai);

One liner to find length of a variable

I just stumbled upon the idea that since printf returns the no.of characters it has printed to the output stream why not use it to find length of any variable in c?
The code goes something like this,
#include<stdio.h>
int main()
{
char *a="Length";
int i=1000;
printf("Size: %d\n",printf("%d\n",i)-1);
printf("String Size: %d",printf("%s\n",a)-1);
return 1;
}
Am I right? I am not concerned about where it is being used. just wanted to know if my understanding is right.
What do you mean by "length of any variable"? You mean the number of bytes used to store the variable (which better achieved with the sizeof and strlen functions) or the byte length of the string representation of the variables?
For the latter one, you should be careful, since you can use format options to actually modify the results. Consider the following example:
float num = 10.0f;
printf("%.10f", num); // return value should be 13
printf("%f", num); // return value depends on the implementation of printf and the float value supplied
Also you have to consider that there are other representations than the decimal one.
As others have already stated, printf has the side effect that it actually writes to stdout. If you do not want this, you can use snprintf to write to a buffer and not to stdout:
char buffer[256];
int x = 10;
snprintf(buffer, sizeof(buffer), "%d", x); // return value is '2'
"One liner to find length of a variable"
Not possible unless its builtin to your compiler, or you define a wild and hairy macro half a page long with a few enums to state your type...
For strings, (which you cannot use sizeof on...) see: https://stackoverflow.com/a/22128415/3370790

Resources