This program will compile but not run. Other programs run - c++

So, I'm using dev-C++. The compiler works fine, a simple hello world program works along with about a dozen other simple programs. This is a work-in-progress of something I'm working on for class.
For me this compiles but it never runs. What's wrong with it?
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
void getNames(vector<string> &vectorName, int &last, string temp);
int main() {
vector<string> names;
string tmp;
int last = 0;
getNames(names, last, tmp);
for(int j = 0; j < last; j++) {
cout << names.at(j) << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
void getNames(vector<string> vectorName, int &last, string temp) {
while (true) {
cout << "Enter a name (quit to stop): ";
cin >> temp;
if (temp == "quit") break;
vectorName.push_back(temp);
last = vectorName.size();
}
}

The program should fail to link because it can't find the definition for:
void getNames(vector<string> &vectorName, int &last, string temp);
That's because you're missing the & in your definition:
void getNames(vector<string> vectorName, int &last, string temp){
^^^^^^^^^^^
Add in the & and it should compile and run just fine.

First your getNames declaration and implementation signatures are not exactly the same.
void getNames(vector<string> &vectorName, int &last, string temp){
void getNames(vector<string> vectorName, int &last, string temp){

Related

Remove duplicates from the string in CPP

I wrote the following code for removing the duplicates from a given string i.e. if ARRUN is the input then the output will be ARUN.
#include <bits/stdc++.h>
using namespace std;
char* removeDuplicates(string &s,int n){
char arr[n];
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
arr[index++] = s[i];
exists[s[i]]++;
}
}
return arr;
}
//driver code
int main(){
string str;
cin >> str;
cout<<removeDuplicates(str,str.length())<<endl;
return 0;
}
The code produces no output at all, however, it works fine if I use char arr[] instead of string class.
You can't use char arr[n] without being n constant or constexpr.
You don't need map. set is sufficient.
Note that map and set remove duplicates already, then you can check if any element is inserted or not to get your new string in the same order of the first, as follows
#include<string>
#include<iostream>
#include<unordered_set>
std::string removeDuplicates(const std::string &s){
std::string arr;
std::unordered_set<char> exists;
for(const auto&el:s)
if(exists.insert(el).second) arr+=el;
return arr;
}
//driver code
int main(){
std::string str;
std::cin >> str;
std::cout<<removeDuplicates(str)<<std::endl;
return 0;
}
std::string support removing elements.
#include <iostream>
#include <string>
std::string removeDuplicates(std::string str) {
for (int i = 0; i < str.size(); i++) {
while (true) {
int j = str.find_last_of(str[i]);
if (i < j) {
str.erase(j, 1);
} else {
break;
}
}
}
return str;
}
int main() {
std::cout << removeDuplicates("ARRUN");
return 0;
}
If a function declaration looks the following way
char* removeDuplicates(string &s,int n);
then it means that the passed object itself will be changed in the function. Otherwise the parameter shall have the qualifier const.
Also it is unclear why the function has return type char *. It looks like the declaration of the function is contradictive.
The second parameter of the function shall have at least the type size_t or that is better std::string::size_type. The type int can not accomodate all values of the type std::string::size_type.
The function could be declared without the second parameter.
A straightforward approach without using intermediate containers that requires dynamic memory allocation can look the following way
#include <iostream>
#include <string>
std::string & removeDuplicate( std::string &s )
{
const char *p = s.c_str();
std::string::size_type pos = 0;
for ( std::string::size_type i = 0, n = s.size(); i < n; i++ )
{
std::string::size_type j = 0;
while ( j < pos && s[i] != s[j] ) j++;
if ( j == pos )
{
if ( i != pos ) s[pos] = s[i];
++pos;
}
}
return s.erase( pos );
}
int main()
{
std::string s( "H e l l o" );
std::cout << "\"" << s <<"\"\n";
std::cout << "\"" << removeDuplicate( s ) <<"\"\n";
return 0;
}
The program output is
"H e l l o"
"H elo"
#Arun Suryan, You pointed out correctly. But you can do it without using vector by using global char array.
Also don't forget to append the newline at the end!
Have a look at the following code:
#include<string>
#include<iostream>
#include<unordered_map>
char* removeDuplicates(std::string &s,int n){
std::unordered_map<char,int> exists;
char* arr = (char*)(malloc(n*sizeof(char)));
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
arr[index++] = s[i];
exists[s[i]]++;
}
}
arr[index] = '\n';
return arr;
}
//driver code
int main(){
std::string str;
std::cin >> str;
std::cout<<removeDuplicates(str,str.length())<<std::endl;
return 0;
}
This might be a bit advanced for newcomers to C++ but another solution makes use of the erase-remove idiom:
std::string removeDuplicates(const std::string& s) {
std::string result = s;
std::unordered_set<char> seen;
result.erase(std::remove_if(result.begin(), result.end(), [&seen](char c)
{
if (seen.find(c) != seen.end())
return true;
seen.insert(c);
return false;
}),
result.end());
return result;
}
It basically uses a set to store characters that have been seen, shuffles the characters to be removed down to the tail (using std::remove_if) and erases the tail from the string.
Working version here.
This works too, a single line solution with an inbuild function.
cout<<str.erase(std::unique(str.begin(), str.end()), str.end());
Simple Answer
#include<bits/stdc++.h>
using namespace std;
string removeduplicate(string key){
set<char>s;
string ans="";
for(int i=0;i<key.size();++i){
if(s.find(key[i])==s.end()){
s.insert(key[i]);
ans.push_back(key[i]);
}
}
return ans;
}
int main()
{
string key="";
cout<<"enter the key:";
cin>>key;
string ans1=removeduplicate(key);
cout<<ans1;
return 0;
}
So, after doing a bit of reading on the Internet I realized that I was trying to return a pointer to the local array in the removeDuplicates() function.
This is what works fine
#include <bits/stdc++.h>
using namespace std;
void removeDuplicates(string &s,int n){
vector<char> vec;
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
vec.push_back(s[i]);
exists[s[i]]++;
}
}
for(auto x: vec)
cout << x;
}
//driver code
int main(){
string str;
cin >> str;
removeDuplicates(str,str.length());
return 0;
}
PS: We can make the return type of function to vector as well.

