Use sscanf to process variable-format output - c

This is a program ,15.5,in the book called Pointers On C.I can't understand what this program want to do.
#include<stdio.h>
#include<stdlib.h>
#define DEFAULF_A 1
#define DEFAULF_B 2
void function(char *buffer)
{
int a,b,c;
if(sscanf(buffer,"%d %d %d",&a,&b,&c)!=3)
{
a=DEFAULF_A;
if(sscanf(buffer,"%d %d",&b,&c)!=2)
{
b=DEFAULF_B;
if(sscanf(buffer,"%d",&c)!=1)
{
fprintf(stderr,"Bad input:%s",buffer);
exit(EXIT_FAILURE);
}
}
}
}//***the title of the program is Use sscanf to process variable-format output***
If I suppose the first three number in buffer is 1,2 and 3.
List item
The sscanf at the second if assigns 1 to B that should have been assigned to A and assigns 2 to C that should have been assigned to B.So why not just throw out the &c and leave the &a in sscanf,like this
c=DEFAULF_A;
if(sscanf(buffer,"%d %d",&a,&b)!=2)
List item
And why does the exit(EXIT_FAILURE) appear in the third if?When the exit(EXIT_FAILURE) appear in the third if,it mean there is a problem with the first read and the second and the third reads don't know.But when it comes this case sscanf(buffer,"%d %d %d",&a,&b,&c)!=3,the program is also wrong.
List item
So what this program want to do?
Due to I just started to learn CS,I only konw a little about C language,and lack other basic computer knowledge,please answer in a way that is easy to understand.Thanks in advance.
This is a example in Pointers On C .This program might correspond to this sentence that "the latter is used to convert the expected number of values.

[] The sscanf at the second if assigns 1 to B that should have been assigned to A and assigns 2 to C that should have been
assigned to B.So why not just throw out the &c and leave the &a in
sscanf,like this
c=DEFAULF_A;
if(sscanf(buffer,"%d %d",&a,&b)!=2)
Because that's (apparently) not the desired behavior. The program is assigning read values to the rightmost subset of variables (a, b, c), so if only two values are provided then they go to b and c, and if only one is provided then it goes to c. The variables that don't get read values assigned to them are assigned default values instead. Your proposed alternative does not achieve the same thing.
And this is in fact the distinguishing characteristic of the function presented -- the "trick", if you will. It would indeed be simpler to write a straight left-to-right style matchup of values to variables.
Nevertheless, the function is needlessly complicated. Myself, I would not write it with three separate sscanf calls, because you can get everything you need from just one. I would write the function something like this:
#define DEFAULT_A 1
#define DEFAULT_B 2
void function(char *buffer) {
int a, b, c, num_fields;
num_fields = sscanf(buffer, "%d %d %d", &a, &b, &c);
switch (num_fields) {
case 3:
// three values read and assigned. nothing to see here.
break;
case 2:
// only two values read (into variables 'a' and 'b')
// shift them to the correct variables and assign a default to 'a'
c = b;
b = a;
a = DEFAULT_A;
break;
case 1:
// only one value read (into variable 'a')
// shift it to the correct variable and assign defaults to the others
c = a;
b = DEFAULT_B;
a = DEFAULT_A;
break;
default:
fprintf(stderr, "Bad input: %s\n", buffer);
exit(EXIT_FAILURE);
}
}
[] And why does the exit(EXIT_FAILURE) appear in the third if?When the exit(EXIT_FAILURE) appear in the third if,it mean there is
a problem with the first read and the second and the third reads don't
know.But when it comes this case sscanf(buffer,"%d %d %d",&a,&b,&c)!=3,the program is also wrong.
The return value of sscanf reports on two things:
how many scanf directives resulted in values being successfully read from the input, converted to the indicated data type, and assigned to variables; and
whether any kind of system error was encountered (very unlikely for sscanf(), but this is shared with scanf(), for which it is a genuine possibility).
You seem to have the second one in mind, but it is the first that the program is mainly relying upon. It is using the return value to determine how many of the variables were assigned values. That the first attempt does not assign all three does not imply that the second will not assign two, or the third, one. But of course you're right that the program is somewhat redundant. As I demonstrate above, only one sscanf() call is needed.
[] So what this program want to do?
Nitpick: it's just one function, not a complete program.
Technically, because it doesn't do anything with the values it parses out of the string, all it does is report on whether the string pointed to by the function argument starts with a text representation of at least one decimal integer, optionally preceded by any number of whitespace characters (spaces, tabs, etc.). If so, it prints nothing. If not, it prints an error message.
But what you're probably looking for is the explanation I provided in response to your first numbered question.

