Jump to content

How to use write() in the same way as printf()

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
12 replies to this topic

#1
gkons

gkons

    Newbie

  • Members
  • Pip
  • 5 posts
As part of an assignment I have written these two lines of code in eclipse under linux environment

childpid=getpid();
printf("I am the child and my id is: %d",childpid);

I want to do the same thing using the function write() instead of printf()
but as I figured out write() doesn't work in the same way as printf(). :(
For example if I have an integer number stored in a variable x and write for example
write(1,&x,1) what I get in stdout is not readable?!!
I suppose that the value of the variable is stored in a different form and somehow I have to transform it in order to display it in a readable form.

If anyone has an idea and could help me with this, I would appreciate it!

#2
Walle

Walle

    Learning Programmer

  • Members
  • PipPipPip
  • 75 posts
Look at the declaration for "write". ostream& write ( const char* s , streamsize n );

As you thought, you can't pass an int. You need to pass is a pointer pointing to a data buffer of type char. Also, you need to pass the size of the buffer.

The "printf" is very special in one way, as it basicly doesn't care much for what you point it. Passing extra parameters, that are not specified in the format string, normally works just fine. The opposite use to work also, i think.
________________________________________________
"I'm not young enough to know everything." - Oscar Wilde

#3
TkTech

TkTech

    The Crazy One

  • Moderators
  • 1,396 posts
I believe you're looking for fprintf(), not write()...

#4
gkons

gkons

    Newbie

  • Members
  • Pip
  • 5 posts
Thank you very much for your answers!
The reason why I use write() is because that's what I am asked to do by my professor, "write the code using write(), without using any functions from the family of printf()).Otherwise things would be easier, but in the end the teachers are to make the life of the students difficult :). Anyway, I forgot to mention that my code is written in C and not C++.
The declaration of write as I found it is
write(int fd, const void *buf, size_t count);
What I don't get is that the second argument of write() is pointer to data, so normally I shouldn't bother what type of data it is. I should be able to send characters, strings, as well as integers. In my code a parent process passes an array of integers to a child process and then the child prints it to the stdout.
When I use the command
write(1, &readbuffer, sizeof(readbuffer) / sizeof(int));
what I get is something like this "�Lw�薨��"
I think Walle that there should be a way to print an integer in a readable form, otherwise the professor wouldn't ask it from me.
Anyway, thank you again for your answer!

#5
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
write() isn't too hard to figure out:
write(1, "Hello World!\n", 13);
The first number is the file descriptor, and 0, 1, and 2 are standard file descriptors meaning stdin, stdout, and stderr respectively. You can also use open() to get another file descriptor from your OS, see below:
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
    int the_file = open("testfile", O_WRONLY | O_CREAT | O_APPEND, 
                        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    write(the_file, "Hello World!\n", 13);
    close(the_file);
    return 0;
}
When you send an "integer", that integer DOES NOT, and CAN NOT convert to the characters you probably expect it to. You'll need to do that manually in your own function if you don't have access to sprintf(). This isn't terribly difficult to do with a couple loops, something like this:

char* itoa(char* buffer, int val, size_t sz)
{
    char inbuf[sz];
    char check;
    int iii;
    for (iii = 0; val; ++iii, val = val / 10)
    {
        check = val % 10;
        inbuf[iii] = '0' + check;
    }
    inbuf[iii] = '\0';
    buffer[iii--] = '\0';

    for (int jjj = 0; iii >= 0 && jjj < sz; ++jjj, --iii)
        buffer[jjj] = inbuf[iii];

    return buffer;
}
Then when you write the values it should come back properly.
Wow I changed my sig!

#6
gkons

gkons

    Newbie

  • Members
  • Pip
  • 5 posts
Thank you ZakeDragon for your answer, it was bery illuminating!
I also looked in a library and I found a similar itoa version in the book "ANSI C" from Kernighan and Ritchie...the code was...

void itoa (int n, char s[])
{
       int i, sign;
       if ((sign=n)<0)
               n=-n;
       i=0;
       do {
              s[i++]=n%10+'0';
       }  while  ((n/=10)>0);
       if  (sign<0)
              s[i++]='-';
       s[i]='\0';
       reverse(s);
}

The main difference I see is that this solution takes the sign of the integer into account as well, but is this necessary? Anyway I will check both solution.
Thank you again!

#7
John

John

    Writes binary right handed and hex left handed

  • Moderators
  • 6,321 posts
It is necessary if you intend on converting negative numbers to a string.

#8
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
char* itoa(char* buffer, int val, size_t sz)
{
    char rev, sign = 0;
    int iii;

    if (val < 0)
    {
        val = -val;
        sign = 1;
        buffer[0] = '-';
    }

    for (iii = sign; val && iii < sz; ++iii, val /= 10)
        buffer[iii] = '0' + (val % 10);

    buffer[iii--] = '\0';

    for (int jjj = sign; iii > jjj; ++jjj, --iii)
    {
        rev = buffer[iii];
        buffer[iii] = buffer[jjj];
        buffer[jjj] = rev;
    }

    return buffer;
}
I don't have a convenient "reverse" function to shorten my code, thus the need for two for loops. This is a bit more stable and uses less memory. I don't know which would be more "efficient", but I do know that the K&R version would require a call to strlen() in the reverse() implementation, so there could very well be 3 loops instead of just 2.
Wow I changed my sig!

#9
gkons

gkons

    Newbie

  • Members
  • Pip
  • 5 posts
I tried this and worked perfect

void reverse(char s[])
{
        int c, i, j;
        for (i=0, j=strlen(s)-1;  i<j; i++, j--)
        {
              c=s[i];
              s[i]=s[j];
              s[j]=c;
         }
}
for the itoa() function I used the one from the book.
And my main function to test it was

int main()
{ 
       int s=-5;
       static char d[10];
       itoa(s,d);
       write(1,d,sizeof(d));
}

But now I have other problems with write()- Oh god I hate this function
For example in the below code:
int main()
{
       int s=-5;
       int g=6;
       static char d[10]; 
       static char h[10];
       itoa(s,d);
       itoa(g,h);
       write(1,d,sizeof(d));
       write(1,h,sizeof(h));
}

When I run it in stdout I get only the number -5!!!
Why is this happening and I don't get the number 6 as well!!
That is an other difference with printf!
If you have an answer to this too, you'll become my c saviour :)

#10
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
I wouldn't use sizeof() for that, since it measures the SIZE of the array (10), instead I'd use strlen(), which gets the length of the string.

    write(1, d, strlen(d));
    write(1, "\n", 1);
    write(1, h, strlen(h));
    write(1, "\n", 1);

When I tested it I experienced no problems, however.
Wow I changed my sig!

#11
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
>_<

Edited by ZekeDragon, 14 January 2010 - 05:05 AM.
Stupid dumb double post problem thing stupid...

Wow I changed my sig!

#12
gkons

gkons

    Newbie

  • Members
  • Pip
  • 5 posts
Yes my friend you are right!It worked fine! With sizeof there were problems, but with strlen is perfect. The conclusion is that with c the detail is very important :)
Thank you again!