c - Last call to function is being printed again - c

This is the loop in my a4.c main method that calls the patternsearch function:
while(!feof(stdin)) {
scanf("%s", &word);
patternSearch(grid, word);
}
For some reason that I can't figure out, this prints the last call to patternsearch twice:
For example, look at my output for test3:
Found "tip" at 0 2, L
Found "pop" at 0 0, D
Found "pop" at 2 0, U
Found "key" at 0 3, D
Found "key" at 2 1, R
"nope" - Not Found
"nope" - Not Found
As you can see, the test result for 'nope' was printed twice. :(
I think my problem is similar to the one stated here:
Last line being printed twice (C++)
but I'm not sure.

Step 1 with any problem involving input: test the return value from the input function.
feof() checks if a prior read resulted in an end-of-file. It does not report about future reads.
Code is having trouble with unexpected results of scanf("%s", &word);, yet code did not check the return value from scanf(). Weak code does not check the return value. Robust code does. Research the proper use of scanf() and its return values.
Do not use "%s" without a width limit.
The & in scanf("%s", &word); is likely not needed. Would need to see word declaration to be sure.
char word[100];
while (scanf("%99s", word) == 1) {
patternSearch(grid, word);
}

The issue here was that feof() only returned true when I actually hit the EOF character.
That means that I was calling scanf(), and hitting the EOF;
that means the loop won't iterate again, but I was already in the middle of it.
But scanf() only actually changes the argument I hand it if it successfully reads what I asked;
since it failed (by hitting EOF),
it won't change the character array, which will still contain whatever it did before (i.e. the previous word).
I checked the return value of scanf(); the number it returns, which is the number of arguments it put a new value into;
if that's less than 1, then I didn't actually get a new string (I think it also explicitly returns EOF if it hits the end-of-file; EOF is a #defined constant that's equal to -1 on most platforms, so the <1 check will work anyway).
This is the code that finally worked:
while(!feof(stdin)) {
if (scanf("%s", &word) < 1)
break;
patternSearch(grid, word);
}

Related

Is there a way to setback ptr inside my file after using fgetc()?

int main(){
int ms = 0, vs = 0, cif = 0, intzn = 0, i;
FILE* dat = fopen("file.txt", "r");
for(i = 0; !feof(dat); i++)
{
if(isupper(fgetc(dat)))
vs++;
else
{
fseek(dat, ftell(dat) - 1, SEEK_SET);
}
if(islower(fgetc(dat)))
ms++;
else
{
fseek(dat, ftell(dat) - 1, SEEK_SET);
}
if(isdigit(fgetc(dat)))
cif++;
else
{
fseek(dat, ftell(dat) - 1, SEEK_SET);
}
if(ispunct(fgetc(dat)))
intzn++;
}
printf("\nVS: %d\nMS: %d\nCif: %d\nIntznc: %d", vs, ms, cif, intzn);
fclose(dat);
return 0;
}
every time i use "fgetc(dat)" in my if statement, the pointer pointing to that character in that file advances, so I am trying to figure out how to set it back in case my if statement is false, where I've tried using "fseek()" but it still wont work, why?
Your loop should not use feof to test for end-of-file because the end-of-file indicator is set only after the end is reached. It cannot tell you in advance there is not another character to get.
Looking at your loop, I suspect you do not need to “go back” in the file. You just need to read one character and examine it in multiple ways. To do that, you can simply read the character and assign its value to a variable. Then you can use the variable multiple times without rereading the character. For future reference, when you do want to reject a character, you can “put it back” into the stream with ungetc(c, dat);.
Further, I suspect you want to read each character in the file and characterize it. So you want a loop to read through the file until the end. To do this, you can use:
To read one character, test it, and reject it if it is not satisfactory, use:
while (1) do
{
/* Use int to get a character, because `fgetc` may
return either an unsigned char value or EOF.
*/
int c = fgetc(dat);
// If fgetc failed to get a character, leave the loop.
if (c == EOF)
break;
// Now test the character.
if (isupper(c))
++vs;
else if (islower(c))
++ms;
else if (isdigit(c))
++cif;
else if (ispunct(c))
++intzn;
// If desired, include a final else for all other cases:
else
++other;
}
There are several issues with your program, among them:
for (...; !feof(f); ...) is wrong. The feof() function determines whether end-of-file has been observed by a previous read from the file. If one has not, then that function does not speak to whether a future read will succeed. feof() is for distinguishing between read failures resulting from EOF and those resulting from I/O errors, not for predicting the future.
When one of your tests succeeds, you do not go back to the beginning of the loop. So suppose that your fseek()s were all working (which may in fact be the case), that your input is "StackOverflow", and that at the beginning of a loop iteration, the 'k' is the next character. Then
the 'k' will be read and rejected by the uppercase test, and the file moved back
the 'k' will be read an accepted by the lowercase test
the 'O' will be read and rejected by the digit test, and the file moved back
the 'O' will be read and rejected by the punctuation test, and lost because the file is not moved back.
I've tried using "fseek()" but it still wont work, why?
It's hard to tell for sure without the input you are using and an explanation of what behavior you actually observe, but likely the problem is related to the second point above.
The thing to do is probably to
avoid any need to push back a character. On each iteration of the loop, read one character from the file and store it in a variable, then perform as many tests as you like on that variable's value.
test the return value of fgetc() (instead of using feof()) to determine when the end of the file has been reached. This dovetails with (1) above.
As an aside, fseek(dat, -1, SEEK_CUR) would be more idiomatic for backing up the file pointer by one byte.

Why is this a valid scanf statement to break out of a while loop?

Why is this a valid line of code to break out of an infinite while loop?
if (scanf("%s", word) != 1) break;
if (scanf("%s", word) != 1) break;
scanf returns the number of items successfully consumed. This value is used as the left hand operand inside of the expression. Thus, this expression is perfectly valid.
In the following example this value shall be 1 if no I/O error occurred and a string was successfully converted because there is only one item to consume.
I guess this if statement is part of a loop whose intention is to read subsequent words from the input until it encounters an EOF state for stdin or any redirected file used as input because the condition is only then evaluated to true (and with that to break out of the surrounding loop) if EOF or another I/O error has happen as scanf() returns 0 in this case.
This shall give you an insight of how this if statement is to be evaluated and interpreted.
The mentioned break statement and its guard is valid but it's lying. Consider the loop
while (1) {
...
}
According to the rules of structured programming the loop should never exit, that is unless the program exits. Rather than using a break statement, a properly structured program should use the return value from the function scan as the loop guard, like this:
tokenCount = scanf("%s", word);
while (tokenCount == 1) {
...
tokenCount = scanf("%s", word);
}
It's also easier to reason about the correctness of a program if expressions do not have side effects; that's why the return value is stored in a variable (with a meaningful name).

what does while(~scanf mean in C?

i watch some code and i don't know what the meaning of while(~scanf
while(~scanf("%s", word+1) !=EOF)
{
int a= strlen(word+1);
i already search google and found nothing on this. Please help
Analyzing the expression while(~scanf("%s", word+1) != EOF):
Run as long as the bitwise-inverted return value of scanf is not equal to the value of EOF.
Analyzing the equivalent expression while(scanf("%s", word+1) != ~EOF):
Run as long as the return value of scanf is not equal to the bitwise-inverted value of EOF.
Assuming that EOF is typically all 1s, this expression is essentially equivalent to:
while(scanf("%s", word+1) != 0)
Which means:
Run as long as the return value of scanf is not 0.
Or simply:
Run until the return value of scanf is 0.
I'm still scratching my head as to whether or not this analysis is correct.
Good question for a job interview (and a good example for how to not write code).
On success scanf will return the number of input items successfully matched. In this case there is only one input item to match therefore on success scanf will return 1, The code above will bitwise invert 1 which will make it -2. Since -2 != EOF, the loop will not end. Since EOF has a value of -1.
If scanf encounters an error or reaches end of input, for example because the user pressed Ctrl-D, it will return EOF and no new value will be placed in the memory location word+1. The code will bitwise invert EOF, which becomes 0, because ~EOF=0. Since 0 != EOF the loop will not end. The call to strlen will return the length of string that was in memory location word+1 prior to calling scanf.
The loop will only end if scanf returns 0, because ~0 = -1 = EOF. This will only happen if scanf was unable to match the input to a string for the conversion specifier "%s".

Flushing stdin after every input - which approach is not buggy?

After Mark Lakata pointed out that the garbage isn't properly defined in my question I came up with this. I'll keep this updated to avoid confusions.
I am trying to get a function that I can call before a prompt for user input like printf("Enter your choice:); followed a scanf and be sure that only the things entered after the prompt would be scanned in by scanf as valid input.
As far as I can understand the function that is needed is something that flushes standard input completely. That is what I want. So for the purpose of this function the "garbage" is everything in user input i.e. the whole user input before that user prompt.
While using scanf() in C there is always the problem of extra input lying in the input buffer. So I was looking for a function that I call after every scanf call to remedy this problem. I used this, this, this and this to get these answers
//First approach
scanf("%*[^\n]\n");
//2ndapproach
scanf("%*[^\n]%*c");
//3rd approach
int c;
while((c = getchar()) != EOF)
if (c == '\n')
break;
All three are working as far as I could find by hit-and-trial and going by the references. But before using any of these in all of my codes I wanted to know whether any of these have any bugs?
EDIT:
Thanks to Mark Lakata for one bug in 3rd. I corrected it in the question.
EDIT2:
After Jerry Coffin answered I tested the 1st 2 approaches using this program in code:blocks IDE 12.11 using GNU GCC Compiler(Version not stated in the compiler settings).
#include<stdio.h>
int main()
{
int x = 3; //Some arbitrary value
//1st one
scanf("%*[^\n]\n");
scanf("%d", &x);
printf("%d\n", x);
x = 3;
//2nd one
scanf("%*[^\n]%*c");
scanf("%d", &x);
printf("%d", x);
}
I used the following 2 inputs
First Test Input (2 Newlines but no spaces in the middle of garbage input)
abhabdjasxd
23
bbhvdahdbkajdnalkalkd
46
For the first I got the following output by the printf statements
23
46
i.e. both codes worked properly.
Second Test input: (2 Newlines with spaces in the middle of garbage input)
hahasjbas asasadlk
23
manbdjas sadjadja a
46
For the second I got the following output by the printf statements
23
3
Hence I found that the second one won't be taking care of extra garbage input whitespaces. Hence, it isn't foolproof against garbage input.
I decided to try out a 3rd test case (garbage includes newline before and after the non-whitespace character)
``
hahasjbas asasadlk
23
manbdjas sadjadja a
46
The answer was
3
3
i.e. both failed in this test case.
The first two are subtly different: they both read and ignore all the characters up to a new-line. Then the first skips all consecutive white space so after it executes, the next character you read will be non-whitespace.
The second reads and ignores characters until it encounters a new-line then reads (and discards) exactly one more character.
The difference will show up if you have (for example) double-spaced text, like:
line 1
line 2
Let's assume you read to somewhere in the middle of line 1. If you then execute the first one, the next character you read in will be the 'l' on line 2. If you execute the second, the next character you read in will be the new-line between line 1 and line 2.
As for the third, if I were going to do this at all, I'd do something like:
int ch;
while ((ch=getchar()) != EOF && ch != '\n')
;
...and yes, this does work correctly -- && forces a sequence point, so its left operand is evaluated first. Then there's a sequence point. Then, if and only if the left operand evaluated to true, it evaluates its right operand.
As for performance differences: since you're dealing with I/O to start with, there's little reasonable question that all of these will always be I/O bound. Despite its apparent complexity, scanf (and company) are usually code that's been used and carefully optimized over years of use. In this case, the hand-rolled loop may be quite a bit slower (e.g., if the code for getchar doesn't get expanded inline) or it may be about the same speed. The only way it stands any chance of being significantly faster is if the person who wrote your standard library was incompetent.
As far maintainability: IMO, anybody who claims to know C should know the scan set conversion for scanf. This is neither new nor rocket science. Anybody who doesn't know it really isn't a competent C programmer.
The first 2 examples use a feature of scanf that I didn't even know existed, and I'm sure a lot of other people didn't know. Being able to support a feature in the future is important. Even if it was a well known feature, it will be less efficient and harder to read the format string than your 3rd example.
The third example looks fine.
(edit history: I made a mistake saying that ANSI-C did not guarantee left-to-right evaluation of && and proposed a change. However, ANSI-C does guarantee left-to-right evaluation of &&. I'm not sure about K&R C, but I can't find any reference to it and no one uses it anyways...)
Many other solutions have the problem that they cause the program to hang and wait for input when there is nothing left to flush. Waiting for EOF is wrong because you don't get that until the user closes the input completely!
On Linux, the following will do a non-blocking flush:
// flush any data from the internal buffers
fflush (stdin);
// read any data from the kernel buffers
char buffer[100];
while (-1 != recv (0, buffer, 100, MSG_DONTWAIT))
{
}
The Linux man page says that fflush on stdin is non-standard, but "Most other implementations behave the same as Linux."
The MSG_DONTWAIT flag is also non-standard (it causes recv to return immediately if there is no data to be delivered).
You should use getline/getchar:
#include <stdio.h>
int main()
{
int bytes_read;
int nbytes = 100;
char *my_string;
puts ("Please enter a line of text.");
/* These 2 lines are the heart of the program. */
my_string = (char *) malloc (nbytes + 1);
bytes_read = getline (&my_string, &nbytes, stdin);
if (bytes_read == -1)
{
puts ("ERROR!");
}
else
{
puts ("You typed:");
puts (my_string);
}
return 0;
I think if you see carefully at right hand side of this page you will see many questions similar to yours. You can use fflush() on windows.

sscanf - reading from empty string

When I pass an empty string to sscanf, it returns zero and it doesn't change the given variable.
char* ptr = "";
abc = sscanf(ptr, "%s", output);
// abc == 0
Can you let me know the way to work it out?
sscanf awaits the first argument to be the C string that the function processes as its source to retrieve the data. Passing an empty string to this function can't yield your variable to be initialized, since there is nothing this function would initialize it with.
Also note that On success, the function returns the number of variables filled. This count can match the expected number of readings or fewer, even zero, if a matching failure happens. In the case of an input failure before any data could be successfully read, EOF is returned.
Following code, compiled with MinGW (gcc-core 4.5.0-1)
char str[10];
int ret = sscanf("", "%9s", str);
printf("%d\n", ret);
outputs -1 (EOF)
Good way of checking whether sscanf was successful is to check whether it's return value is really equal to the number of provided variables. In this case it would be if (ret == 1). Although many people just check, whether value greater than 0 was returned, to make sure that something has been read and that no error has occurred.

Resources