Search Function returns wrong results - c++11

I have made a function for my program that reads from a text file, adds content to a vector and then search in that vector. The Problem is that even if the file is empty it shows that it found something, on the other side if i change return value to 0 it does not give results at all!
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
vector<string> contacts;
//This function returns at what index the name is found
int searchContact(string contactToSearch)
{
string entry;
ifstream input;
input.open("contacts.txt");
while (input.good())
{
while (getline(input, entry))
{
contacts.push_back(entry);
}
input.close();
}
for(int i = 0; i < contacts.size(); i++)
{
if(contactToSearch == contacts[i])
{
//Found => Returning index rest of program can see index
return i;
}
}
return 1;
}

I have just refactored your code a little. Further improvements are possible, but to begin with
1) You dont need a while for input.good()
2) You were trying to return 0 and 1 which are indeed valid positions where the string could have been present in the vector
All these aside, I still think your code might not properly populated the array The reasons for this maybe :- case sensitive comparison, reading incorrect file, binary file.. etc..
Here is a refactored code that you could use
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
void readContacts(const string &fileName inputFileName, vector<string> &contacts){
string entry;
ifstream input;
input.open(inputFileName);
if (input.good())
{
while (getline(input, entry))
contacts.push_back(entry);
input.close();
}
}
int searchContact(const string &contactToSearch, vector<string> &contacts)
{
for (int i = 0; i < contacts.size(); i++)
{
if (contactToSearch == contacts[i])
return i;
}
return -1;
}
int main(){
vector<string> contacts;
// This needs to be filled in with the contact name u want to search
string contactToSearch;
readContacts("contacts.txt", contacts);
int index = searchContact(contactToSearch, contacts)
if (index != -1)
cout << "Found Contact " << contactToSearch" at location " << index << endl;
else
cout << "Could Not find contact " << contactToSearch << endl;
}

Related

Get item closest to a value in a std::vector of doubles

Is there an elegant way in C++ 11 to get the item from a std::vector of doubles which is closest to a certain value?
Code:
#include <iostream>
#include <vector>
double GetClosest(const std::vector<double>& vec, double value) {
// How to get the item closest to "value" from the items in vec. Vec is assumed to be sorted.
}
int main() {
std::vector<double> my_doubles_vec;
my_doubles_vec.push_back(101480.76915103197);
my_doubles_vec.push_back(101480.85708367825);
my_doubles_vec.push_back(101480.93293087184);
my_doubles_vec.push_back(101481.0027936101);
my_doubles_vec.push_back(101481.5625);
my_doubles_vec.push_back(101481.5626);
std::cout.precision(17);
std::cout << GetClosest(my_doubles_vec, 101480.76915103201) << std::endl; // Should output "101480.76915103197"
std::cout << GetClosest(my_doubles_vec, 101480.93293086279) << std::endl; // Should output "101480.93293087184"
std::cout << GetClosest(my_doubles_vec, 101481.5625) << std::endl; // Should output "101481.5625"
return 0;
}
Since its a std::vector of doubles, I think precision comes into play? Or can the logic be made in such a way that one doesn't need to bother about precision?
You could use std::partition_point, std::lower_bound or std::upper_bound on the sorted range.
Example:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if(vec.empty()) throw std::runtime_error("no elements");
// partition_point is the most generic of the three:
auto it = std::partition_point(vec.begin(), vec.end(), [value](double v) {
return v < value;
});
// or auto it = std::lower_bound(vec.begin(), vec.end(), value);
// or auto it = std::upper_bound(vec.begin(), vec.end(), value);
if(it == vec.end()) --it; // value larger than the largest in the vector
else if( it != vec.begin()) { // value not less than first
// check which one of the two around the partition point that is closest
if(std::abs(*std::prev(it) - value) < std::abs(*it - value)) --it;
}
return *it;
}
Since the vector is sorted, you could try something like this:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if (vec.empty()) throw std::invalid_argument("vector cant be empty");
if (vec.size() == 1) return vec[0];
auto iter = std::find_if(vec.begin(), vec.end(),
[=](double d){ return d >= value; }
);
if (iter == vec.begin()) return vec.front();
if (iter == vec.end()) return vec.back();
if (std::abs(value - *(iter-1)) < std::abs(value - *iter)) --iter;
return *iter;
}

Using recursion inside a called constructor

