I am writing a program that will receive a text file, read in a list of names from that file, sort those names in alphabetical order, and then print the sorted list back out.
This originally was a project for my "Intro to Programming" class that was to use arrays, but I'm trying to retool it to work with vectors instead, allowing me to use a file of any length instead of a rigid array length.
But Intellisense is giving me an error:
No suitable conversion function from "std::vector<std::string, std::allocator<std::string>>" to "std::vector<std::string, std::allocator<std::string>>*" exists
Any time that I try to pass the filename to a function (ex at displayArray(names, nameQty), I get the error with names). I'm having a hard time googling how to pass a vector to a function, so I think that's where my problem is. The full code is pasted below:
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
using namespace std;
int readFromFile(string[], string);
void displayArray(vector<string>[], int);
void alphaSort(vector<string>[], int);
void swap(string&, string&);
int main() {
//Declare variables
string fileName;
vector<string>names(1);
int nameQty;
//Prompt for file name
cout << "Please enter the name of the file to read names from: " << endl;
cin >> fileName;
//Call function to open file and read names into a vector array. Function will return the number of names in file
nameQty = readFromFile(names, fileName);
//Display unsorted names
cout << "Unsorted names:" << endl;
displayArray(names, nameQty);
//Sort names into alphabetical order
alphaSort(names, nameQty);
//Display sorted names
cout << "Sorted names:" << endl;
displayArray(names, nameQty);
//More to come after this; program isn't done yet!
}
/*
* Function to read a list from a text file into an array.
* The array starts at size 1, then increments by 1 for each subsequent iteration
* The array then deletes the final element when there is nothing more to read
* (since the last element will be uninitialized)
*/
int readFromFile(vector<string> array, string fileName) {
ifstream inputFile;
inputFile.open(fileName);
if (!inputFile) {
cout << "Invalid file name. Please restart program and try again."
<< endl;
system("pause");
exit(EXIT_FAILURE);
}
else {
int index = 0;
while (inputFile) {
cin >> array[index];
array.push_back;
index++;
}
array.pop_back;
inputFile.close();
return (index + 1);
}
}
//Function to display list of items in array
void displayArray(vector<string> array[], int quantity) {
for (int i = 0; i < quantity; i++)
cout << array[i] << endl;
}
//Selection sort function puts array elements in alphabetical order
void alphaSort(vector<string> names[], int qty) {
for (int j = 0; j < qty - 1; j++) {
for (int i = j + 1; i < qty; i++) {
if (names[j] > names[i]) {
swap(names[j], names[i]);
}
}
}
}
//Function to swap elements a and b in array
void swap(string &a, string &b) {
string temp = a;
a = b;
b = temp;
}
Please don't worry about my using system("pause") and using namespace std. I'm aware that's poor practice, but it's what we've been asked to do in class.
You want:
void displayArray(vector<string>& array, int quantity)
or in this case even better:
void displayArray(const vector<string>& array, int quantity)
In your code it seems you are trying to pass an array of vectors (which is not that straightforward in C++ and boils down to a pointer to a vector in this case). To avoid copying you should use a reference.
You may also be interested to read about move semantics.
Also, as noted in the comments, you may also want to fix readFromFile:
int readFromFile(vector<string>& array, string fileName)
By changing it to a reference the function will modify caller's vector, instead of creating and modifying a local copy.
Related
#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
using namespace std;
void getinput (string &first,string &second);
void lengthcheck (string first, string second);
//int anagramcheck (string word);
int* lettercounter (string input);
int main()
{
std::string a;
std::string b;
getinput(a,b);
lengthcheck (a,b);
lettercounter(a);
lettercounter(b);
int* one = lettercounter(a);
int* two = lettercounter(b);
if (one == two)
cout << "You Have Entered An Anagram" << endl;
else
cout << "You Have Not Entered An Anagram" << endl;
}
void getinput (string &first, string &second) {
cout << "Enter First Input: ";
getline(cin, first, '\n');
cout << "Enter Second Input: ";
getline(cin, second, '\n');
cout << "You Entered " << first << " and " << second <<endl;
}
void lengthcheck(string first, string second){
int lengtha = first.length();
int lengthb = second.length();
if ((lengthb > 60) || (lengtha > 60)) {
cout << "Input Is Invalid" << endl;
} else if (lengtha !=lengthb) {
cout << "Input is not an anagram" << endl;
} else {
cout << "Input is Valid" << endl;
}
}
int* lettercounter(string input)
{
static int freq[26] = {0};
int length = input.length();
for (int i=0; i<26; i++) {
freq[i]=0;
}
for (int i=0; i <length; i++) {
if(input[i]>='a' && input[i]<='z')
{
freq[input[i] - 97]++;
}
else if(input[i]>='A' && input[i]<='Z')
{
freq[input[i] - 65]++;
}
}
for(int i=0; i<26; i++) {
/* If current character exists in given string */
if(freq[i] != 0)
{
printf("'%c' = %d\n", (i + 97), freq[i]);
}
return freq;
}
}
I am having trouble returning the array named freq from the user definied function called lettercount. Can someone give me a hint? I need the lettercount to return an array. I need to call the function lettercount twice so i can compare the results of each array to determine if the two inputs are anagrams. I am not sure if the function is returning an actual value to the main.
First of all, freq shouldn't be static. By making it static, you would be accessing the same array everytime. For what you want to do, you don't want to always access the same memory.
In second place, you cannot just return a pointer to memory that has not being allocated dynamically or that isn't static. When you get out of scope (i.e. you return from the function lettercounter back to main), the memory that was occupied by the array will be freed. So, you would be returning a pointer to memory that is no longer reserved, resulting in undefined behavior.
If you really need to work with raw pointers, then each time you enter lettercounter, you would need to allocate memory for the array dynamically like this: int * freq = new int[26];. This will reserve memory for an array of size 26. Then, when you return freq, the memory will still be allocated. However, don't forget that the memory allocated with new doesn't delete itself. You have to clean your mess. In this case, at the end of main you would call delete[] one; and delete[] two;.
int* lettercounter(string input)
{
int * freq = new int[26];
.
.
.
return freq;
}
int main()
{
.
.
int* one = lettercounter(a);
int* two = lettercounter(b);
.
.
delete[] one;
delete[] two;
}
In any case, I'd recommend you to learn to use smart pointers and about standard containers (like a vector). These operations would be much simpler.
I have coded thus far and I am not sure how to sort using the 2-dimensional array. Basically, one function is for sorting an array of strings, another function is for swapping two strings. Any help would be appreciated. (Also I am not allowed to use c++ 11 :/)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void input_name(string&);
void sort_names(string&);
void repeat_pro(int&);
void sortArray(string, int);
int main() {
string b_list[100][2];
string name;
int choice;
int count=0;
cout << "Welcome to the Business Sorting Program!" << endl;
do{
input_name(name);
b_list[count][1] = name;
count++;
repeat_pro(choice);
cout<<"\n \n Your Businesses are:"<<endl;
for(int j=0; j<count; j++){
cout<<b_list[j][1]<<endl;
}
cout << "\n\n";
}while(choice == 0);
cout << "Thanks for using this program"<<endl;
return 0;
}
void input_name(string &name){
cout << "Enter in the name of the business: ";
getline(cin, name);
}
void sort_names(string &name){
}
void repeat_pro(int &choice){
cout << "Do you want to enter in more names: ";
string answ;
cin>>answ;
cin.ignore(1000,'\n');
if (answ == "YES" || answ == "Y" || answ == "yes" || answ == "y"){
choice = 0;
}
else {
choice = 1;
}
}
it is not clear to me from the description what problem the program really tried to solve. I'm assuming it's kind of like a two column spreadsheet, the second column is the name entered by the user(but what is in the first column?).
assume you need to keep the array in sorted order as the data goes in, just do a binary search (you can do a linear search for small dataset like 100 entries).
// we don't have lambda before C++11
struct comparator {
bool operator () (const string (&x)[2], const string (&y)[2]) const {
return x[1] < y[1];
}
};
//... omitted
string data[100][2];
int count = 0;
while (count < 100) {
// no rvalue, move, rvo, etc. before C++11
string name;
input_name(name);
// no type deduction and lambda
string (*position)[2] =
std::lower_bound(&data[0], &data[count], name, comparator());
int index = position - &data[0];
// simulate an vector::insert operation, but for our array
for (int i = count; i > index; --i) {
// before we had move in C++, we would do swap with an empty element.
// in this case, the entry at data[count] is default constructed
std::swap(data[i][1], data[i-1][1]);
}
data[index][1] = name;
}
//... omitted
of course we can use a typedef to make it cleaner, but that's left to you.
I need to make a program with three functions.
The main function should call the second function passing it the array as the first argument and the number of elements in the array as the second argument.
The second function is passed in an array and the number of elements in the array. The function should get 8 names from the user and return the number of names read back to main. Use the return statement to do this.
After the array is filled by the second function, main should then call a third function passing it the array as the first argument and the value returned by the second function as the second argument.
The third function should display the names from the array on separate lines on the computer screen. The third function is passed in an array as the first parameter. The second parameter is the number of elements in the array to be displayed.
The main function has an array of 10 elements. The second function is passed that array of 10 elements but only reads in 8 elements. The number read in by the second function is returned back to main. Main then passes the array and the value returned back from the second function to the third function.
My code up to this point is:
#include <iostream>
#include <string>
using namespace std;
int main()
{
// get the names and store them in the array
int const arraySize(10);
int names = 8;
string array[arraySize];
// send to second function
recievenames(array, arraySize);
// send to third function
displaynames(array, 8);
return 0;
}
int recievenames(string array[], int arraySize)
{
int names = 0;
// Get names.
for (int count = 0; count < 8; count++)
{
cout << "Enter name " << (count + 1) << " of 8: ";
cin >> array[count];
if (count < 8)
{
names++;
}
}
// Display amount of names entered.
cout << names << " received.";
}
void displaynames(string array[], int names)
{
// Display names entered in array.
for (int count = 0; count < names; count++)
{
cout << array[count] << endl;
}
}
For some reason it isn't working can someone tell me why?
you have to do a foward declartion of the function prototypes recievenames() and displaynames() and place them before main() . Then you can define and embody the functions after main.
#include <iostream>
#include <string>
using namespace std;
// declare function prototypes
int recievenames(string array[], int arraySize);
void displaynames(string array[], int names);
int main()
{
// get the names and store them in the array
int const arraySize(10);
int names = 8;
string array[arraySize];
// send to second function
recievenames(array, arraySize);
// send to third function
displaynames(array, 8);
return 0;
}
//define functions
int recievenames(string array[], int arraySize)
{
int names = 0;
// Get names.
for (int count = 0; count < 8; count++)
{
cout << "Enter name " << (count + 1) << " of 8: ";
cin >> array[count];
if (count < 8)
{
names++;
}
return 0;
}
// Display amount of names entered.
cout << names << " received.";
}
void displaynames(string array[], int names)
{
// Display names entered in array.
for (int count = 0; count < names; count++)
{
cout << array[count] << endl;
}
}
Here is the assignment:
Write a program that reads in a text file one word at a time. Store a word into a dynamically created array when it is first encountered. Create a paralle integer array to hold a count of the number of times that each particular word appears in the text file. If the word appears in the text file multiple times, do not add it into your dynamic array, but make sure to increment the corresponding word frequency counter in the parallel integer array. Remove any trailing punctuation from all words before doing any comparisons.
Create and use the following text file containing a quote from Bill Cosby to test your program.
I don't know the key to success, but the key to failure is trying to please everybody.
At the end of your program, generate a report that prints the contents of your two arrays in a format similar to the following:
Word Frequency Analysis
I 1
don't 1
know 1
the 2
key 2
...
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int readInFile (string tempArray [], string file, int arraySize);
int main()
{
ifstream inputFile;
string *readInArray = 0,
*compareArray = 0,
filename,
word;
int wordCount = 0;
int encountered = 0;
int j = 0,
*wordFrequency = 0;
cout << "Enter the filename you wish to read in: ";
getline(cin, filename);
inputFile.open(filename.c_str());
if (inputFile)
{
while (inputFile >> word)
{
wordCount++;
}
inputFile.close();
readInArray = new string[wordCount];
readInFile(readInArray, filename, wordCount);
}
else
{
cout << "Could not open file, ending program";
return 0;
}
compareArray = new string[wordCount];
wordFrequency = new int[wordCount];
for (int count = 0; count < wordCount; count++)
wordFrequency[count] = 0;
for(int i = 0; i < wordCount; ++i)
{
j = 0;
encountered = 0;
do
{
if (readInArray[i] == compareArray[j])
encountered = 1;
++j;
} while (j < wordCount);
if (encountered == 0)
{
compareArray[i]=readInArray[i];
wordFrequency[i] += 1;
}
}
for(int k=0; k < wordCount; ++k)
{
cout << "\n" << compareArray[k] << " ";
}
for(int l=0; l < wordCount; ++l)
{
cout << "\n" << wordFrequency[l] << " ";
}
return 0;
}
int readInFile (string tempArray [], string file, int arraySize)
{
ifstream inputFile;
inputFile.open(file.c_str());
if (inputFile)
{
cout << "\nHere is the text file:\n\n";
for(int i=0; i < arraySize; ++i)
{
inputFile >> tempArray[i];
cout << tempArray[i] << " ";
}
inputFile.close();
}
}
Here is my question:
How do you store a word into a dynamically created array when it is first encountered? As you can see from my code made a string array with some of the elements empty. I believe it is suppose to be done using pointers.
Also how do I get rid of the punctuation in the string array? Should it be converted to a c-string first? But then how would I compare the words without converting back to a string array?
Here is a link to a java program that does something similar:
http://math.hws.edu/eck/cs124/javanotes3/c10/ex-10-1-answer.html
Thank you for any help you can offer!!
As to the first part of your question, you are not using a dynamically created array. You are using a regular array. C++ provides implementations of dymnamic arrays, like the vector class http://www.cplusplus.com/reference/vector/vector/
As to the second part of your question, I see no reason to convert it to a c string. The string class in c++ provides functionality for removing and searching for characters. http://www.cplusplus.com/reference/string/string/
The string::erase function can be used to erase punctuation characters found with string::find.
Note: There are other ways of doing this assignment that may be easier (like having an array of structs containing a string and an int, or using a map) but that may defeat the purpose of the assignment.
I am trying to figure out what I am doing wrong here and its five in the morning and I have to turn this in today at 9 in the morning, so this is my last hope to come to you guys.
This program has to allow a user to enter 5 ints, 7 floats and 5 chars, which go into arrays which have to be coded via Function Templates. The numeric data than has to be bubble sorted and averaged. This has to be printed out Then I have to save the arrays to a .dat file and retrieve the data from the file and once again output it.
Errors: The Average is not recorded properly somehow so you get a nasty random memory output.
Only the int values are being saved to the text file, and I don't even know how to retrieve properly and print the retrieved values again.
Updated Code with fixed calc function
#include<iostream>
#include<iomanip>
#include<fstream>
using namespace std;
//Load data to array from Keyboard.
template <class T>
void load(T *a,const int n)
{
for(int i=0;i<n;i++)
cin>>a[i];
}
//Calc and Print the Average for a numeric array.
template <class T>
void calc(T *a,const int n,float *avg)
{
float b=0;
for (int i=1;i<n;i++)
{
b+=a[i];
}
*avg=b/n;
cout<<"The Average is: "<<*avg<<endl;
//Does not work. Prints out a random block of memory.
//Tried a couple things and still get he same bug.
}
//Sort the data array in ascending order.
template <class T>
void sort(T *a,const int n)
{
float t;
for(int i=0;i<n-1;i++)
for(int j=0;j<n-1;j++)
if (a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
//Save the array data to a text file.
template <class T>
void get(T *a,const int n)
{
ofstream outfile("C:\array.dat", ios::out);
for(int i=0;i<n;i++)
outfile << a[i]<< endl;
outfile.close();
//Only saves the first array (The ints)
}
//Retrieve the array data from the text file.
template <class T>
void save(T *a,const int n)
{
ifstream infile("C:\array.dat", ios::in);
for(int i=0;i<n;i++)
{
infile>>a[i];
}
infile.close();
}
/*Output should include the average for each of the two numeric arrays
along with all three arrays being printed out in ascending order twice,
once before the text file is saved and once after the array is retrieved
from the text file*/
int main()
{
const int n1=5,n2=7,n3=5;
int a[n1];
float b[n2];
char c[n3];
float avg[3];
int i;
cout<<"Enter 5 integers"<<endl;
load(a,n1);
sort(a,n1);
calc(a,n1,avg);
cout<<"Enter 7 floats"<<endl;
load(b,n2);
sort(b,n2);
calc(b,n2,avg+1);
cout<<"Enter 5 strings"<<endl;
load(c,n3);
cin.ignore(20, '\n');
sort(c,n3);
cout << endl;
cout<<"Output:"<<endl;
cout<<"The Integer array:" << endl;
for (i = 0; i < n1; i++)
cout << a[i] << " ";
cout << endl;
cout<<"The Float array:" << endl;
for (i = 0; i < n2; i++)
cout << b[i] << " ";
cout << endl;
cout<<"The String array:" << endl;
for (i = 0; i < n3; i++)
cout << c[i] << " ";
cout << endl;
save(a,n1);
get(a,n1);
save(b,n2);
get(b,n2);
save(c,n3);
get(c,n3);
//Need to print the now returned values here.
cout << endl;
//cin.get();
system("PAUSE");
return 0;
}
Sorry if half of this doesn't make sense. I am really tired.
For the average:
template <class T>
void calc(T *a,const int n,float *avg)
{
float b=0;
for (int i=1;i<n;i++)
{
b+=a[i];
}
avg[n]=b/n;
cout<<"The Average is: "<<avg[4]<<endl;
//Does not work. Prints out a random block of memory.
//Tried a couple things and still get he same bug.
}
you don't need an array of averages, you just want one average.
agv[n] = b / n; //assigns to the the n'th elemement of an array called avg.
try this instead:
*avg = b/n
And for printing it out, just '*avg' also.
When you call calc, try:
float avg1;
calc(b,n4,&avg1);
When you see & and *, read them as the following:
& address of
* contents of address
you only need three averages, one for the 5 ints, one for the 7 floats and one for the 5 chars.
float avg[4]; // should be: float avg[3];
You seem to be passing the wrong parameters to each of the calc functions. When you call calc for the ints, use:
calc(a,n1,avg);
for floats:
calc(b,n2,avg+1);
for chars:
calc(c,n3,avg+2);
n4=2; is not relevant to anything, you can delete n4.
When you open the file, you will need to specify ios:app which appends to the existing file. Without that, every time you write to the file anything that existed in it before will be thrown away.
ios::out | ios::app
So, first write just use ios::out, after that include ios::app