C++ Creating Lottery Guessing Program

Okay so the project is to create a lottery number composed of 10 random positive integers and the user is suppose to guess it until the user guesses the correct number. All of my code looks good but when I run the program and enter in a number it gives me this MSVS Runtime Library error? I dont even know what it means as I am fairly new to programming. Help would be very appreciated!
Main.cpp
#include <iostream>
#include <cmath>
#include <ctime>
#include "Lottery.h"
using namespace std;
int main() {
const int size = 9; //declare variables
int win[size];
int g;
srand(time(NULL));
assign(win, size);
draw(win, size);
g = entry();
if (check(win,size,g) == true) {
cout << "Congradulations! You have won the lottery!" << endl;
}
else {
cout << "Try again!" << endl;
}
printOut(g);
}
Lottery.cpp
#include <iostream>
#include <cmath>
#include "Lottery.h"
using namespace std;
int entry() {
int guess;
cout << "Enter a number from 0 to 99." << endl;
cin >> guess;
return guess;
}
void assign(int w[], int s) {
for (int i = 0; i < s; i++) {
w[s] = -1;
}
}
bool check(int w[], int s, int g) {
for (int i = 0; i < s; i++) {
if (g == w[i]) {
return true;
}
}
return false;
}
void draw(int w[], int s) {
for (int i = 0; i < s; i++) {
int tmp = rand() % 100;
if (check(w, s, tmp)) {
i--;
}
else
w[i] = tmp;
}
}
void printOut(int g) {
cout << "Numbers you have chosen:" << " " << g << endl;
}
Lottery.h
#ifndef LOTTERY_INCLUDED
#define LOTTERY_INCLUDED
void assign(int[], int);
bool check(int[], int, int);
void draw(int[], int);
int entry();
void printOut(int);
#endif //LOTTERY
Debugging tutorials are available elsewhere. But if something bad happens, don't panic and look for instructions.
First, your runtime error:
This has a link "Break and open exception settings" link or a "Break" button. Break which will take you to the end of main if you click it.
The details say we did something bad near win.
Look at this:
void assign(int w[], int s) {
for (int i = 0; i < s; i++) {
w[s] = -1; //<------Oh oops!
}
}
We know the length of the array is s i.e. 9, and are using w[s] where we clearly meant w[i].
The extra details in the error are telling you a possible place to look.