Seeing how you are essentially asking 'What does this program' do: It is essentially performing a 'default initialization for not entered values'.
Another (more efficient) way to achieve (much) the same thing is:
#include<stdio.h>
#include<stdlib.h>
#define DEFAULF_A 1
#define DEFAULF_B 2
void function(char *buffer)
{
int a,b,c;
switch (sscanf(buffer,"%d %d %d",&a,&b,&c))
{
case 1:
b = DEFAULF_B; //Only one has been entered, assign default to 'b'.
//Falls through
case 2:
c = DEFAULF_A; //Only two have been entered, assign default to 'c'.
//Falls through.
case 3: break; //All three have been entered, do nothing.
default:
exit(EXIT_FAILURE); //None have been entered -> Abort the program.
break;
}
}
If buffer contained 3 numbers, all three numbers are kept and no defaults are applied.
If buffer contained 2 numbers, the two numbers are kept (in your code that's b and c, in mine it's a and b) and DEFAULF_A is assigned to the remaining variable.
If buffer contained 1 number, that number is kept (c for you, a in my example) and the other two get assigned DEFAULF_A and DEFAULF_B respectively.
If buffer contained no number at all, your program gets terminated with the return code 'EXIT_FAILURE', which a calling program could fetch.

The program examines contents from a buffer, and tries to read three values from it, for example:
1 2 3
If the first sscanf finds three numbers, it reads them all. If only two are found, it assigns default value to a and tried to read two numbers. If only one is found, it assigns default value to b and tries to read one number. If there are no numbers, the program exits, because there is no default value for c.
So if we reach exit(), it means there were neither 3, 2, or 1 numbers in the buffer. If one of the if clauses succeeded, further ones are not executed.
It is important to realize that sscanf always starts from the beginning of the buffer. So if it reads for example 1 2 in the first call, but cannot find the third one, the buffer still contains the same data during the second call, and two numbers can be read.
Regarding your question 1: Why are two numbers considered as "b and c", rather than "a and b"? This is simply the way the programmer wanted the program to work. They could have as easily set a default value for c and considered the two numbers as "a and b".
Regarding your question 2: What if the output is completely invalid, and the third read will fail? In that case, we know that the first and second reads will fail as well, so we can safely put the error handling after the third one.

Related

How does the following code works printf("%c")?

I wanted to know how the following program is working?
#include <stdio.h>
int main(void) {
while(1){
if(printf("%d",printf("%c")))
break;
else
continue;
}
return 0;
}
I did not know how the part printf("%c") is working and therefore the whole program.I am aware of writing something like printf("%c", 'a'); like that but how is it working without providing the character to be printed? My question is what does the following program prints and how does it prints so?
I have tried to run the program, sometimes it prints nothing, but sometimes it is printing some random character followed by 1. I am not able to get how it is working, can someone please explain what is going behind the code and how it is printing that random characters, and why there is one at the end?
Here are some output I am getting
Welcome to Undefined Behavior. You fail to have sufficient number of arguments for the format you specify, e.g.
C11 Standard - 7.21.6.1 The fprintf function(p2) "If there are insufficient arguments for the format, the behavior is undefined." 7.21.6.1(p9) "If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."
A cool wrong program you have.
printf("%c") attempts to print a single character that is supposed to be the second parameter. However, since you have never passed the second parameter, the function prints whatever is in the register that was supposed to have the second parameter. In other words, some random character. However, it prints one character and returns 1: the number of characters printed.
That 1 is in turn printed by printf("%d",printf("%c")). Now you have a random character followed by 1, and since the outer printf also prints one character, it returns 1.
Finally, if(printf("%d",printf("%c"))) interprets that later 1 as true and breaks the loop.
This is about format bugs.
Look at this code, when execute printf("%d", 123), the program will push number 123 onto the stack, and then push string "%d", when printf meets "%d", it will read the value on the top of the stack, so printf find the number 123.
Now look at this code, printf("%c"), program will push string "%c" onto the stack, and try to read value on the top of the stack, you haven't push a value for printf, so printf will still find value, but the value is random, so you might get a random value.

