Scanf understandings - c++

I am going through some examples in a book I have and I have come to something I've never seen before nor understand:
scanf("%d-%d-%d-%d-%d", &prefix, &group, &publisher, &item, &check_digit);
This code is part of a program that asks the user to enter their ISBN number of a book and later on breaks down the ISBN into Prefix = x, Group = y, etc..
I have NEVER seen the hypens between the %d's. Does anyone see any point in this??
Thanks

"Pattern matching". If the input doesn't fit the specified pattern (also called format), it fails. So if you input anything else than INT-INT-INT-INT-INT (where INT is a placeholder for an integer you input), the input would be considered invalid.

The represent the actual parts of the string to be scanned.
For example your "%d-%d-%d-%d-%d" would work with something like "10-56-666-1-90".

It parses 5 numbers (matched by %d) with a dash between each two (the -). Each number is saved to a variable passed in as argument. See the manual for scanf and printf under Conversions.

scanf takes a format string, so it's about what input it expects to see for input. The hyphens are for actual hyphens in the input. 1-2-3-4-5-6 would be valid input for this call, and give you prefix=1, group=2, etc.

Related

FLUTTER - Checking if a string contains another one

I am working on an English vocabulary learning app. Some of the exercises given to the users are written quizzes. They have to translate French words into English words and vice versa.
To make the checking a little more sophisticated than just "1" or "0" (TypedWord == expectedWord), I have been working with similarities between strings and that worked well (for spelling mistakes for example).
I had also used the contains function, so that for example, if the user adds an article in front of the expected word, it doesn't consider it wrong. (Ex : Ecole (School is expected), but user writes "A school").
So I was checking with lines such as "if (typedWord.contains(word)==true) then...". It works fine for the article problem.
But it prompts another issue :
Ex : A bough --> the expected French word is "branche". If user types "une branche", it considers it correct, which is great. But if user types "débrancher" (to unplug), it considers it correct as well as the word "branche" is a part of "débrancher"...
How could I keep this from happening ? Any idea of other ways to go about it ?
I read the three proposed answers which are really interesting. The thing is that some of the words are compound.... "Ex : kitchen appliance, garden tool" etc... so then I think the "space" functions might be problematic...
In this case, separate the whole answer with the "space", then compare it with the correct word.
For an example:
User's answer: That is my school
Separate it with space, so that you will find an array of words:
that, is, my, school.
Then compare each word with your word. It will give you the correct answer.
The flutter code will be like below:
usersAnswer?.split(" ").forEach((word){
if(word == correctAnswer)
print("this is a correct answer");
});
You can split the string by space and check if the resulting array has the word you're looking for.
typedWord.split(' ').contains('debranche');
So if typedWord is 'une branchethesplit(' ') will turn it into this array: ['une', 'branche'].
Now when you check if this array contains('branche') it will check if the exact string branche exists which in this case it does and returns true.
However if it's 'une debranche' the resulting array would be: ['une', 'debranche'] and because this array has no value equal to 'branche' it will return false. Remember that when you use split it turns the string into an array and by using contains on an array it checks whether or not an item of exactly the value you provide contains exists or not, whereas in a string it checks if part of that string matches the given value or not.
You could check for whitespaces before and after the correct word: something like if (typedWord.contains(' '+word+' ')==true) then..., so that "débrancher" gets marked as wrong. This is kind of strict, though: if the sentence must be completed with some punctuation, it would be rejected by this check. You'll probably want some RegExp that allows punctuation but not whitespaces.

How to take this kind of a STDIN inputs in c++?