undefined reference to CLASS::function()

So when I try to simply compile my code using "g++ Asg5.cpp" I receive the following error
/tmp/cczhpSGO.o: In function 'main':
Asg5.cpp:(.text+0x2fb): undefined reference to 'BinomialTree::insert(int)'
collect2: ld returned 1 exit status
If anyone's wondering why I'm not using a makefile, my professor simply wants to type g++ <.cpp with main()> to compile..
Anyway here's my code I really appreciate the assistance!
Asg5.cpp
#include "BinomialTree.h"
#include "BinomialNode.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <stdio.h>
using namespace std;
int main(int argc, char* argv[])
{
//input handling
if(argc != 2)
{
cout << "Incorrect Usage. \n Example: ./a.out <filename>" << endl;
exit(1);
}
BinomialTree *tree = new BinomialTree();
char *buffer;
char *token;
//read file into buffer.**************************************
string input;
ifstream file;
file.open(argv[1]);
if(file.is_open())
{
string str;
while(file.good())
{
getline(file,str);
input += " " + str;
}
}
else{
cout << "File not found"<< endl;
return 1;
}
file.close();
int buf;
stringstream ss(input);
vector<int> tokens;
while(ss >> buf)
{
tokens.push_back(buf);
}
int i = 0;
for(i = 0; i < tokens.size(); i++)
tree->insert(tokens[i]);
//end file reading *******************************************
delete tree;
}
BinomialNode.h
#ifndef _BINOMIALNODE_H_
#define _BINOMIALNODE_H_
#include "BinomialTree.h"
class BinomialNode
{
public:
int k;
BinomialNode *children[20];
int data;
BinomialNode();
};
#endif
BinomialNode.cpp
class BinomialNode
{
BinomialNode::BinomialNode(int n)
{
this->k = 0;
this->data = n;
}
}
BinomialTree.h
#ifndef _MULTIMAP_H_
#define _MULTIMAP_H_
#include "BinomialNode.h"
class BinomialTree
{
public:
BinomialNode * BQ[20];
void insert(int n);
void merge(BinomialNode *queue, BinomialNode *in, int k);
void print(BinomialNode *root, int tab);
};
#endif
BinomialTree.cpp
#include "BinomialNode.h"
#include "BinomialTree.h"
#include <iostream>
#include <cstdlib>
class BinomialTree
{
void BinomialTree::insert(int n)
{
BinomialNode *in = new BinomialNode(n);
if(BQ[0] == NULL)
{
BQ[0] = in;
return;
}
else
merge(BQ[0], in, 0);
}
void BinomialTree::merge(BinomialNode *queue, BinomialNode *in, int k)
{
if(queue == NULL)
{
BQ[k] = in;
return;
}
if(n == NULL)
{
BQ[k] = queue;
return;
}
if(queue->data > in->data)
{
merge(in, queue);
return;
}
queue->k++;
BinomialNode* temp[queue->k];
int i;
for(i = 0; i < queue->k-1; i++)
temp[i] = queue->children[i];
temp[queue->k-1] = in;
for(i = 0; i < queue->k; i++)
queue->children[i] = temp[i];
if(BQ[queue->k] == NULL)
{
BQ[queue->k] = queue;
return;
}
else
merge(queue, BQ[queue->k]);
}
void BinomialTree::print(BinomialNode *root, int tab)
{
if(root == NULL)
return;
int i;
for(i = 0; i < tab*5; i++) cout << " ";
cout << root->data << endl;
for(i = 0; i < root->k; i++) print(root->children[i], tab+1);
}
}
You cpp files shouldn't have Class in them. They should look more like:
BinomialNode.cpp
#include "BinomialNode.h"
BinomialNode::BinomialNode(int n) :
k(0)
{
data = n;
}
And of course the corollary for the much longer BinomialTree.cpp. Also, you should compile it with something like:
g++ BinomialTree.cpp BinomialNode.cpp Asg5.cpp -o asg5
Also you're going to run into a lot of other problems with you code. For instance:
BinomialNode * BQ[20];
I don't see BQ being initialized anywhere, which means you're pretty much guaranteed a seg fault if you were to run this. You need to initialize this or allocate it. Seeing lines like:
if(BQ[0] == NULL)
Makes me think you really wanted:
BinomialNode BQ[20];
Though you would still need to initialize it to all NULLs since you aren't guaranteed that will be full of NULLs when you run the program. Also, this is recursive and infinite and can't possibly work (in BinomialNode.h):
BinomialNode *children[20];
There are likely more issues with this code, but that wasn't your question, so I'll stop now!
You need to compile all the .cpp files into one program. You're not using BinomialTree.cpp anywhere right now. If your project requires that you simply type g++ Asg5.cpp then you need to #include your .cpp files or move their contents to your .h files. But the normal solution would be to build all the .cpp files together, not just the one containing main().

