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

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.

Related

Check scanf formating without conversions

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.

using getchar() and getting stuck in loop [duplicate]

For my homework assignment, I need to implement Horners Algorithm for converting between bases.
I have been told to use getchar() for this assignment. But I am having a problem where when I hit enter, the program doesn't terminate and just takes in more chars.
Example:
bryce> ./pa1
Enter the fromRadix:16
Enter the toRadix:2
abc
abc
^C
bryce>
Code:
int readRadixA(int radixA)
{
char myChar = getchar();
int result = 0;
int run = 0;
while(myChar != EOF)
{
if(myChar == "\n")
break;
Horners();
myChar = getchar();
}
return result;
}
I am not asking for help implementing Horners; I am asking for help to terminate the getchar() correctly.
if(myChar=="\n")
^ ^
You're comparing myChar wrong. Try this instead:
if(myChar == '\n')
^ ^
A second problem is that getchar returns int, not char. Maybe you can rewrite it like this:
int myChar;
while((myChar = getchar()) != EOF && myChar != '\n')
{
/* Your stuff. */
}
EDIT
In light of comments, I think some stdio operation before that while is leaving a \n in the buffer.
Instead of scanf("%d", &radix) try:
scanf("%d ", &radix);
^
That space will make scanf eat the remaining blanks (including the newline).
Check the return type of getchar(). Yes, it's an int. That's because EOF must have a value that can be distinguished from a valid character. myChar must actually be made to be int.
Try this code
int readRadixA(int radixA)
{
char myChar;
int result = 0;
int run = 0;
do
{
myChar = getchar();
// implement horners here
}while(myChar != 13);
return result;
}
I checked your code I think you are leaving a '\n' in the input keyboard buffer after the toRadix.
And their is one more thing that
getchar()
reads all the characters in one go till a '\n' is received.
And there is one more mistake you have committed by comparing a
char to a pointer e.g mychar=="\n"
further information about your implementation of toRadix can be really helpful to answer your question
On linux, to end the standard input, you have to type  Ctrl-D. The kernel and tty layers makes that an end-of-file mark or condition. Then getchar gives EOF (which is not a valid char, for example on systems where char are unsigned bytes between 0 and 255, EOF could be -1).
Notice that feof(3) is valid only after a read operation (e.g. getchar, fgets, etc...) so coding while(feof(stdin)) is generally wrong (contrarily to what I wrote in the previous version of this answer). You'll better test that getchar is returning EOF so your myChar should be an int (not a char).

Reading string by char till end of line C/C++ [duplicate]