Don't know where to begin on how to use recursion within a called constructor.
recursion.cpp
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
#include "MinilabRecursion.h"
MinilabRecursion::puzzleRecurse(int n)
{
int recurse(n) // <--- Don't know what to do here
{ //error: expected ',' or ';' before '{' token
if( n == 0 )
{
return 1;
}
if( n >= 1 )
{
return recurse(n - 1) + 4 * n;
}
}
} //error: expected '}' at end of input
driver.cpp
#include <iostream>
#include <string>
using namespace std;
#include "MinilabRecursion.h"
{
cout << "puzzleRecurse(1) returns: " << MinilabRecursion::puzzleRecurse(1) << endl;
cout << "puzzleRecurse(7) returns: " << MinilabRecursion::puzzleRecurse(7) << endl;
cin.get();
return 0;
}
recursion.h
#ifndef MINILABRECURSION_H
#define MINILABRECURSION_H
#include <iostream>
#include <string>
using namespace std;
class MinilabRecursion
{
public:
static int puzzleFormula(int n);
static int puzzleLoop(int n);
static int puzzleRecurse(int n);
};
#endif
The if statements within recursion.cpp should give me the desired outcome, but I do not know how to use recursion in this context.
I'm not sure I can make sense out of the code you posted. It seems you want to do the following, but are confused about some of the C++ basics:
int MinilabRecursion::puzzleRecurse(int n)
{
if (n == 0) {
return 1;
}
return puzzleRecurse(n - 1) + 4 * n;
}

The problem is i need the input of the string to accept a blank line

The program is supposed to receive a string, that can have blank lines, blank spaces, and break lines. So the problem is i can't use get line, because i don't know how many break lines the user will use.
I tried making a do while but it didn't work, the program stops working.
It was a do while, that would receive an char and using pushback insert in the string while the char was different to EOF. I don't know how else to do it, or why this do while doesn't work.
This code is using get line witch doesn't accept a break line.
'''''
#ifndef INDICE_H
#define INDICE_H
#include <cstddef>
struct Indice{
std::size_t f;
double p;
};
#endif
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <map>
#include "Indice.hpp"
int main()
{
std::string str;
std::getline(std::cin, str);
// Count the number of occurrences for each word
std::string word;
std::istringstream iss(str);
std::map<std::string,Indice> occurrences;
while (iss >> word) ++occurrences[word].f;
//Calculate the percentual each word
int total = 0.0;
for (std::map<std::string,Indice>::iterator it = occurrences.begin();
it != occurrences.end(); ++it)
{
total += it->second.f;
}
for (std::map<std::string,Indice>::iterator it = occurrences.begin();
it != occurrences.end(); ++it)
{
it->second.p = (static_cast<double>(it->second.f))/total;
}
// Print the results
for (std::map<std::string,Indice>::iterator it = occurrences.begin();
it != occurrences.end(); ++it)
{
if(it->first.size()>2)
std::cout << it->first << " " << it->second.f << " "<< std::fixed << std::setprecision(2) << it->second.p << std::endl;
}
return 0;
}
''''
Two possible solutions:
#include <iostream>
#include <string>
int main(){
std::string line;
while(std::cin >> line){
//Variable line contains your input.
}
//Rest of your code
return 0;
}
Or:
#include <iostream>
#include <string>
int main(){
std::string line;
while(std::getline(std::cin, line)){
if (line.empty()){
break;
}
//Variable line contains your input.
}
//Rest of your code
return 0;
}

Reversing a string using only iostream, fstream, string and vector

I just started working with C++ about a week ago so I don't know much about the language. I am working on creating a program that inputs a text file and then reverses all of the lines.
So an input of:
"abc"
"123"
Would be:
"cba"
"321"
I can figure out how to input the lines from the file, but I am having trouble with my reverse function. I have tried to just print out each individual character as a string using substring, starting from length - 1 and ending at 0. But this does not seem to be working. When I run the program, I get these errors that I don't understand.. Any ideas as to what is going wrong?
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void reverse(string input) {
for((int x=input.length()-1); x=0; x--)
cout << input.substr(x);
}
cout << endl;
}
int main()
{
string line;
ifstream myFile;
myFile.open("reverse_input.txt");
while(getline(myFile, line)) {
reverse(line);
}
return 0;
}
There are couple syntax errors in your code that the compiler was complaining
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void reverse(string input) {
for( unsigned int x= (input.length()-1); x>=0; x--) { //Missing {, extra (), >= insteadof = 0
cout << input[x] << flush;
}
cout << endl;
}
int main()
{
string line;
ifstream myFile;
myFile.open("reverse_input.txt");
while(getline(myFile, line)) {
reverse(line);
}
return 0;
}