Explanation needed to understand this recursive C program to print a string in reverse

I cannot understand when does the putchar line is being executed and how it's helping to reverse the input lines ? If EOF occurs the return statement gets executed , but what happens after that line ?
#include<stdio.h>
int fun_reverse();
void main(){
fun_reverse();
}
int fun_reverse(){
int ch ;
ch = getchar();
if(ch==EOF)
return;
fun_reverse();
putchar(ch);
}
every time you're calling fun_reverse in your fun_reverse function, it doesn't print the inputted char immediately, just asks for input for another one, piling on the requests (and creating as much local variables storing each char) until EOF is reached.
When EOF is encountered, fun_reverse returns without calling fun_reverse again, ending the chain, making all callers return and eventually print the results.
The fact that the calls have been piled on due to recursion has the effect of reversing the output, because unpiling them is done the other way round.
This technique is often used to convert a number to string without any extra buffer. Converting a number to string gives the "wrong" end of the number first, so you have to buffer the numbers until the number digits are fully processed. A similar algorithm as the one above allows to store the digits and print them in the readable order.
Though your question is already been answered I would suggest you to read about 'head recursion' and 'tail recursion'.
Have a look at accepted answer of this question.

Identyfying prefix in the same string as a suffix

Eg-
maabcma is valid because it contains ma as a proper prefix as well as a proper suffix.
panaba is not.
How do I find out if a word is valid or not as above in C language?
I'm not very good at string operations. So, please help me out with a pseudocode.
Thanks in advance.
I'm completely lost. T=number of test cases.
EDIT: New code. My best code so far-
#include<stdio.h>
#include<string.h>
void main()
{
int i,T,flag=0;
int j,k,len=0;
char W[10],X[10];
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%s",W);
for(len=0;W[len]!='\0';len++)
X[len]=W[len];
X[len]='\0';
for(j=len-1;j>=0;j--)
for(k=0;k<len;k++)
{
if(X[k]!=W[j])
flag=0;
else if((j-k)==(len-1))
flag==1;
}
if (flag == 1)
printf("NICE\n");
else
printf("NOT\n");
}
}
Still not getting the proper results. Where am I going wrong?
The thing is you are only setting the value of flag if a match exists, otherwise you must set it to 0. because see, if I have:
pammbap
my prefix is pam and suffix is bap.
According to the final for loop,
p and a match so flag is set to 1.
but when it comes to b and m it does not become zero. Hence, it returns true.
First, void is not a valid return type for main, unless you are developing for Plan 9.
Second, you should get into the habit of checking the return value of scanf() and all input functions in general. You can't rely on the value of T if the user does not input a number, because T is uninitialised. On that same note, you shouldn't use scanf with an unbounded %s scan operation. If the user enters 20 characters, this isn't going to fit into the ten character buffer that you have. An alternative approach is to use fgets to get a whole line of text at once, or, to use a bounded scan operation. If your array fits 10 characters (including the null terminator) then you can use scanf("%9s", W).
Third, single-character variable names are often very hard to understand. Instead of W, use word, instead of T, use testCount or something similar. This means that someone looking at your code for the first time can more easily work out what each variable is used for.
Most importantly, think about the process in your head, and maybe jot it down on paper. How would you solve this problem yourself? As an example, starting with n = 1,
Take the first n characters from the string.
Compare it to the last n characters from the string
Do they match?
If yes, print out the first n characters as the suffix and stop processing.
If no, increment n and try again. Try until n is in the middle of the string.
There are a few other things to think about as well, do you want the biggest match? For example, in the input string ababcdabab, the prefix ab is also the suffix, but the same can be said about abab. In this case, you don't want to stop processing, you want to keep going even if you find a prefix, so, you should just store the length of the largest prefix that is also the suffix.
Second-most-importantly, running into hurdles like this is incredibly common when learning C, so don't let this put a dampener on your enthusiasm, just keep trying!

