Check scanf formating without conversions - c++

Is there a way how to check if some specific characters were given on input using scanf without using character conversions?
int main(void)
{
if(scanf("{ ["))
printf("GOOD INPUT\n");
else
printf("BAD INPUT\n");
return 0;
}
This code always gives the bad input option (it expects scanf return value to be 1) but interestingly if I enter other than the desired characters it gives the bad input imediately but if I enter it as its specified in the scanf it blows the bad input at me AFTER I enter the whole input.
So it must be awaiting the input to be in that specified format but my question is: How can I check it, without any conversions, and make according action depending on wether the input was entered correctly or not?

You might use the %n conversion of scanf (it sets below into pos the number of characters read so far)
int pos= -1;
if (scanf("{ [%n", &pos) >=0 && pos>0)
printf("GOOD INPUT\n");
else
printf("BAD INPUT");
Beware, the return count of scanf might be implementation specific (it probably stays at 0). But pos get assigned to a positive offset of scanf did get { followed by some (zero or more) space-like characters followed by a [.
However, what you probably want is some lexical analysis and parsing, then scanf is not a good solution. You'll better read the entire line (e.g. with fgets or getline) and parse it later.
See also the man page of scanf(3)

scanf (and cousins) returns a count of the number of successful conversions. If you specify 0 conversions, then its return value will always be 0.
To use scanf for this task, I'd probably use a couple of scanset conversions:
char a[2], b[2];
if (scanf("%1[{] %1[[]", &a, &b) == 2)
printf("Matched");
Or, you could simplify this a little bit:
char a[2];
if (scanf("{ %1[[]", &a) == 1)
Either way, we've specified each scan set to match only one specified character, but it's still a conversion, so we can see whether it succeeded or failed.
Unfortunately, we still have to assign the result somewhere. scanf does support using * like this: "%*s", to tell it to read a string, but not store the result anywhere--but when you do so, that conversion doesn't get counted in the return value, so (much like before) we can't use it to determine whether we got a match or not.

If good input needs to exactly 3 characters: { space [, use "%*1[ ]" to scan a space and "%n", which saves the scan character count, to insure scanning reach the expected end.
int main(void) {
int n = -1;
scanf("{%*1[ ][%n", *n);
if (n >= 0) {
printf("GOOD INPUT\n");
} else {
printf("BAD INPUT\n");
}
return 0;
}
I'd recommend to read a line of input with fgets() first and then parse the buffer. That can leave stdin in a better known state when bad input happens.

Related

Symbol at the end of txt file appears [duplicate]

What is wrong with using feof() to control a read loop? For example:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
char *path = "stdin";
FILE *fp = argc > 1 ? fopen(path=argv[1], "r") : stdin;
if( fp == NULL ){
perror(path);
return EXIT_FAILURE;
}
while( !feof(fp) ){ /* THIS IS WRONG */
/* Read and process data from file… */
}
if( fclose(fp) != 0 ){
perror(path);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
What is wrong with this loop?
TL;DR
while(!feof) is wrong because it tests for something that is irrelevant and fails to test for something that you need to know. The result is that you are erroneously executing code that assumes that it is accessing data that was read successfully, when in fact this never happened.
I'd like to provide an abstract, high-level perspective. So continue reading if you're interested in what while(!feof) actually does.
Concurrency and simultaneity
I/O operations interact with the environment. The environment is not part of your program, and not under your control. The environment truly exists "concurrently" with your program. As with all things concurrent, questions about the "current state" don't make sense: There is no concept of "simultaneity" across concurrent events. Many properties of state simply don't exist concurrently.
Let me make this more precise: Suppose you want to ask, "do you have more data". You could ask this of a concurrent container, or of your I/O system. But the answer is generally unactionable, and thus meaningless. So what if the container says "yes" – by the time you try reading, it may no longer have data. Similarly, if the answer is "no", by the time you try reading, data may have arrived. The conclusion is that there simply is no property like "I have data", since you cannot act meaningfully in response to any possible answer. (The situation is slightly better with buffered input, where you might conceivably get a "yes, I have data" that constitutes some kind of guarantee, but you would still have to be able to deal with the opposite case. And with output the situation is certainly just as bad as I described: you never know if that disk or that network buffer is full.)
So we conclude that it is impossible, and in fact unreasonable, to ask an I/O system whether it will be able to perform an I/O operation. The only possible way we can interact with it (just as with a concurrent container) is to attempt the operation and check whether it succeeded or failed. At that moment where you interact with the environment, then and only then can you know whether the interaction was actually possible, and at that point you must commit to performing the interaction. (This is a "synchronisation point", if you will.)
EOF
Now we get to EOF. EOF is the response you get from an attempted I/O operation. It means that you were trying to read or write something, but when doing so you failed to read or write any data, and instead the end of the input or output was encountered. This is true for essentially all the I/O APIs, whether it be the C standard library, C++ iostreams, or other libraries. As long as the I/O operations succeed, you simply cannot know whether further, future operations will succeed. You must always first try the operation and then respond to success or failure.
Examples
In each of the examples, note carefully that we first attempt the I/O operation and then consume the result if it is valid. Note further that we always must use the result of the I/O operation, though the result takes different shapes and forms in each example.
C stdio, read from a file:
for (;;) {
size_t n = fread(buf, 1, bufsize, infile);
consume(buf, n);
if (n == 0) { break; }
}
The result we must use is n, the number of elements that were read (which may be as little as zero).
C stdio, scanf:
for (int a, b, c; scanf("%d %d %d", &a, &b, &c) == 3; ) {
consume(a, b, c);
}
The result we must use is the return value of scanf, the number of elements converted.
C++, iostreams formatted extraction:
for (int n; std::cin >> n; ) {
consume(n);
}
The result we must use is std::cin itself, which can be evaluated in a boolean context and tells us whether the stream is still in the good() state.
C++, iostreams getline:
for (std::string line; std::getline(std::cin, line); ) {
consume(line);
}
The result we must use is again std::cin, just as before.
POSIX, write(2) to flush a buffer:
char const * p = buf;
ssize_t n = bufsize;
for (ssize_t k = bufsize; (k = write(fd, p, n)) > 0; p += k, n -= k) {}
if (n != 0) { /* error, failed to write complete buffer */ }
The result we use here is k, the number of bytes written. The point here is that we can only know how many bytes were written after the write operation.
POSIX getline()
char *buffer = NULL;
size_t bufsiz = 0;
ssize_t nbytes;
while ((nbytes = getline(&buffer, &bufsiz, fp)) != -1)
{
/* Use nbytes of data in buffer */
}
free(buffer);
The result we must use is nbytes, the number of bytes up to and including the newline (or EOF if the file did not end with a newline).
Note that the function explicitly returns -1 (and not EOF!) when an error occurs or it reaches EOF.
You may notice that we very rarely spell out the actual word "EOF". We usually detect the error condition in some other way that is more immediately interesting to us (e.g. failure to perform as much I/O as we had desired). In every example there is some API feature that could tell us explicitly that the EOF state has been encountered, but this is in fact not a terribly useful piece of information. It is much more of a detail than we often care about. What matters is whether the I/O succeeded, more-so than how it failed.
A final example that actually queries the EOF state: Suppose you have a string and want to test that it represents an integer in its entirety, with no extra bits at the end except whitespace. Using C++ iostreams, it goes like this:
std::string input = " 123 "; // example
std::istringstream iss(input);
int value;
if (iss >> value >> std::ws && iss.get() == EOF) {
consume(value);
} else {
// error, "input" is not parsable as an integer
}
We use two results here. The first is iss, the stream object itself, to check that the formatted extraction to value succeeded. But then, after also consuming whitespace, we perform another I/O/ operation, iss.get(), and expect it to fail as EOF, which is the case if the entire string has already been consumed by the formatted extraction.
In the C standard library you can achieve something similar with the strto*l functions by checking that the end pointer has reached the end of the input string.
It's wrong because (in the absence of a read error) it enters the loop one more time than the author expects. If there is a read error, the loop never terminates.
Consider the following code:
/* WARNING: demonstration of bad coding technique!! */
#include <stdio.h>
#include <stdlib.h>
FILE *Fopen(const char *path, const char *mode);
int main(int argc, char **argv)
{
FILE *in;
unsigned count;
in = argc > 1 ? Fopen(argv[1], "r") : stdin;
count = 0;
/* WARNING: this is a bug */
while( !feof(in) ) { /* This is WRONG! */
fgetc(in);
count++;
}
printf("Number of characters read: %u\n", count);
return EXIT_SUCCESS;
}
FILE * Fopen(const char *path, const char *mode)
{
FILE *f = fopen(path, mode);
if( f == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return f;
}
This program will consistently print one greater than the number of characters in the input stream (assuming no read errors). Consider the case where the input stream is empty:
$ ./a.out < /dev/null
Number of characters read: 1
In this case, feof() is called before any data has been read, so it returns false. The loop is entered, fgetc() is called (and returns EOF), and count is incremented. Then feof() is called and returns true, causing the loop to abort.
This happens in all such cases. feof() does not return true until after a read on the stream encounters the end of file. The purpose of feof() is NOT to check if the next read will reach the end of file. The purpose of feof() is to determine the status of a previous read function
and distinguish between an error condition and the end of the data stream. If fread() returns 0, you must use feof/ferror to decide whether an error occurred or if all of the data was consumed. Similarly if fgetc returns EOF. feof() is only useful after fread has returned zero or fgetc has returned EOF. Before that happens, feof() will always return 0.
It is always necessary to check the return value of a read (either an fread(), or an fscanf(), or an fgetc()) before calling feof().
Even worse, consider the case where a read error occurs. In that case, fgetc() returns EOF, feof() returns false, and the loop never terminates. In all cases where while(!feof(p)) is used, there must be at least a check inside the loop for ferror(), or at the very least the while condition should be replaced with while(!feof(p) && !ferror(p)) or there is a very real possibility of an infinite loop, probably spewing all sorts of garbage as invalid data is being processed.
So, in summary, although I cannot state with certainty that there is never a situation in which it may be semantically correct to write "while(!feof(f))" (although there must be another check inside the loop with a break to avoid a infinite loop on a read error), it is the case that it is almost certainly always wrong. And even if a case ever arose where it would be correct, it is so idiomatically wrong that it would not be the right way to write the code. Anyone seeing that code should immediately hesitate and say, "that's a bug". And possibly slap the author (unless the author is your boss in which case discretion is advised.)
No it's not always wrong. If your loop condition is "while we haven't tried to read past end of file" then you use while (!feof(f)). This is however not a common loop condition - usually you want to test for something else (such as "can I read more"). while (!feof(f)) isn't wrong, it's just used wrong.
feof() indicates if one has tried to read past the end of file. That means it has little predictive effect: if it is true, you are sure that the next input operation will fail (you aren't sure the previous one failed BTW), but if it is false, you aren't sure the next input operation will succeed. More over, input operations may fail for other reasons than the end of file (a format error for formatted input, a pure IO failure -- disk failure, network timeout -- for all input kinds), so even if you could be predictive about the end of file (and anybody who has tried to implement Ada one, which is predictive, will tell you it can complex if you need to skip spaces, and that it has undesirable effects on interactive devices -- sometimes forcing the input of the next line before starting the handling of the previous one), you would have to be able to handle a failure.
So the correct idiom in C is to loop with the IO operation success as loop condition, and then test the cause of the failure. For instance:
while (fgets(line, sizeof(line), file)) {
/* note that fgets don't strip the terminating \n, checking its
presence allow to handle lines longer that sizeof(line), not showed here */
...
}
if (ferror(file)) {
/* IO failure */
} else if (feof(file)) {
/* format error (not possible with fgets, but would be with fscanf) or end of file */
} else {
/* format error (not possible with fgets, but would be with fscanf) */
}
feof() is not very intuitive. In my very humble opinion, the FILE's end-of-file state should be set to true if any read operation results in the end of file being reached. Instead, you have to manually check if the end of file has been reached after each read operation. For example, something like this will work if reading from a text file using fgetc():
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *in = fopen("testfile.txt", "r");
while(1) {
char c = fgetc(in);
if (feof(in)) break;
printf("%c", c);
}
fclose(in);
return 0;
}
It would be great if something like this would work instead:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *in = fopen("testfile.txt", "r");
while(!feof(in)) {
printf("%c", fgetc(in));
}
fclose(in);
return 0;
}

EOF - scanf and printf

I'm tring to do a simple exercise here, but i need to understand how EOF works first.
void main()
{
char s1[1000];
while (scanf("%s", s1)!=EOF)
;
printf("%s",s1);
}
The idea is to have multiple lines in input, and display them.
The problem I have is that if I put
Hello World
This is stackoverflow
When printf is called, it only prints
stackoverflow
Why isn't it printing everything and how do I make it print?
Regards
Remove the semicolon ;:
while (scanf("%s", s1)!=EOF)
printf("%s",s1);
Note that this will still exhibit odd behavior at end of file depending on how it ends exactly. Furthermore, it splits the input into words, which are separated by spaces or new lines. You may want to simply split into lines.
So you may be better served with for instance:
while (gets(s1)!=NULL)
puts(s1);
This code fragments reads your input line by line until end-of-file.
To read everything (or as much as your buffer can hold), you can use:
char s1[1000] = "";
fread(s1, sizeof(s1) - 1, 1, stdin);
puts(s1);
However, my preferred method of reading a text file is:
using namespace std;
string line;
while (getline(cin, line))
{
cout << line << endl;
}
That is because usually I want to process a file line by line, and getline with a string ensures the line buffer is always big enough.
You probably want this:
char s1[1000][20];
int i = 0 ;
while (!feof(stdin))
fgets(s1[i++], 20, stdin) ;
int j ;
for (j = 0; j < i; j++)
printf("%s\n", s1[j]);
Here you can enter at most 1000 lines that are maximum 19 characters long.
What you have is a loop that reads words into a buffer until it reaches EOF (and does nothing with those words), followed by a printf to print the contents of the buffer. The printf is after the loop (not in it), so executes once after the loop completes. At that time, the buffer will contain the last word read, so that is what gets printed.
The EOF return test means "nothing more to be read", which isn't necessarily an end of file (might be an error condition of some kind), but in practice that distinction can be ignored. Looping until your reading function returns EOF or NULL (depends on function) is good practice.
If you want to print each word as it is read, you need to put a printf in the loop.
If you want to store the words for later processing, you need to store them somewhere. That means declaring some storage space, or allocating space on the heap, and some bookkeeping to track how much space you've used/allocated.
If you want lines rather than words, you should use fgets instead of scanf("%s". Note that fgets returns NULL rather than EOF when there's nothing more to be read.
Because it only prints the last thing that is read from the file ("stackoverflow"). This is caused by the semicolon after the end of your while(...); - this means that you are doing while(...) { /* do nothing */} - which is probably not what you wanted
Also, printf("%s",s1)!='\0'; makes no sense at all. For one thing, printf returns the number of characters printed - '\0' is the value zero written as a character constant. And of course, doing != 0 of the result without some sort of use of the comparison is pretty much pointless too.
Use fgets instead of scanf if you want to read one line at at time. scanf will stop reading when it finds a whitespace. fgets will read till the end of the line.
Use fgets(). Simple and sweet
char buf[1000];
while (fgets(buf, sizeof buf, stdin) != NULL) {
fputs(buf, stdout);
}
Here is how end-of-file works in C. The input channels are called input streams; disk files and stdin are both input streams. The "end-of-file" state is a flag that a stream has, and that flag is triggered when you try to read from a stream, but it turns out there are no more characters in the stream, and there never will be any more. (If the stream is still active but just waiting for user input for example, it is not considered to be end-of-file; read operations will block).
Streams can have other error states, so looping until "end-of-file" is set is usually wrong. If the stream does go into an error state then your loop will never exit (aka. "infinite loop").
The end-of-file state can be checked by feof. However, some input operations also can signal an error as well as, or instead of, returning the actual data they were intended to read. These functions can return the value EOF. Usually these functions return EOF in both cases: end-of-file, and stream error. This is different to feof which only returns true in the case of end-of-file.
For example, getchar() and scanf will return EOF if it was end-of-file, but also if the stream is in an error state.
So it is OK to use getchar()'s result as a loop condition, but not feof on its own.
Also, it is sometimes not OK to use scanf() != EOF as a loop condition. It's possible that there is no stream error, but just that the data you requested wasn't there. For example, if you scan for "%d" but there are letters in the stream. Instead, it's better to check for successful conversion (scanf returns the number of successful conversions it performed). Then when you exit your loop, you can go on to call feof and ferror to see whether it was due to end-of-file, or error, or just unexpected input.

C++ User enters a non-integer value for integer variable

I am working on program where a list of options is displayed to the user and he would then enter an integer to specify which option he wants to select.Now I have pre-empted the situation where the user might enter an integer value apart from the valid ones. But if he enters any other value, say a character or a string, the program goes into an infinite loop with the list of options being printed infinitely. How can i rectify this? I mean, I should be able to give my user an error when for a predefined integer variable he enters a value that is not an integer.
Any help appreciated. Here is a sample code.
do{
printf("Select appropriate option.\n");
printf("Press 1 to do this");
printf("Press 2 to do that.\n");
printf("Press 3 to exit the program.\n");
scanf("%d",&choice);
if(choice!=1 && choice!=2 && choice!=3)
printf("You entered an invalid choice. Please enter again.\n");
switch(choice){
case 1:
//do this
break
case 2:
//do that
break;
case 3:
exit(1);
}}
while(choice!=3);
So basically when a user enters a non-integer value for choice I want the program to notify the user and ask him for another input.
It cannot be done with direct scanf into an integer variable. Such scanf will not only accept 1.23, it will also accept 1abcde and other inputs. scanf (and other conversion functions) reads as much as it can in accordance with the requested format. It stops when it finds something that does not satisfy format requirements and simply leaves it untouched.
If you want to perform this sort of analysis, you have to read the input as string and then parse and analyze that string manually.
A C-style code sketch (since you insist on C-style code, despite having tagged it as [C++]) might look as follows
char buffer[100]; /* 100 should be enough for everyone :) */
int n = scanf("%s", buffer);
if (n < 1)
/* ERROR, can't read */;
char *end;
long choice = strtol(buffer, &end, 10);
if (end == buffer || *end != '\0' || errno == ERANGE)
/* ERROR, bad format */;
/* ... */
scanf will not consume any non-digits when converting %d. It will return 0 because it didn't convert anything, and the "bad input" will still be there waiting to be consumed. You have to consume it in some way to be ready for a valid input.
(also note you're excluding 3 in your if before testing for it in your switch)
Use iostream - see http://www.cplusplus.com/reference/iostream/
Having said that if you insist on using scanf - check the return value - i.e. read http://linux.die.net/man/3/scanf
isdigit will check for any input that is a digit(number) type.
For this include header ctype.h.
Also terminate your program using exit(0) if input is incorrect.
For this include header stdlib.h.
#include<ctype.h>
#include<stdlib.h>
char c;
scanf("%c", &c);
if (isdigit(c))
{
case statement...
...
...
}
else
{
printf("Wrong input");
exit(0);
}

Why does scanf appear to skip input?

I am confused about scanf's behaviour in the following program. scanf appears to input once, and then not input again, until a stream of characters is printed.
Below in a C program
#include<stdio.h>
int main()
{
int i, j=0;
do
{
++j;
scanf("%d", &i);
printf("\n\n%d %d\n\n", i, j);
}
while((i!=8) && (j<10));
printf("\nJ = %d\n", j);
return 0;
}
here, Till i am inputting any integer program works perfectly fine, but when a character is inputted it goes on printing the last inputed value of i and never stops(untill j is 10 when loop exits) for scanf to take next input.
output::
1 <-----1st input
1 1
2 <---- 2nd input
2 2
a <---- character input
2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 10
J = 10
same thing is happening in c++ also.
#include<iostream>
using namespace std;
int main()
{
int i, j=0;
do
{
++j;
cin>>i;
cout<<i<<" "<<j<<"\n";
}
while((i!=8) && (j<10));
cout<<"\nj = "<<j<<"\n";
}
output of c++ program ::
1 <-----1st input
1 1
2 <-----2nd input
2 2
a <------ character input
0 3
0 4
0 5
0 6
0 7
0 8
0 9
0 10
j = 10
only change in c++ is that 0 is being printed instead of last value.
I know here integer values are expected by the program, but i want to know what happens when character is inputted in place of an integer?
what is the reason of all happening above?
When you enter a, then cin >> i fails to read it because the type of i is int to which a character cannot be read. That means, a remains in the stream forever.
Now why i prints 0 is a different story. Actually it can print anything. The content of i is not defined once the attempt to read fails. Similar thing happens with scanf as well.
The proper way to write it this:
do
{
++j;
if (!(cin>>i))
{
//handle error, maybe you want to break the loop here?
}
cout<<i<<" "<<j<<"\n";
}
while((i!=8) && (j<10));
Or simply this (if you want to exit loop if error occurs):
int i = 0, j = 0;
while((i!=8) && (j<10) && ( cin >> i) )
{
++j;
cout<<i<<" "<<j<<"\n";
}
If scanf sees a character in the input stream that doesn't match the conversion specifier, it stops the conversion and leaves the offending character in the input stream.
There are a couple of ways to deal with this. One is to read everything as text (using scanf with a %s or %[ conversion specifier or fgets) and then use atoi or strtol to do the conversion (my preferred method).
Alternately, you can check the return value of scanf; it will indicate the number of successful conversions. So, if scanf("%d", &i); equals 0, then you know there's a bad character in the input stream. You can consume it with getchar() and try again.
You can never expect your users to enter valid things. The best practice is to read the input into a string and try to convert it to integer. If the input is not an integer, you can give an error message to the user.
The problem is that when you enter an input that is not of the expected type (specified by %d for scanf, and the int type for cin>>i;, the inputstream is not advanced, which results in both operations trying to extract the same type of data from the exact same incorrect input (and failing just as well this time around too), thus you will never asked for another input.
To ensure this does not happen you will need to check the return value of both operations (read the manual for how each reports errors). If an error does happen (as when you enter a character), you will need to clear the error, consume the invalid input and try again. I find it better in C++ to read a whole line using std::gtline() instead of int or even std::string when geting input from ther user interactively, so you get into this "infinite" loop you experienced.
You are ignoring the return value. See what the manual says about scanf(3):
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.
It fails matching an integer.
You could check the return value of scanf to determine if an integer has been parsed correctly (return should =1). On failure, you have choices: either notify the user of the error and terminate, or recover by reading the next token with a scanf("%s" ...) perhaps with a warning.
For scanf, you need to check its return value to see if the conversion on the input worked. scanf will return the number of elements successfully scanned. If the conversion did not work, it will leave the input alone, and you can try to scan it differently, or just report an error. For example:
if (scanf("%d", &i) != 1) {
char buf[512];
fgets(buf, sizeof(buf), stdin);
printf("error in line %d: got %s", j, buf);
return 0;
}
In your program, since the input is left alone, your loop repeats trying to read the same input.
In C++, you check for failure using the fail method, but the input stream failure state is sticky. So it won't let you scan further without clearing the error state.
std::cin >> i;
if (std::cin.fail()) {
std::string buf;
std::cin.clear();
std::getline(cin, buf);
std::cout
<< "error in line " << j
<< ": got " << buf
<< std::endl;
return 0;
}
In your program, since you never clear the failure state, the loop repeats using cin in a failure state, so it just reports failure without doing anything.
In both cases, you might find it easier or more reliable to work with the input if you would read in the input line first, and then attempt to parse the input line. In pseudocode:
while read_a_line succeeds
parse_a_line
In C, the catch to reading a line is that if it is longer than your buffer, you will need to check for that and concatenate multiple fgets call results together to form the line. And, to parse a line, you can use sscanf, which is similar to scanf but works on strings.
if (sscanf(buf, "%d", &i) != 1) {
printf("error in line %d: got %s", j, buf);
return 0;
}
In C++, for quick low level parsing of formatted input, I also prefer sscanf. But, if you want to use the stream approach, you can convert the string buffer into a istringstream to scan the input.
std::getline(cin, buf);
if (std::cin.fail()) {
break;
}
std::istringstream buf_in(buf);
buf_in >> i;
if (buf_in.fail()) {
std::cout << "error in line " << j
<< ": got " << buf
<< std::endl;
return 0;
}

How to use fscanf to reads any character into a string until a tab is reached?

How to use fscanf to reads any character into a string until a tab is reached?
My data file have only 1 row:
123'\t'(Tab)345'\t'Le Duc Huy'\t'567
and i use fscanf like this:
fscanf(fin,"%d %d %d %[^\t]%s %d",&m,&n,&k,s,&q);
it return q with wrong value. Anybody can tell me what made it failed?
Using fscanf(), you will need a negated character class and a length:
char string[32];
if (fscanf(fp, "%31[^\t]", string) != 1)
...error or EOF...
The modified version of the question has a data string with a single quote after the final tab, and the single quote cannot be converted to an integer, so the value in q is undefined. Note that you must check the return value of fscanf() to ensure that all the fields you expected to match actually did match, In the context, if probably returned the value 4 instead of 5, telling you there was an error.
Instead of fscanf I would just use fgetc (though my syntax may be off a bit):
int c;
string s = "";
for (;;)
{
c = fgetc(somefile);
if (c == '\t' || c == EOF) break;
s += c;
// ...
}
Here's the fscanf() version:
fscanf (stream, "[^\t]", output);
Note, this is not safe!
char foo[100];
scanf("%s\t", foo);
You have no way of keeping the user from overflowing the buffer
Eliminate the space before %[. It's eating your tab. Also, as others have said, this code is unsafe and probably unreliable on input that's not formatted exactly as you expect. It would be better to use fgets and then parse it yourself with strtol and a few for loops.