Error inserting string key,value in unordered_map - c++

I am writing my first STL program in C++, and I am facing this issue.
This is my program :
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
int n,m;
// n : number of file extenstions
// m : number of filenames to identify
string extension, type, filename;
cin >> n >> m;
unordered_map<string,string> hashmap;
while(n--)
{
cin >> extension >> type;
hashmap.insert(make_pair<string,string>(extension,type));
}
while(m--)
{
cin >> filename;
extension = filename.substr(filename.find_last_of('.')+1);
cout << extension << endl;
}
}
My input file is :
5 6
html text/html
htm text/html
png image/png
svg image/svg+xml
txt text/plain
index.html
this.file.has.lots.of.dots.txt
nodotsatall
virus.exe
dont.let.the.png.fool.you
case.matters.TXT
I am getting error : no matching function for call to ‘make_pair(std::string&, std::string&)’ . I cannot figure out the problem.

The error is in the line
make_pair<string,string>(extension,type)
It should instead be
make_pair(extension, type)

First of all, I'd rather use make_pair(extension, type) and let the compiler to deduce the types in any case, to avoid any risks, as someone else suggested.
Anyway, I see that the details below are interesting from your point of view, thus it's worth to put them in a dedicated response, hoping they are also right.
That said, see the documentation.
As far as I understand (I'm far from being an expert) the deduced types in your case would be T&, U&, thus using the couple T, U (as <string, string>) ends in a function prototype that doesn't accept references as arguments (that's why you got the error and that one specifically).
You can use instead the following pattern in your case:
make_pair<string&,string&>(extension,type)
This one works for you actually use references to initialize the pair and you are going to require the sames as template arguments.
Again, for the make_pair can easily deduce the types of its arguments, you can freely omit them and I strongly suggest to do that.

Related

Why are some programmers using string as an input and then converting it?

I've recently came across this code in C++:
int main(){
std::string a='0'; //I missed the quotes here anyways that wasn't
//really necessary for the question
std::cout<<"Enter your number: ";
getline(std::cin,a);
int ia=std::stoi(a);
return 0;
}
So why would someone write code like that, when you can write it like this:
int main(){
int a=0;
cout<<"Enter a number: ";
cin>>a;
return 0;
}
(I'm using using namespace std; by the way)
Why write longer code like in the first example? Is it more efficient considering time and memory?
There's more than one way to take this kind of input, and believe me, there are a multitude of weird, bizarre, if not just plain wrong ways to do it.
Reading into a std::string means you can do your own validation and surface errors where the conversion failed, or if the input was unexpectedly long or short.
If you read into an int you will get an int but it can obscure errors on input meaning you have fewer opportunities to provide feedback about conversion issues.
For example, with the std::cin >> a method you can input "lol" and you get back 0 which glosses over the fact that what you put in is total trash.
This is why it's often advantageous to read in a whole line into a std::string and do your own parsing, like checking with a regular expression that the format is correct before converting, otherwise surfacing errors.

I need help writing a function that checks the data type of another variable

Hi i'm having trouble making a function that checks the data type of a variable and checks it to make sure if a data type is similar to it in C++. Here's my code so far:
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
int typeCheck(string words, string typeWanted);
//make number assurance function .
string word;
cin >> word;
typeCheck(word, "string");
}
int typeCheck(string words, string typeWanted) {
if (typeid(words).name() != typeid(typeWanted).name()) {
cin.clear();
cin.ignore();
return 0;
}
else if (typeid(words).name()== typeid(typeWanted).name())
cout << "All good";
}
When I run the code it keeps saying the same output which is: All good even if I put a string or an int when its not the correct one. Instead of saying this I want it to clear the buffer and ignore it. Can anyone help me with this problem? Thanks in advance!
C++ is a statically typed language, meaning that the type is known at compile time. It will never be known only at run time.
What that means is that in your example:
int typeCheck(string words, string typeWanted);
both words and typeWanted will always be strings. If it is ever not a string, it will fail to compile. Thus, using typeid() in this situation is somewhat pointless. Your if statement will always be false, and your else-if statement will always be true.
Instead, you would want to use typeid() when you don't know they will be the same type, like in some sort of template situation:
template <class WordsType, class TypeWantedType>
int typeCheck(WordsType words, TypeWantedType typeWanted);
Here, a typeid() comparison makes more sense, because you don't really know if words and typeWanted are both strings.
You could do something like this instead:
template <class WordsType>
int typeCheck(WordsType words, string typeWanted) {
if (typeid(words).name() != typeWanted) {
//...
}
// ...
}
This would compare an unknown type to a wanted type.
Finally, there is another option, #RSahu's option from the comments:
if(words == typeWanted) {
//...
}
This will compare the input the user gave to the string "string".
It's unclear to me what you want to do exactly, so I can't recommend which one you should use, but at least now you have a couple of options.
It is because you are converting the type to string eaither way so it will allways trigger as correct as long as it is a string in the function input.
I would recommend that you use a template type so that whatever you enter into the TypeCheck() function will retain its type.

using input redirection in while loop

I need to create a program that reads in a list of random integers via input redirection and performs various tasks with them. For the purpose of this question I just want to print the sum of each number + 1. Trouble is, I don’t know how to get it to perform the operation on anything but the first number in the list. My mini program (program.cpp) is
#include <iostream>
using namespace std;
int main () {
int input;
bool arb = true;
cin >> input;
while (arb) {
cout << input + 1 << endl;
}
return 0;
}
and a sample textfile (textfile.txt) I'm using contains
9
8
7
6
When I run it it prints out “10” for infinity. What I’d like it do is print out
10
9
8
7
or the equivalent for whatever other text file may be used.
I thought maybe I could somehow reference specific lines in the textfile, but from searching how to do that all the similar questions I could find seemed to have solutions that required fstream, which is something I haven’t learned yet and therefore I’m not allowed to use it (this is for a class assignment).
The only compiler directives I’ve learned are iostream, string, cmath, iomanip, cstdlib, and ctime. The ways to get input I’ve learned are cin >> input, cin.get(input), and cin.getline(input), so if there are other ways of reading in the file besides those 3 that I’m unaware of, unfortunately I can’t use it. Note that my program HAS to use a while loop. The way the program will be run is
./program < whatevertextfile.txt
which I can't change.
given these restrictions, how can I get my program to read in and use each integer in the text file?
The idiomatic way to read a sequence of white-space separated integers in C++ would be
#include <iostream>
using namespace std;
int main () {
int input;
while (cin >> input) {
cout << input + 1 << endl;
}
return 0;
}
Let's come to why this works the way it does.
cin >> input
discards possible white-space and then reads an integer from the standard input. Moreover, it returns a reference of the cin object used. With this returned reference, you can call the bool conversion operator to check if any of the fail bits is set in the given std::basic_ios object. So
while (cin >> input)
does two things. Read an integer from standard input and check if it successfully completed the operation. As long as this operation succeeds, your while loop continues to iterate and you print the numbers.
See http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt for reference on std::basic_istream::operator>>.
See http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool for reference on operator bool.
Edit1: Move references to bottom so that the answer is more readable.

read and extract informations from file c++

I am trying to find a solution for the error that the c++ compiler (codeblocks) keeps showing to me,I searched for answers on the net but none of them seemed to be helpful.
I have a txt file in which there are numbers,each of them is written in a line.
What i want is to read each number(line by line)and store it in a variable after converting it from string to float.
This my code
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
float z;
int j=0;
stringstream s;
const ifstream fich1;
fich1.open("test.txt",ios::in);
if(!fich1)
{
cerr<<"could not open the file";
EXIT_FAILURE;
};
else const string ligne1;
while((!fich1.eof())
{
if(j!=i)
{
j++;
getline(fich1,l1); // the first error is: no matching function for call to ‘getline(const ifstream&, const string&)
else if(j == i)
{
fich1>>s; // the second error is: ambiguous overload for ‘operator>>’ (operand types are ‘const ifstream {aka const std::basic_ifstream<char>}’ and ‘std::stringstream {aka std::basic_stringstream<char>}’)
z=(float)s; // I couldn't find a clear answer to convert from string to float
}
}
if anyone wants to ask any question about the code to make it clearer may ask it please,I am waiting for your answers as well as your questions :)
After the edit, I am able to read some code, but still I am suggesting the example I have below, since I am see scary things, like an EOF inside a loop!
Oh also, if you have C++11 support, then you could use std::stof.
You could try this (since your post is not readable), which reads a file line by line and stores every float number in a vector:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
int main() {
std::vector<float> v;
std::string rec_file = "test.txt";
std::string line;
std::ifstream myfile(rec_file.c_str());
if(myfile.is_open()) {
while(std::getline(myfile,line)) {
if(!line.empty())
v.push_back(atof(line.c_str()));
}
myfile.close();
} else {
std::cerr << "Unable to open file";
}
for(unsigned int i = 0; i < v.size(); ++i)
std::cout << v[i] << std::endl;
return 0;
}
with the test.txt to be:
1.2
2.3
3.4
4.5
5.6
6.7
and the output:
1.2
2.3
3.4
4.5
5.6
6.7
Your ifstream shouldn't be constant, as getline alters the ifstream.
To convert from char array to float use atof(chararray)
To convert from string to float you could use atof(string.cstr())
You cannot use const here. But that's not your only problem.
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
Looks good.
float z;
int j=0;
stringstream s;
There should be some int main() { here, because that is the function called by the runtime when a C++ executable starts. This isn't Bash or Perl where execution simply picks up at the first statement.
And you either need to write using namespace std; or prefix identifiers like stringstream as std::stringstream.
const ifstream fich1;
This won't work. ifstream must not be declared const. (This is actually the explanation for the errors you encountered, but you made many more.)
An input file stream is an object with complex inner state, like where in the file you're currently at, error flags etc.; this inner state is changing so const ifstream simply won't work.
fich1.open("test.txt",ios::in);
This can't work either due to const, just like all the other operations on fich1 you're doing further down.
if(!fich1)
{ cerr<<"could not open the file";
EXIT_FAILURE;
};
EXIT_FAILURE is a symbolic constant for a return value. As-is, you could just as well have written 0;. If you expected this to end your program, you're wrong.
;
The semicolon ends the if.
else
Since the if has ended, this is a syntax error.
const string ligne1;
If you declare a string const, you cannot assign to it. Besides, even if the else were correct, that semicolon would have ended the else, because you didn't add braces (as you should always do, even with one-line blocks, because it's so easy to make mistakes otherwise).
The way the code continues, I very much doubt this was your intention. (Some discipline with the indenting makes this kind of mistakes really easy to spot.)
while((!fich1.eof())
How to read until EOF from cin.
{ if(j!=i)
{j++;
Do some proper indenting, will you? Besides, no i has been declared at this point.
getline(fich1,l1);
I assume l1 is the string you declared earlier as ligne1. (Since that happened inside the else, ligne1 is no longer in scope, but I'll let that one pass since you obviously intended the while to be inside the else block.)
Anyway, this can't work because both your ifstream and your string are constant, i.e. cannot be changed. This does not make sense, and thus getline() was not defined for const parameters.
else if(j == i)
Since you didn't close the brace of the if statement above, this is a syntax error as well. Again, proper indenting discipline would have made this immediately obvious.
{ fich1>>s;
I very much doubt there exists an operator>>() for const ifstream, so I am not surprised you get an error here.
z=(float)s;
You're trying to cast (C style, too...) a stringstream object to a float number? What do you expect the result might be? It will definitely not be the 3.14 or whatever you've written into test.txt...
}
}
Lost track of your braces. This code is FUBAR, I didn't even check if it makes sense semantically once all the errors are fixed, and I suspect you're pulling some elaborate troll prank here. If that isn't the case, I suggest you take another good look at whatever textbook you're using to learn C++, because you got a good many things very wrong.
Purely style-related advice: fich1, ligne1... don't use localized (non-English) identifiers. It just adds another problem when communicating about your code. (And this is coming from a non-native English speaker.)

Binary to decimal conversion(positional notation method) using for_each loop c++

I'm using positional notation method convert binary to decimal and its different i guess nobody has tried it yet i guess, and in this I'm using for_each loop
Here are some steps:
store binary as string
-take out one digit at a time from string using for_each loop and do operation.
int main(void)
{
string input;
cout << "Enter string of binary digits " ;
cin >> input ;
for_each(input.begin(), input.end(),bitodec);
cout << "Decimal equivalent is " << u << endl;
system("PAUSE");
}
here is full code
There is logical error.
I am not sure what exactly it is you are asking, since you did not state a question. I presume, however, that you would like to know why you get the compiler error:
prog.cpp:13:48: error: ‘for_each’ was not declared in this scope
for_each(input.begin(), input.end(),bitodec);
(It would have been nice if this was included in the question)
You get this error because you try to use std::for_each, which was not declared in your program. It is defined in the "algorithm" header, so to fix this problem, you would have to add
#include <algorithm>
somewhere at the beginning of your file.
There are, however, some other problems with the complete code(which should really have been included in your question), for instance: Your global variable u is never modified, because you declare a new, temporary one in bitodec's if block and modify this one.
So, as Joachim Pileborg mentioned in the comments, it would be much easier(and apparently less error prone), to simply use std::stoi.
I hope this helps ;-)
As the documentation of std::bitset says:
Bitsets can be manipulated by standard logic operators and converted to and from strings and integers.
So using std::bitset is a simple way to achieve your goal. For example:
std::string bit_string = "110010";
std::bitset<8> b3(bit_string); // [0,0,1,1,0,0,1,0]
std::bitset<8> b4(bit_string, 2); // [0,0,0,0,0,0,1,0]
std::bitset<8> b5(bit_string, 2, 3); // [0,0,0,0,0,0,0,1]