Dynamic memory allocation for input? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I am having a lot of trouble starting my project. Here are the directions:
"Complete counts.c as follows:
Read characters from standard input until EOF (the end-of-file mark) is read. Do not prompt the user to enter text - just read data as soon as the program starts.
Keep a running count of each different character encountered in the input, and keep count of the total number of characters input (excluding EOF)."
The format my professor gave me to start is: `
#include <stdio.h>
int main(int argc, char *argv[]) {
return 0;
}
In addition to how to start the problem, I'm also confused as to why the two parameter's are given in the main function when nothing is going to be passed to it. Help would be much appretiated! Thank you!
`
Slightly tricky to see what you're having trouble with here. The title doesn't form a complete question, nor is there one in the body; and they seem to be hinting at entirely different questions.
The assignment tells you to read characters - not store them. You could have a loop that only reads them one at a time if you wish (for instance, using getchar). You're also asked to report counts of each character, which would make sense to store in an array. Given that this is of "each different character", the simplest way would be to size the array for all possible characters (limits.h defines UCHAR_MAX, which would help with this). Remember to initialize the array if it's automatically allocated (the default for function local variables).
Regarding the arguments to main, this program does not need them, and the C standard does allow you to leave them out. They're likely included as this is a template of a basic C program, to make it usable if command line arguments will be used also.
For more reference code you might want to compare the word count utility (wc); the character counting you want is the basis of a frequency analysis or histogram.
This should give you a start to investigate what you need to learn to complete your task,
Initially declare a character input buffer of sufficient size to read chars as,
char input[SIZE];
Use fgets() to read the characters from stdin as,
if (fgets(input, sizeof input, stdin) == NULL) {
; // handle EOF
}
Now input array has your string of characters which you to find occurrence of characters. I did not understand When you say different characters to count, however you have an array to traverse it completely to count the characters you need.
Firstly, luckily for you we will not need dynamic memory allocation at all here as we are not asked to store the input strings, instead we simply need to record how many of each ascii code is input during program run, as there a constant and finite number of those we can simply store them in a fixed size array.
The functions we are looking at here (assuming we are using standard libs) are as follows:
getchar, to read chars from standard input
printf, to print the outputs back to stdout
The constructs we will need are:
do {} while, to loop around until a condition is false
The rest just needs simple mathematical operators, here is a short example which basically shows a sample solution:
#include <stdio.h>
int main(int argc, char *argv[])
{
/* Create an array with entries for each char,
* then init it to zeros */
int AsciiCounts[256] = {0};
int ReadChar;
int TotalChars = 0;
int Iterator = 0;
do
{
/* Read a char from stdin */
ReadChar = getchar();
/* Increment the entry for its code in the array */
AsciiCounts[ReadChar]++;
TotalChars++;
} while (ReadChar != EOF);
/* Stop if we read an EOF */
do
{
/* Print each char code and how many times it occurred */
printf("Char code %#x occurred %d times\n", Iterator, AsciiCounts[Iterator]);
Iterator++;
} while (Iterator <= 255);
/* Print the total length read in */
printf("Total chars read (excluding EOF): %d", --TotalChars);
return 0;
}
Which should achieve the basic goal, however a couple of extension exercises which would likely benefit your understanding of C. First you could try to convert the second do while loop to a for loop, which is more appropriate for the situation but I did not use for simplicity's sake. Second you could add a condition so the output phase skips codes which never occurred. Finally it could be interesting to check which chars are printable and print their value instead of their hex code.
On the second part of the question, the reason those arguments are passed to main even though they are ignored is due to the standard calling convention of c programs under most OSes, they pass the number of command line arguments and values of each command line argument respectively in case the program wishes to check them. However if you really will not use them you can in most compilers just use main() instead however this makes things more difficult later if you choose to add command line options and has no performance benefit.

Please Explain this Example C Code

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;
}

Resources