OpenCV: Load multiple images

I am updating some older OpenCV code that was written in (I guess) an OpenCV 1.1 manner (i.e. using IplImages).
What I want to accomplish right now is to simply load a series of images (passed as command line arguments) as Mats. This is part of a larger task. The first code sample below is the old code's image loading method. It loads 5 images from the command line and displays them in sequence, pausing for a key hit after each, then exits.
The second code sample is my updated version using Mat. It works fine so far, but is this the best way to do this? I've used an array of Mats. Should I use an array of pointers to Mats instead? And is there a way to do this such that the number of images is determined at run time from argc and does not need to be set ahead of time with IMAGE_NUM.
Basically, I'd like to be able to pass any number (within reason) of images as command line arguments, and have them loaded into some convenient array or other similar storage for later reference.
Thanks.
Old code:
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std;
using namespace cv;
// the number of input images
#define IMAGE_NUM 5
int main(int argc, char **argv)
{
uchar **imgdata;
IplImage **img;
int index = 0;
char *img_file[IMAGE_NUM];
cout << "Loading files" << endl;
while(++index < argc)
if (index <= IMAGE_NUM)
img_file[index-1] = argv[index];
// malloc memory for images
img = (IplImage **)malloc(IMAGE_NUM * sizeof(IplImage *)); // Allocates memory to store just an IplImage pointer for each image loaded
imgdata = (uchar **)malloc(IMAGE_NUM * sizeof(uchar *));
// load images. Note: cvLoadImage actually allocates the memory for the images
for (index = 0; index < IMAGE_NUM; index++) {
img[index] = cvLoadImage(img_file[index], 1);
if (!img[index]->imageData){
cout << "Image data not loaded properly" << endl;
return -1;
}
imgdata[index] = (uchar *)img[index]->imageData;
}
for (index = 0; index < IMAGE_NUM; index++){
imshow("myWin", img[index]);
waitKey(0);
}
cvDestroyWindow("myWin");
cvReleaseImage(img);
return 0;
}
New code:
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <time.h>
using namespace std;
using namespace cv;
// the number of input images
#define IMAGE_NUM 5
int main(int argc, char **argv)
{
Mat img[IMAGE_NUM];
int index = 0;
for (index = 0; index < IMAGE_NUM; index++) {
img[index] = imread(argv[index+1]);
if (!img[index].data){
cout << "Image data not loaded properly" << endl;
cin.get();
return -1;
}
}
for (index = 0; index < IMAGE_NUM; index++) {
imshow("myWin", img[index]);
waitKey(0);
}
cvDestroyWindow("myWin");
return 0;
}
you can use a vector instead of an array:
for example
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <time.h>
#include <vector>
using namespace std;
using namespace cv;
int main(int argc, char **argv)
{
vector<Mat> img;
//Mat img[IMAGE_NUM];
int index = 0;
for (index = 0; index < IMAGE_NUM; index++) {
//img[index] = imread(argv[index+1]);
img.push_back(imread(argy[index+1]));
if (!img[index].data){
cout << "Image data not loaded properly" << endl;
cin.get();
return -1;
}
}
vector<Mat>::iterator it;
for (it = img.begin(); it != img.end() ; it++) {
imshow("myWin", (*it));
waitKey(0);
}
cvDestroyWindow("myWin");
return 0;
}
It took me a while to get back around to this, but what I've ended up doing is as follows, which is probably functionally the same as Gootik's suggestion. This has worked well for me. Notice that for functions that take Mat& (i.e. a single cv::Mat), you can just de-ref the array of Mats and pass that, which is a notation I'm more comfortable with after doing a lot of image processing work in Matlab.
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std;
using namespace cv;
int main(int argc, char **argv)
{
if (argc==1){
cout << "No images to load!" << endl;
cin.get();
return 0;
}
int index = 0;
int image_num = argc-1;
Mat *img = new Mat[image_num]; // allocates table on heap instead of stack
// Load the images from command line:
for (index = 0; index < image_num; index++) {
img[index] = imread(argv[index+1]);
if (!img[index].data){
cout << "Image data not loaded properly" << endl;
cin.get();
return -1;
}
}
for (index = 0; index < image_num; index++) {
imshow("myWin", img[index]);
waitKey(0);
}
cvDestroyWindow("myWin");
delete [] img; // notice the [] when deleting an array.
return 0;
}

Resources