Quicksort Throws Stack Overflow error

Okay, so my entire program is shown below. For some reason, when the partition function is called, it is throwing a stack overflow error. I have poured over the code and searched for help. You fine programmers are my last hope. Everything else works fine, or at least as well as it needs to. I'd appreciate it if you could look at the Quicksort and the partition functions for me and see if you can figure out where I messed up.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <time.h>
#include <stdio.h>
#include <dos.h>
using namespace std;
vector<int> DataIn(ifstream&);
void quickSort(int, int, vector<int>&, int);
int partition(vector<int>& list, int start, int end)
{
int pivot = list[start];
int index = start;
for (int i = start + 1; i < end; i++)
{
if (list[i] <= pivot)
{
swap(list[index], list[i]);
}
}
index++;
if (index != end)
{
swap(list[index], list[start]);
}
return index;
}
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int repeat = 0;
int fileCount = 1;
while (repeat == 0)
{
int loadFail = NULL;
cout << "\nWhat is the file name: ";
string fileName;
cin >> fileName;
ifstream fileIn(fileName);
do
{
if (fileIn.fail())
{
loadFail = 1;
cout << "\nUnable to open file. Please try again:";
cout << "\nWhat is the file name: ";
cin >> fileName;
ifstream fileIn(fileName);
if (fileIn.good())
{
loadFail = 0;
}
}
else
{
loadFail = 0;
}
} while (loadFail == 1);
vector<int> fileData;
fileData = DataIn(fileIn);
int fileLength = fileData.size();
void quickTime = quickSort(0, fileLength - 1, fileData, fileCount);
return 0;
};
vector<int> DataIn(ifstream& read)
{
vector<int> data;
int dataLine;
while (!read.eof())
{
read >> dataLine;
read.ignore();
data.push_back(dataLine);
}
return data;
}
void quickSort(int begin, int end, vector<int>& list, int fileNum)
{
int mid = 0;
if (end > begin)
{
mid = partition(list, begin, end);
quickSort(begin, mid, list, fileNum);
quickSort(mid + 1, end, list, fileNum);
}
return elapsed_time;
}
You have a few major issues in your posted code.
You are trying to return a value in void function (quickSort). Also I don't see where you declared that variable.
You are declaring a type void variable, which is wrong. A void function return void, that means that it doesn't return anything.
You have a missing bracket at the end of the main() function.
Your while loop will never stop, because repeat is always equal with 0.
In your quick sort function, in the first recursive call there should be mid-1
Your partitioning function logic is wrong
Also filenum variable is not used anywhere.
Here is a modified version of your code, that does work.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <time.h>
#include <stdio.h>
#include <dos.h>
using namespace std;
vector<int> DataIn(ifstream&);
void quickSort(int, int, vector<int>&);
int partition(vector<int>& arr, int left, int right)
{
int pivot = arr[left];
while (left != right)
{
if (arr[left] > arr[right])
{
swap(arr[left], arr[right]);
}
if (pivot == arr[left])
right--;
else
left++;
}
return left;
}
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int repeat = 0;
int fileCount = 1;
int loadFail = NULL;
cout << "\nWhat is the file name: ";
string fileName;
cin >> fileName;
ifstream fileIn(fileName);
do
{
if (fileIn.fail())
{
loadFail = 1;
cout << "\nUnable to open file. Please try again:";
cout << "\nWhat is the file name: ";
cin >> fileName;
ifstream fileIn(fileName);
if (fileIn.good())
{
loadFail = 0;
}
}
else
{
loadFail = 0;
}
} while (loadFail == 1);
vector<int> fileData;
fileData = DataIn(fileIn);
int fileLength = fileData.size();
quickSort(0, fileLength - 1, fileData);
return 0;
}
vector<int> DataIn(ifstream& read)
{
vector<int> data;
int dataLine;
while (!read.eof())
{
read >> dataLine;
read.ignore();
data.push_back(dataLine);
}
return data;
}
void quickSort(int begin, int end, vector<int>& list)
{
int mid = 0;
if (end > begin)
{
mid = partition(list, begin, end);
quickSort(begin, mid-1, list);
quickSort(mid + 1, end, list);
}
}

