Md Soman Khan
Md Soman Khan

Reputation: 25

What is the use of `putw` and `getw` function in c?

I wanna know the use of putw() and getw() function. As I know, these are used to write and read from file as like as putc and getc but these deals with only integers. But when I use these for writing integers, it just write different symbol in file (like if I write 65 to file using putw(). It writes A in the file). Why does it take the ASCII value? I am using codeblocks 13.12. Code:

#include <stdio.h>

int main() {
    FILE *fp;
    int num;

    fp = fopen("file.txt", "w");
    printf("Enter any number:\n");
    scanf("%d", &num);
    putw(num, fp);
    fclose(fp);
    printf("%d\n", num);

    return 0;
}

Upvotes: 1

Views: 21051

Answers (4)

DrSheldon
DrSheldon

Reputation: 659

Beware! The Linux implementation is completely different from the original AT&T definition!

What putw and getw are:

  • A quick hack to write ints to a file, and read them back on the same machine.

They have many compatibility issues:

  • They depend on the size of an int, which is not standardized.

  • Implementations differ on whether they produce human-readable text, or binary.

  • There is no guarantee on the byte order of what is produced. Maybe it is the processor's endianness, maybe it is network byte order.


Both functions are listed in my copy of The C Programmer's Handbook, written by AT&T Bell Laboratories in 1984. This is after the 1st edition of K&R, but before the first ANSI C standard and the 2nd edition of K&R. At that point in history, even basic measures of compatibility between machines (such as size_t, INT_MAX, and int32_t) did not yet exist.

These functions appear on page 50 in a section titled "WORD I/O":

C Programmer's Handbook page 50

Notice that it states that getw accepts "characters delimited by whitespace". This means that the AT&T implementation uses text (not binary) format. The format (decimal, hexadecimal, etc) of the text is unclear.


On my Linux machine, putw and getw are clearly using binary file format. My test program:

#include <stdio.h>

int main()
{
    putw('T', stdout);
    putw('e' + 's'*256, stdout);
    putw('t' + 'i'*256 + 'n'*65536 + 'g'*256*65536, stdout);
    printf("!\n");
    while (!feof(stdin)) {
        printf("getw=%08X, ", getw(stdin));
        printf("ferror=%d\n", ferror(stdin));
    }
    printf("===Done===\n");
}

and its output:

Testing!
1234
getw=34333231, ferror=0
4321
getw=3233340A, ferror=0
getw=FFFFFFFF, ferror=0
===Done===

Notice that -- unlike the AT&T implementation -- it is not delimiting with whitespace (note the newline of the input appears as a 0x0A byte). I'm willing to bet that it's merely a call to fwrite(&w, sizeof(int), 1, stream). In fact, the man page suggests using fwrite instead!

The man page also claims that is in Linux for compatibility with Sys V Release 4, which came out in 1988. However, as you can see above, files produced by AT&T SVR4 will not be compatible with Linux's version of getw.

Upvotes: 0

Nate Eldredge
Nate Eldredge

Reputation: 58715

If num is an int, then putw(num, fp) is equivalent to fwrite(&num, sizeof(int), 1, fp), except for having a different return value. It writes an int to the file in binary format. getw is similar but with fread instead. You can see how glibc implements them: putw,getw.

This means that:

  • They are not appropriate for writing text. If you want to write a number to a file in human-readable decimal or hexadecimal format, use fprintf instead.

  • They typically read/write more than one byte (one character) to the file. For instance, on a machine with 32-bit ints, they will read/write four bytes. Attempting to do putw('c') will not simply write the single character 'c'.

  • They should only be used with files opened in binary mode (if that makes a difference on your system).

  • You should not expect the contents of the file to be human-readable at all. If you attempt to view the file in an editor, you'll see the representation of whatever bytes are in the file, in your current character set (e.g. ASCII).

  • You should not expect the file to be successfully read back on another computer that uses a different internal representation for int (e.g. different width, different endianness).

On a typical system with 32-bit little-endian int, putw(65, fp) will result in the four bytes 0x41 0x00 0x00 0x00. The 0x41 (decimal 65) is the ASCII code for the character A, so you'll see that if you view it. The 0x00 bytes may or may not be displayed at all, depending on what you are using to view.