In lots of hackathon they provide testcases. So in those test cases they provide inputs in different ways through STDIN. This is one of the situation I struggle at all.
This is one kind of a input: (This is one testcase)
Mike
John
Ahmed
Sangha
Daniel
Ann
So here I have 6 inputs. But they don't provide number of inputs. So I can't use for loop or while loop to take this input. Because I don't know how many iteration I should do. So I have to take inputs until end. But this is not a input from a file. So I can't use EOF as well. This input is from STDIN. So how can I take this kind of input and store it in an array? Also I don't know how many elements should create in array. Because I don't know how many number of inputs are there. (different testcases may contain different number of inputs). How can I solve this kind of a problem?
Thank you so much for the help!
You should be able to use EOF, because stdin is a file (at least on linux)
The input here clearly shows you how many entries are presented. Note that each entry is on a newline so, considering it as a delimiter, you can parse your input stream and get the entries separated and also get the count of entries.
C++ getline() does this exactly:
istream& getline( istream& is, string& str, char delim );
Last param to getline is optional because it uses '\n' as default.
If you want to do it the raw way, you could setup a file pointer and do a lookahead for '\n' and read everything before it into new item of a variable array(vector) ...do this repeatedly until u reach EOF of stream(or filestream)

Good way to tokenize a string to store values? Or alternative for user input

Hello again Stackoverflow, I'm here again asking a question for my C++ programming class. The problem I am facing is mostly to due with user input from the keyboard. I need to be able to take the user input to decide what function to call and what arguments to give the function. For example something like add 5 would call the add function with the argument 5. At first I tried overloading the >> operator to take both a string and an int but the problem I ran into was the program was unable to take input without the int such as deletemax so I had to throw that idea out. So now I am back to tokenizing the input but we are not allowed to use Boost for this program so I came up with something like this using sstream
bool out = false;
string token;
string In;
int num;
do
{
cout << "heap> ";
cin >> In;
istringstream iss(In);
while(getline(iss, token, ' '))
{
cout << token << endl; //I know this is incorrect but just not what to replace it with
}
out = ProcessCommand (token, num); //Takes string and int to call correct functions
} while (out != true);
The problem lies in that I'm not quite sure how to correctly tokenize the string so I can get 2 string and convert the second string to an int. Can anyone offer me some assistance? I would greatly appreciate it. Also if there is a better way to go about this than I am trying I would also like to hear it.
Thanks for any help you can give me.
Googling "C++ string tokenize" will get you plenty of hits, with the first hit being on Stackoverflow. But you should take a stab at it. I'm guessing it's the point of the exercise.
You said "argumentS", which suggests that commands you support take varying numbers of arguments. I'd break it down like this:
read a line from the user
split line into 'tokens' on space boundaries, store tokens in a list
based on the first token in the list, choose a command to execute
pass the list of tokens to the command, so it can validate/interpret them as arguments
The tricky part is #2. Do you know about container classes yet? You can use vector<string> to store the chunks you parse. To do the actual parsing, you iterate through the characters of the string. Skip whitespace until you find a non-whitespace character (or run out of characters). Save this position: start. Then skip non-whitespace until you find whitespace (or run out of characters). Save this position: end. Copy the substring represented between from start to end and copy that to your token list.
Working out the actual details of this, making sure you don't have off-by-on-errors, etc. is going to be challenging if you've never done it before, which I'm guessing is the point.
You don't need to read in the whole of user input all at once.
For example you could read in the first bit of user input (the operation, add or deletemax, etc). From there depending on the operation you could continue to read arguments from input (in the case of add) or begin performing the operation immediately (in the case of deletemax).
One way would be to have a std::map of function names as keys and required number of arguments as values. You'd read a line of input, get the function name and then decide whether you need aditional arguments. I'd write a function that'd return a vector of arguments extracted from a string stream or an empty vector in case the input was invalid.

How can I left-justify numerical output in fortran?