How to alphabetically sort strings?

I have been trying to use this c++ program to sort 5 names alphabetically:
#include <iostream>
#include <cstring>
#include <conio.h>
using namespace std;
int main()
{
char names[5][100];
int x,y,z;
char exchange[100];
cout << "Enter five names...\n";
for(x=1;x<=5;x++)
{
cout << x << ". ";
cin >> names[x-1];
}
getch();
for(x=0;x<=5-2;x++)
{
for(y=0;y<=5-2;y++)
{
for(z=0;z<=99;z++)
{
if(int(names[y][z])>int(names[y+1][z]))
{
strcpy(exchange,names[y]);
strcpy(names[y],names[y+1]);
strcpy(names[y+1],exchange);
break;
}
}
}
}
for(x=0;x<=5-1;x++)
cout << names[x];
return 0;
}
If I enter Earl, Don, Chris, Bill, and Andy respectively, I get this:
AndyEarlDonChrisBill
Could someone please tell me whats wrong with my program?
You could use std::set or std::multiset (if you will allow repeated items) of strings, and it will keep the items sorted automatically (you could even change the sorting criteria if you want).
#include <iostream>
#include <set>
#include <algorithm>
void print(const std::string& item)
{
std::cout << item << std::endl;
}
int main()
{
std::set<std::string> sortedItems;
for(int i = 1; i <= 5; ++i)
{
std::string name;
std::cout << i << ". ";
std::cin >> name;
sortedItems.insert(name);
}
std::for_each(sortedItems.begin(), sortedItems.end(), &print);
return 0;
}
input:
Gerardo
Carlos
Kamilo
Angel
Bosco
output:
Angel
Bosco
Carlos
Gerardo
Kamilo
You can use the sort function:
#include <algorithm>
#include <vector>
using namespace std;
...
vector<string> s;
sort(s.begin(),s.end());
You are using too much unnecessary loops. Try this simple and efficient one. You need to just swap when a string is alphabetically latter than other string.
Input
5
Ashadullah
Shawon
Shakib
Aaaakash
Ideone
Output
Aaaakash
Ashadullah
Ideone
Shakib
Shawon
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s[200],x[200],ct,dt;
int i,j,n;
cin>>n;
for(i=0;i<n;i++)
{
cin>>s[i];
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(s[i]>s[j])
{
ct=s[i];
s[i]=s[j];
s[j]=ct;
}
}
}
cout<<"Sorted Name in Dictionary Order"<<endl;
for(i=0;i<n;i++)
{
cout<<s[i]<<endl;
}
return 0;
}
Your code implements a single-pass of bubble sort. Essentially missing the 'repeat until no changes are made to the array' loop around the outside.
The code does not take care when the names are already in order. Add the following
else if(int(names[y][z])<int(names[y+1][z]))
break;
To the if statement.
Putting this here in case someone needs a different solution.
/* sorting example */
#include <iostream>
using namespace std;
bool isSwap( string str1, string str2, int i)
{
if(str1[i] > str2[i])
return true;
if(str1[i] == str2[i])
return isSwap(str1,str2,i+1);
return false;
}
int main()
{
string str[7] = {"you","your","must","mike", "jack", "jesus","god"};
int strlen = 7;
string temp;
int i = 0;
int j = 0;
bool changed = false;
while(i < strlen-1)
{
changed = false;
j = i+1;
while(j < strlen)
{
if(isSwap(str[i],str[j],0))
{
temp = str[i];
str[i] = str[j];
str[j] = temp;
changed = true;
}
j++;
}
if(changed)
i = 0;
else
i++;
}
for(i = 0; i < strlen; i++)
cout << str[i] << endl;
return 0;
}