These function are not a good idea to use in new code. Even if you do need to store binary data in files, which has various disadvantages as noted and should usually only be done if there is a very good reason for it, you should simply use fwrite and fread. getw/putw are a worse option because:

  • They will make your code less portable. fwrite/fread are part of the ISO C standard, which is the most widely supported cross-platform modern standard for the C language. getw/putw were present in the Single Unix Specification v2 version 2, which dates to 1997 and is now obsolete. They were not included in the POSIX/SUSv3 specs which superseded SUSv2, and it would be unwise to count on them being available on new systems.

  • They will make your code less readable. Since fread/fwrite are far more widely used, another programmer reading your code will recognize immediately what they do. Since getw/putw are more obscure, people are likely to have to go and look them up, and the names don't make it easy to remember that they operate specifically on the type int. Readers may also confuse them with the similarly-named ISO-standard functions getwc/putwc. So using getw/putw makes your code less readable.

  • They may introduce subtle bugs. getw returns EOF on end-of-file or error, but EOF is a valid integer value (often -1). Therefore, if it returns this value, you cannot easily tell whether the file actually contained the integer -1, or whether the read failed. And since this only happens for one particular value, it may be missed in testing. You can check ferror() and feof() to distinguish the two cases, but this is awkward, easy to forget to do, and negates most of the apparent convenience of the "simpler" interface of getw compared to fread.

I speculate that the only reason these functions existed in the first place is that, like putc (respectively getc), putw could be implemented as a macro that directly wrote the buffer of fp and would thus be a little more efficient than calling fwrite. Such an implementation is no longer feasible on modern systems, since it wouldn't be thread-safe, so putw needs a function call anyway. In fact, with glibc in particular, putw just calls fwrite after all, with the overhead of an additional function call, so it's now less efficient. So there is no longer any reason at all to use these functions.

Upvotes: 4

Rakesh Vekariya
Rakesh Vekariya

Reputation: 574

Let's read the point to point explanation of getw() and putw() functions.

  • getw() and putw() are related to FILE handling.
  • putw() is use to write integer data on the file (text file).
  • getw() is use to read the integer data from the file.
  • getw() and putw() are similar to getc() and putc(). The only difference is that getw() and putw() are especially meant for reading and writing the integer data.

int putw(integer, FILE*);

Return type of the function is integer.

Having two argument first "integer", telling the integer you want to write on the file and second argument "FILE*" telling the location of the file in which the data would be get written.

Now let's see an example.

int main()
{
    FILE *fp;

    fp=fopen("file1.txt","w");
    putw(65,fp);

    fclose(fp);
}

Here putw() takes the integer number as argument (65 in this case) to write it on the file file1.txt, but if we manually open the text file we find 'A' written on the file. It means that putw() actually take integer argument but write it as character on the file.

So, it means that compiler take the argument as the ASCII code of the particular character and write the character on the text file.


int getw(FILE*);

Return type is integer.

Having one argument that is FILE* that is the location of the file from which the integer data to be read.

In this below example we will read the data that we have written on the file named file1.txt in the example above.

int main()
{
  FILE *fp;
  int ch;

  fp=fopen("file1.txt","r");

  ch=getw(fp);
  printf("%d",ch);

  fclose(fp);
}

output

65

Explanation: Here we read the data we wrote to file1.txt in above program and we will get the output as 65.

So, getw() reads the character 'A' that was already written on the file file1.txt and return the ASCII code of the character 'A' that is 65.

We can also write the above program as:

int main()
{
   FILE *fp;

   fp=fopen("file1.txt","r");

   printf("%d",getw(fp));

  fclose(fp);
}

output

65

Upvotes: 7

Karthikeyan.R.S
Karthikeyan.R.S

Reputation: 4041

From the man page of putw() and getw()

getw() reads a word (that is, an int) from stream. It's provided for compatibility with SVr4.

putw() writes the word w (that is, an int) to stream. It is provided for compatibility with SVr4.

You can use the fread and fwrite function for better use.

getw() reads the integer from the given FILE stream.

putw() it write the integer given in the first argument into the file pointer.

getw:

It will read the integer from the file. like getchar() doing the work. Consider the file having the content "hello". It will read the h and return ascii value of h.

putw:

It will place the given integer, integer taken as a ascii value. Corresponding value of the ascii value placed in the file. like putchar()

Upvotes: 0

Related Questions