I am writing some simple output in fortran, but I want whitespace delimiters. If use the following statement, however:
format(A20,ES18.8,A12,ES18.8)
I get output like this:
p001t0000 3.49141273E+01obsgp_oden 1.00000000E+00
I would prefer this:
p001t0000 3.49141273E+01 obsgp_oden 1.00000000E+00
I tried using negative values for width (like in Python) but no dice. So, is there a way to left-justify the numbers?
Many thanks in advance!
There's not a particularly beautiful way. However, using an internal WRITE statement to convert the number to a text string (formerly done with an ENCODE statement), and then manipulating the text may do what you need.
Quoting http://rsusu1.rnd.runnet.ru/develop/fortran/prof77/node168.html
An internal file WRITE is typically
used to convert a numerical value to a
character string by using a suitable
format specification, for example:
CHARACTER*8 CVAL
RVALUE = 98.6
WRITE(CVAL, '(SP, F7.2)') RVALUE
The WRITE statement will fill the
character variable CVAL with the
characters ' +98.60 ' (note that there
is one blank at each end of the
number, the first because the number
is right-justified in the field of 7
characters, the second because the
record is padded out to the declared
length of 8 characters).
Once a number has been turned into a
character-string it can be processed
further in the various ways described
in section 7. This makes it possible,
for example, to write numbers
left-justified in a field, ...
This is easier with Fortran 95, but still not trivial. Write the number or other item to a string with a write statement (as in the first answer). Then use the Fortran 95 intrinsic "ADJUSTL" to left adjust the non-blank characters of the string.
And really un-elegant is my method (I program like a cave woman), after writing the simple Fortran write format (which is not LJ), I use a combination of Excel (csv) and ultraedit to remove the spaces effectively getting the desired LJ followed directly by commas (which I need for my specific import format to another software). BF
If what you really want is whitespace between output fields rather than left-justified numbers to leave whitespace you could simply use the X edit descriptor. For example
format(A20,4X,ES18.8,4X,A12,4X,ES18.8)
will insert 4 spaces between each field and the next. Note that the standard requires 1X for one space, some of the current compilers accept the non-standard X too.
!for left-justified float with 1 decimal.. the number to the right of the decimal is how many decimals are required. Write rounds to the desired decimal space automatically, rather than truncating.
write(*, ['(f0.1)']) RValue !or
write(*, '(f0.1)') RValue
!for left-justified integers..
write(*, ['(i0)']) intValue !or
write(*, '(i0)') RValue
*after feedback from Vladimir, retesting proved the command works with or without the array brackets

checking float inside a string and return result?

I have a text file which I geline to a string. The file is like this: 0.2abc 0.2 .2abc .2 abc.2abc abc.2 abc0.20 .2 . 20
I wanna check the result then parse it in to separate float. The result is:0.2 0.2abc 2 20 2abc abc0.20 abc
This is expalined: check if there is 2 digit (before and after '.' (full stop)) whether with char or not. If only 1 site of the '.' is digit the '.' will be full stop.
How can I parse a STRING to separate result like that? I did use iterator to check the '.' and pos of it, but still got stuck.
The first thing you need to do is split the input in words. Easy, just don't use .getline()
but instead rely on `while (cin >> strWord ) { /* do stuff with word*/ };
The second thing is to kick out bad input words early: words of 2 characters or less, with more than one ., or with the . first or last.
You now know that the . is somewhere in the middle. find() will give you an iterator. ++ and -- give you the next and previous iterators. * gives you the character that the iterator points to. isdigit() tells you whether that character is a digit. Add ingredients together and you're done.
Seems like some fairly complicated advice above -- and not necessarily helpful.
Your question does not make it entirely clear what the end result should look like. Do you want an array of floating point numbers? Do you just want the sum? Do you want to print out the results?
If you want help with homework, the best policy is to post your own attempt and then others can help you improve it, to make it work.
One approach that might help is to try to break the string into sub-strings (tokens) and discard the junk.
Write a function that accepts a character and returns true (this is part of a floating point number) or false (it isn't).
Scan along the string using an iterator or an index.
While current char is not part of a token, skip it.
If you find a token char, while current char is part of a token, copy it to another string
etc. to get all floating point substrings.
Then you can use std::stringstream or ::atof() to convert.
Have a bit of a go and post what you can get done.
sounds like you could use some regex to extract your number.
Try this regex in order to extract the floating values within a string.
[0-9]+\.[0-9]+
Keep in mind that this won't extract integer values. ie 234abc
I don't know if there is a built-in way to use regex in c++ but i found this library with a quick google search which allows you to use regex in c++
Sounds like you should look at the "Interpreter" Design Pattern.
Or you could use the "State" Design Pattern and do it by hand.
There should be plenty of examples of both on the web.