I know that printf returns a negative error or number of characters printed on success. Only reason to check this return value is if the execution of program somehow depends on the printf status. But I could not think of a scenario where this return value is useful. I, for one, have never checked the return value of printf function.
What are the scenarios where return status from printf is useful?
There are at least 2 uses of the return value of printf:
To check for errors. This is rarely important when your output is interactive or purely informative, but for programs that are processing text from stdio or a file and writing the result to stdout, it's important to know whether an error (such as disk full, closed pipe, or dropped network connection) prevented the entire output from being written. This is especially important if the source file will be deleted/replaced by the output once the output is complete. However, due to buffering, checking the result of printf itself is usually not helpful. You'll want to check ferror(stdout) after writing the last output and flushing in order to get a reliable indication of whether any write errors occurred. On the other hand, checking the return value of printf allows you to detect failure early so you don't waste time attempting to write millions of lines when the first line already failed, so it can be a very useful check; it's just not a sufficient check by itself.
If the number of characters output is not obvious, you may want to know how many characters were written. A naive usage of this number would be for lining up columns, but assuming characters have fixed width in their visual presentation is rather antiquated. It might make sense if you were formatting source code, though. Another similar usage (not sure whether this is less or more antiquated) is writing fixed-width fields in a file. For example, if your fields are 80 bytes and printf returned 52, you'd want to write 28 more padding bytes to finish off the field.
There are a couple of situations in which you might want to check the return value of printf. One is to check for errors, as you mention; while there's usually nothing you can do if there's an error on printf, you may, if you're printing something really big, and get an error, decide to try printing it in smaller chunks.
You may also be interested in how wide the output was; printf() returns the number of characters written on success. If you are trying to line up output, and you do a printf() with something of variable width, you can check the return value to find out how many characters were printed, so you know what column you are on. Of course, this only works if all of your characters are 1 column wide (which is true of most ASCII characters), but there are some cases in which this might be useful.
snprintf() prints to a fixed-size buffer instead of stdout or a file. It will only print up to the size of the buffer that you give it; but it's possible that it would require more space to print the full string. It returns the amount of space it would have needed to print the full string; this way, you can use the return value to allocate a new buffer of the appropriate size, and try again, if your original buffer was too small. You almost always use the return value of snprintf(), for this reason.
One of the main reasons why this is used is for troubleshooting. Printf can be used to also write to a file (not only STDOUT). Ensuring that all the charachters have been writen to the file is crucial in some applications. An example of this can be found below:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
printf("This will display on the screen.\n");
if((fp=freopen("OUT", "w" ,stdout))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
if( printf("This will be written to the file OUT.") < 0){
return -1;
}
fclose(fp);
return 0;
}
You might ask why you should use printf to print a file. Consider this. Some software was developed that had no error logging implemented but instead used printf. A knowledgeable C programmer can redirect the output of printf to a file at the top of the code and thus implement error logging to a file instead of STDOUT. At this point he can use the return value of printf to ensure that the these errors were printed correctly.
It is mostly for the purposes of error checking. You can make sure that the operation was successful or not using the return value.
If a non-negative value is returned (indicating the number of characters written) it means the operation was successful. If a negative number is returned there was some error.
For example,
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int result = printf("This is a test!");
if (result > 0)
{
printf("%d characters were written!", result);
return EXIT_SUCCESS;
}
else return EXIT_FAILURE;
}
I, too have never used the return value.
But beside the error check, you might count the number of characters which have been output, to make some sort of statistic, or limitation
in some cases, printf is only able to put a part of your string into stdout, and this is not an error.
if you have to be sure that your string is sended complete, you could use the return value to see this.
its mos useful when working with fprintf and sockets, etc. but still could be useful.
Related
I am trying to read a time like data (i.e. 10:55) from a text file and assign it in such a way that I can do calculations with it. For instance if I want to covert 10 hrs and 55 minutes from 10:55 into minutes:
10*60+55=655. But 10:55 contains ':' so I can't directly assign it to an integer.
So far I was able to solve this problem using atoi(char *ptr)function which coverts the numbers inside a string into integer type data.The code is running just fine but I am not sure how this function works. Because the string "10:55" contains a non numeric value so shouldn't it return junk value immediately when it detects ":".But in my case it returns 10 and then, after I shifted the pointer by 3 places it gives 55.
So it will be really helpful if someone elaborates how this function exactly works.
Finally is there any other way of solving this problem without using atoi() function and only using basic C programming techniques. If yes then please share your code and explanation with me.Thanks a lot for helping. Here is my code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int hh,mm;
char startingtime[6];
int strtimearr[2];
FILE *start=fopen("start.txt","w");
if(start==NULL)
{
printf("FILE DOES NOT EXIST");
}
printf("START TIME\n");
printf("->HOUR(hh):");
scanf("%d",&hh);
printf("->MINUTE(mm):");
scanf("%d",&mm);
fprintf(start,"%d:%d",hh,mm);
fclose(start);
start = fopen("start.txt", "r");
if(start==NULL)
{
printf("FILE DOES NOT EXIST");
}
fscanf(start, "%s", startingtime);
fclose(start);
//puts(startingtime);
char *s1= startingtime;
strtimearr[0] = atoi(s1);
strtimearr[1] = atoi(s1+3);
printf("Time : %d:%d \nconverted to minute : %d",strtimearr[0],strtimearr[1],(strtimearr[0]*60+strtimearr[1]));
}
It works but is not robust. If the user gives a number greater than 99 for hour or minute, you will write more than 5 bytes to the file. Then at read time you will read past end of startingtime array invoking Undefined Behavious. On the other hand, if hour is less than 10, the minute field will start at position 2 and not 3.
For IO, the rule is be strict when writing and tolerant when reading. So I advise you to use a stricter format for writing: fprintf(start,"%2d:%02d",hh,mm); or fprintf(start,"%02d:%02d",hh,mm); to be consistent for values less than 10.
At read time, you could at least limit size with fscanf(start, "%5s", startingtime); and then decode with sscanf:
int cr = sscanf(startingtime, "%d:%d", strtimearr, strtimearr+1);
Or directly decode at read time with fscanf:
int cr = fscanf(start, "%d:%d", strtimearr, strtimearr+1);
and control that cr is 2 before printing the result.
How to read a time like “10:55” from a text file
You could use fscanf, or combine fgets (or maybe getline(3) or even on Linux readline(3) ...) and sscanf or strtol but then don't forget to test its return value (some int for fscanf etc...). You might be interested by the %n format control string directive to fscanf or sscanf(3) ....
You could, on POSIX or Linux systems, use time(7) facilities. So #include <time.h> then use strptime(3) or getdate(3).
You could read byte by byte and use fgetc. Check for error conditions (at least EOF). Be aware of UTF-8, in 2020 it is almost everywhere ....
Don't forget to check for parsing errors.
A time like 123:456 in your text file probably don't make sense, and you should check for such input mistakes (and probably give at least the line number where such an input does not make sense).
Read at least about errno(3) and perror(3)
Your program should use perror or strerror(3) when fopen fails. Be also aware that stdout is usually line buffered (except in command pipelines). Consider using fflush and/or setvbuf.
Read of course how to debug small programs and what every C programmer should know about undefined behavior. Consider reading the C11 standard n1570 ...
Enable all warnings and debug info when compiling. If you use a recent GCC compiler on your C code, compile it with gcc -Wall -Wextra -g.
The first part of your question, was already answered as a comment.
Regarding the second question, you could use fscanf to read the integer values directly from the file instead of reading a char array and converting it to an int by atoi:
fscanf(start,"%d:%d", &strtimearr[0], &strtimearr[1]);
If fscanf is successful, it returns the count of successfully read items, otherwise EOF is returned.
According to manual, int fscanf(FILE *stream, const char *format, ...) returns the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure. How shall I differentiate between:
zero matched and assigned items
end of the file
an empty file?
See the 'return values' section of the POSIX specification for fscanf(), for example.
Zero matched and assigned items is reported by fscanf() returning 0.
End of file is reported by fscanf() returning EOF.
An empty file is reported by the first call to fscanf() returning EOF.
Note that the prescription makes it difficult to spot the difference between an empty file (no bytes) and a file with no useful data in it. Consider this test program (I called it eof59.c, compiled to create eof59):
#include <stdio.h>
int main(void)
{
char buffer[256];
int rc;
while ((rc = scanf("%255s", buffer)) != EOF)
printf("%d: %s\n", rc, buffer);
}
If you run it with /dev/null as input (the ultimate empty file), it says nothing. However, it also says nothing if you feed it a file with a single blank (and no newline), or just a newline, or indeed any sequence of white space. You can also experiment replace the format string with " x %255s". Feeding it a file with just an x (possibly with white space around it) generates no output. Feed it a file with a y as the first character (other than white space) and the program runs for a long time reporting 0: on each line of output.
Note that while (!feof(file)) is always wrong, but after a function such as scanf() has returned EOF, you can legitimately use feof() and ferror() to disambiguate between genuine EOF and an error on the file stream (such as a disk crashing or …).
if (feof(stdin))
printf("EOF on standard input\n");
if (ferror(stdin))
printf("Error on standard input\n");
With the code shown, you should normally see 'EOF on standard input'; it would probably be quite hard to generate (even simulate) an error on standard input. You should not see both messages, and you should always see one of the messages.
The manual says that
Upon successful return, these functions [printf, dprintf etc.] return the number of characters printed.
The manual does not mention whethet may this number less (but yet nonnegative) than the length of the "final" (substitutions and formattings done) string. Nor mentions that how to check whether (or achieve that) the string was completely written.
The dprintf function operates on file descriptor. Similarily to the write function, for which the manual does mention that
On success, the number of bytes written is returned (zero indicates nothing was written). It is not an error if this number is smaller than the number of bytes requested;
So if I want to write a string completely then I have to enclose the n = write() in a while-loop. Should I have to do the same in case of dprintf or printf?
My understanding of the documentation is that dprintf would either fail or output all the output. But I agree that it is some gray area (and I might not understand well); I'm guessing that a partial output is some kind of failure (so returns a negative size).
Here is the implementation of musl-libc:
In stdio/dprintf.c the dprintf function just calls vdprintf
But in stdio/vdprintf.c you just have:
static size_t wrap_write(FILE *f, const unsigned char *buf, size_t len)
{
return __stdio_write(f, buf, len);
}
int vdprintf(int fd, const char *restrict fmt, va_list ap)
{
FILE f = {
.fd = fd, .lbf = EOF, .write = wrap_write,
.buf = (void *)fmt, .buf_size = 0,
.lock = -1
};
return vfprintf(&f, fmt, ap);
}
So dprintf is returning a size like vfprintf (and fprintf....) does.
However, if you really are concerned, you'll better use snprintf or asprintf to output into some memory buffer, and explicitly use write(2) on that buffer.
Look into stdio/__stdio_write.c the implementation of __stdio_write (it uses writev(2) with a vector of two data chunks in a loop).
In other words, I would often not really care; but if you really need to be sure that every byte has been written as you expect it (for example if the file descriptor is some HTTP socket), I would suggest to buffer explicitly (e.g. by calling snprintf and/or asprintf) yourself, then use your explicit write(2).
PS. You might check yourself the source code of your particular C standard library providing dprintf; for GNU glibc see notably libio/iovdprintf.c
With stdio, returning the number of partially written bytes doesn't make much sense because stdio functions work with a (more or less) global buffer whose state is unknown to you and gets dragged in from previous calls.
If stdio functions allowed you to work with that, the error return values would need to be more complex as they would not only need to communicate how many characters were or were not outputted, but also whether the failure was before your last input somewhere in the buffer, or in the middle of your last input and if so, how much of the last input got buffered.
The d-functions could theoretically give you the number of partially written characters easy, but POSIX specifies that they should mirror the stdio functions and so they only give you a further unspecified negative value on error.
If you need more control, you can use the lower level functions.
Concerning printf(), it is quite clear.
The printf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred. C11dr §7.21.6.3 3
A negative value is returned if an error occurred. In that case 0 or more characters may have printed. The count is unknowable via the standard library.
If the value return is not negative, that is the number sent to stdout.
Since stdout is often buffered, that may not be the number received at the output device on the conclusion of printf(). Follow printf() with a fflush(stdout)
int r1 = printf(....);
int r2 = fflush(stdout);
if (r1 < 0 || r2 != 0) Handle_Failure();
For finest control, "print" to a buffer and use putchar() or various non-standard functions.
My bet is that no. (After looking into the - obfuscated - source of printf.) So any nonnegative return value means that printf was fully succesful (reached the end of the format string, everything was passed to kernel buffers).
But some (authentic) people should confirm it.
This code comes from K&R. I have read it several times, but it still seems to escape my grasp.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
return(bufp>0)?buf[--bufp]:getchar();
}
int ungetch(int c)
{
if(bufp>=BUFSIZE)
printf("too many characters");
else buf[bufp++]=c;
}
The purpose of these two functions, so K&R says, is to prevent a program from reading too much input. i.e. without this code a function might not be able to determine it has read enough data without first reading too much. But I don't understand how it works.
For example, consider getch().
As far as I can see this is the steps it takes:
check if bufp is greater than 0.
if so then return the char value of buf[--bufp].
else return getchar().
I would like to ask a more specific question, but I literally dont know how this code achieves what it is intended to achieve, so my question is: What is (a) the purpose and (b) the reasoning of this code?
Thanks in advance.
NOTE: For any K&R fans, this code can be found on page 79 (depending on your edition, I suppose)
(a) The purpose of this code is to be able to read a character and then "un-read" it if it turns out you accidentally read a character too many (with a max. of 100 characters to be "un-read"). This is useful in parsers with lookahead.
(b) getch reads from buf if it has contents, indicated by bufp>0. If buf is empty, it calls getchar. Note that it uses buf as a stack: it reads it from right-to-left.
ungetch pushes a character onto the stack buf after doing a check to see if the stack isn't full.
The code is not really for "reading too much input", instead is it so you can put back characters already read.
For example, you read one character with getch, see if it is a letter, put it back with ungetch and read all letters in a loop. This is a way of predicting what the next character will be.
This block of code is intended for use by programs that make decisions based on what they read from the stream. Sometimes such programs need to look at a few character from the stream without actually consuming the input. For example, if your input looks like abcde12xy789 and you must split it into abcde, 12, xy, 789 (i.e. separate groups of consecutive letters from groups of consecutive digits) you do not know that you have reached the end of a group of letters until you see a digit. However, you do not want to consume that digit at the time you see it: all you need is to know that the group of letters is ending; you need a way to "put back" that digit. An ungetch comes in handy in this situation: once you see a digit after a group of letters, you put the digit back by calling ungetch. Your next iteration will pick that digit back up through the same getch mechanism, sparing you the need to preserve the character that you read but did not consume.
1. The other idea also shown here can be also called as a very primitive I/O stack mangement system and gives the implementation of the function getch() and ungetch().
2. To go a step further , suppose you want to design an Operating System , how can you handle the memory which stores all the keystrokes?
This is solved by the above code snippet.An extension of this concept is used in file handling , especially in editing files .In that case instead of using getchar() which is used to take input from Standard input , a file is used as a source of input.
I have a problem with code given in question. Using buffer (in form of stack) in this code is not correct as when getting more than one extra inputs and pushing into stack will have undesired effect in latter processing (getting input from buffer).
This is because when latter processing (getting input) going on ,this buffer (stack) will give extra input in reverse order (means last extra input given first).
Because of LIFO (Last in first out ) property of stack , the buffer in this code must be quene as it will work better in case of more than one extra input.
This mistake in code confused me and finally this buffer must be quene as shown below.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufr = 0;
int buff = 0;
int getch(void)
{
if (bufr ==BUFSIZE)
bufr=0;
return(bufr>=0)?buf[bufr++]:getchar();
}
int ungetch(int c)
{
if(buff>=BUFSIZE && bufr == 0)
printf("too many characters");
else if(buff ==BUFSIZE)
buff=0;
if(buff<=BUFSIZE)
buf[buff++]=c;
}
If I have a program that is using scanf to get user inputted data:
scanf("%d",&val);
When I run it through lint I get warnings saying that scanf returns a int and it is not being assigned anywhere. What is the c practice to solve this problem? Do I type cast it as void?
(void)scanf("%d",&val);
The C best practice to solve this warnings is simple: Check the resultcode. The scanf function returns in the int if the operation has gone ok or not, and stores the error usually in errno.
The lack of resultcode checks usually results in big errors in certain situations.
The proper answer, of course, is to not ignore the return value. For a robust program, you should always (EDIT: usually) check that the return value indicates success, and fail gracefully when it does not.
Ideally you would do something like
int scanVal = scanf("%d", &val);
if (scanVal != 1) {
// wait a minute, scanf couldn't match input to a "%d"!
}
and then act on the output in a sensible manner.
Instead of silencing the lint message, just check the return value to make sure nothing has gone wrong. From the man page:
RETURN VALUE
These functions return the number of input items
successfully matched and assigned, which can be
fewer than provided for, or even zero in the event of an early
matching failure.
The value EOF is returned if the end of input is reached before
either the first successful conversion or a matching failure occurs. EOF is also >returned if a read error occurs, in which case the
error indicator for the stream (see ferror(3)) is set, and
errno is set indicate the error.
scanf returns the number of input items successfully matched and assigned. Compare its return value to the number you expect in order to detect errors.
while (scanf("%d",&val) != 1)
printf("Try again.\n");
Use
#pragma warning(disable:<warning number>)
scanf("%d",&val);
#pragma warning(default:<warning number>)
And your compiler will suppress that warning.
The best practice is to assign the return value of scanf to see if all (or how many) items were read. In this particular case, if it returns anything but 1, something went wrong (e. g. you wanted a number but the user is giving you unprintable characters) and you should handle it appropriately.
If you want your code to be robust in the presence of bad input, don't use scanf("%d", ...).
For most errors, scanf("%d", &val) will return 0 to indicate that it wasn't able to read an int value (for example, if the input is "foo" rather than "123").
But if the input is syntactically valid but out of range (for example 9999999999999999999), the behavior is undefined.
Most implementations will probably behave sanely, but I don't know how much consistency there is.
To read an int value safely, use fgets() (not gets()) followed by strtol(). (fgets() can have problems with very long input lines, but there are ways to deal with that.)