This question already has answers here:
c++ compile error: ISO C++ forbids comparison between pointer and integer
(5 answers)
Closed 5 years ago.
How to read a string one char at the time, and stop when you reach end of line? I'am using fgetc function to read from file and put chars to array (latter will change array to malloc), but can't figure out how to stop when the end of line is reached
Tried this (c is the variable with char from file):
if(c=="\0")
But it gives error that I cant compare pointer to integer
File looks like (the length of the words are unknown):
one
two
three
So here comes the questions:
1) Can I compare c with \0 as \0 is two symbols (\ and 0) or is it counted as one (same question with \n)
2) Maybe I should use \n ?
3) If suggestions above are wrong what would you suggest (note I must read string one char at the time)
(Note I am pretty new to C++(and programming it self))
You want to use single quotes:
if(c=='\0')
Double quotes (") are for strings, which are sequences of characters. Single quotes (') are for individual characters.
However, the end-of-line is represented by the newline character, which is '\n'.
Note that in both cases, the backslash is not part of the character, but just a way you represent special characters. Using backslashes you can represent various unprintable characters and also characters which would otherwise confuse the compiler.
The answer to your original question
How to read a string one char at the time, and stop when you reach end of line?
is, in C++, very simply, namely: use getline. The link shows a simple example:
#include <iostream>
#include <string>
int main () {
std::string name;
std::cout << "Please, enter your full name: ";
std::getline (std::cin,name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
Do you really want to do this in C? I wouldn't! The thing is, in C, you have to allocate the memory in which to place the characters you read in? How many characters? You don't know ahead of time. If you allocate too few characters, you will have to allocate a new buffer every time to realize you reading more characters than you made room for. If you over-allocate, you are wasting space.
C is a language for low-level programming. If you are new to programming and writing simple applications for reading files line-by-line, just use C++. It does all that memory allocation for you.
Your later questions regarding "\0" and end-of-lines in general were answered by others and do apply to C as well as C++. But if you are using C, please remember that it's not just the end-of-line that matters, but memory allocation as well. And you will have to be careful not to overrun your buffer.
If you are using C function fgetc then you should check a next character whether it is equal to the new line character or to EOF. For example
unsigned int count = 0;
while ( 1 )
{
int c = fgetc( FileStream );
if ( c == EOF || c == '\n' )
{
printF( "The length of the line is %u\n", count );
count = 0;
if ( c == EOF ) break;
}
else
{
++count;
}
}
or maybe it would be better to rewrite the code using do-while loop. For example
unsigned int count = 0;
do
{
int c = fgetc( FileStream );
if ( c == EOF || c == '\n' )
{
printF( "The length of the line is %u\n", count );
count = 0;
}
else
{
++count;
}
} while ( c != EOF );
Of course you need to insert your own processing of read xgaracters. It is only an example how you could use function fgetc to read lines of a file.
But if the program is written in C++ then it would be much better if you would use std::ifstream and std::string classes and function std::getline to read a whole line.
A text file does not have \0 at the end of lines. It has \n. \n is a character, not a string, so it must be enclosed in single quotes
if (c == '\n')

Find a string in a file C++

I am trying to parse a file in C++. My file contents are as follows:
//Comments should be ignored
FileVersion,1;
Count,5;
C:\Test\Files\Test_1.txt 0,16777216,16777552,0,0,1,0,1,1,1;
FileVersion is the first line I need to read information. All the previous lines are just comments which begin with a '//'. How do I set my cursor to line containing FileVersion? Becuase I am using fscanf to read the information from the file.
if ( 1 != fscanf( f, "FileVersion,%d;\n", &lFileVersion ))
{
//Successfully read the file version.
}
I like to write parsers (assuming "line-based") by reading a line at a time, and then using sscanf strncmp and strcmp (or C++'s std::stringstream and std::string::substr) to check for various content.
In your example, something like:
enum Sates
{
Version = 1,
Count = 2,
...
} state = Version;
char buffer[MAXLEN];
while(fgets(buffer, MAXLEN, f) != NULL)
{
if (0 == strncmp("//", buffer, 2))
{
// Comment. Skip this line.
continue;
}
switch (state)
{
case Version:
if (0 == strncmp("FileVersion,", buffer, 12))
{
if (1 == sscanf(buffer, "FileVersion,%d;", &version))
{
state = Count;
break;
}
Error("Expected file version number...");
}
break;
...
}
}
There are of course oodles of other ways to do this.
Since this is tagged C++, I will give you a C++ solution.
You can use a single call to f.ignore() to discard the first line of the stream:
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Technically this skips everything up and including the newline at the end of the first line, so the stream position will be just before the newline on the second line. Formatted I/O discards leading whitespace so this will be no issue.
The above requires the use of C++ file streams since this is C++, and the use of the formatted operators operator>>() and operator<<() to perform input and output.
Not a particular C++ solution, but:
read a line with fgets (oh okay, if you want, you can substitute a C++ function for that);
if it starts with your 'comment' designator, skip to end of loop
if the line is empty (i.e., it contains only a hard return; or, possibly, check for zero or more whitespace characters and then an end-of-line), skip to end of loop
at end of loop: if you got something else, use sscanf on that string.

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.