Converting std::vector to char* - c++

I am a c++ student working on a project to receive and encode a message with a simple cipher. To do so, the program accepts each word as a string, converts the string into a vector of characters, and then modifies each character before storing it in a file. In the line that returns the encoded message to the main function, I get this error message: < cannot convert std::vector<char, std::allocator<char> >' tochar*' for argument 1' tochar* cipher(char*, int)' . Despite this error, the program will run, however, it will simply stop after a word has been entered and end the program. This is the code I am using:
// Cipher.cpp
// This program accepts a message and encodes it
// Written by Will Grindle
#include<iostream.h>
#include<string.h>
#include<iomanip.h>
#include<math.h>
#include<fstream.h>
#include<vector.h>
using namespace std;
string get_message(); // function prototypes
char* cipher(char broken[], int length);
int main()
{
int index, length; // declare index for vectors
string message; // declare string
ofstream outfile; // declare filestream
outfile.open("MESSAGE.DAT", ios::in); // create file and open it
message = get_message(); // use function to retrieve data
length = message.length(); // find length of message
// declare vector for breaking the strings down
vector <char> broken(message.begin(), message.end());
vector <char> encoded(50); // declare vector for encoded message
encoded[index] = cipher(broken, length); // initialize encoded to new message
for(index = 0; index <= length - 1; index++)// loop for displaying values
{
cout << encoded[index] << endl;
}
if(outfile) // if there is no error with the file
{
for(index = 0; index <= length - 1; index++) // loop for writing encoded
{ // message to file
outfile << encoded[index] << endl;
cout << "Data written to file." << endl;
}
}
else
{
cout << "Error opening file." << endl;
}
outfile.close(); // close file
system("pause");
return 0;
}
string get_message()
{
string entry; // declare string
cout << "Please enter the word to be entered." << endl; // request entry
cin >> entry; // user enters word
system ("pause");
return entry;
}
char* cipher(char broken[], int length)
{
char index; // declare index
if( broken[index] < 123 && broken[index] > 96 ) // if characters are lowercase,
{ // make them uppercase
broken = broken - 32;
}
for(index = 0; index <= length - 1; index ++)
{
broken[index] = broken[index] * (2/3);
broken[index] = broken[index] - 12;
broken[index] = broken[index] ^ 2;
}
cout << "Message encoded." << endl;
system ("pause");
return(broken);
}
I am open to any suggestions on how to make this work. Thank you!

In C++, a vector isn't actually an array of chars, so you can't pass it into a function expecting a char array. You have a few options here.
First, I'd recommend updating your code so that the cipher function takes in as a parameter either a vector or a std::string. These objects are safer than raw arrays because they know their sizes and can do reallocations if you need them to grow.
Second, you could change the call to cipher to pass in a pointer to the vector's underlying array, like this:
cipher(broken.data(), broken.size());
I think this is a less elegant and more error-prone solution, but you're welcome to use it if you'd like.

Your code looks more like C...
Maybe start learning the basic data types and data structures first.
Then make sure you understand the usage of the vector template
This seems good as well: Differences between C and C++
It also points out some things about style and what you could do, but shouldn't do.
And of course this Programmers.StackExChange Post: What are the fundamental differences between C and C++?
Try to use a modern C++ IDE such as CodeBlocks, Eclipse, Netbeans, ...;
This will help you to prevent some faults at the beginning.

Related

What is a better way to get C++ get text data into a program rather than using fstream

this is a very challenging question as I'm not sure how to ask it correctly.
I wrote a program that will read in the same text data on load every time. The text data is a list of words in the dictionary and the program solves anagram type puzzles (like Jumble, Boggle, Scrabble, etc). This text data never changes. Currently I use to read a text file which MUST be present in the same folder as the .exe that is built. This assumes the user would not just go in and erase, edit, or otherwise corrupt the text file or something really within the realm of possibility for a user to do. Not only that but locking a file and reading it are very noticeably slow operations.
Most of what the program does is convert the .txt file into an abstract data type (ADT) which sorts the word into a 'signature' then builds a set of words that have the same signature. These sets are stored in a structure (called map here) that is a key:value type data structure where the key is the signature. Anyway that info is irrelevant to the question just sufficient to say that on load I need to build my ADT in memory. I'm looking for a more sophisticated way than text files.
Since I'm new at programming there is probably a much better way. I just don't know how to even ask the question since I don't know what is available out there.
I understand databases, but then again it seems like that relies on an external file. I have seen posts which talk about storing data in a .h file but they always want to build a character array (char[i]), which would require converting this data into my ADT and that seems again like a waste of time when the program is loading. (why bother converting it into a char array just to read it back to the ADT?)
/*
* Project: myJumble
* Created by CS106 C++ Assignment Wizard 0.1
*
* Name: Brad Beall
* Section: Life
* This code will solve the jumble puzzles in the newspaper.
*/
#include <fstream>
#include <iostream>
#include "simpio.h"
#include "map.h"
#include "set.h"
#include "genlib.h"
//This function swaps two characters.
void Swap(char &ch1, char &ch2)
{
char tmp = ch1;
ch1 = ch2;
ch2 = tmp;
}
//This function sorts all the chars in a word in alphabetical order
string SortWord(string inWord)
{
inWord = ConvertToLowerCase(inWord);
//these two for loops will sort the string alphabetically
// - idea is starting from the front, find the 'smallest' character in the string.
// (where a is 'smaller' than b)
// then move that smallest character to the front of the string
// now move to the next character and again look for the smallest character.
// Example: for "peach", first move the 'a' to the front to form "apech", then move 'c' to form "acpeh"...
for (int i = 0; i < inWord.length(); i++) {
int minIndex = i;
for (int j = i+1; j < inWord.length(); j++)
{
if (inWord[j] < inWord[minIndex])
{
// looking for the 'smallest' character
minIndex = j;
}
}
Swap(inWord[i], inWord[minIndex]);
}
return inWord;
}
void BuildDictionary(Map<Set<string> > &kDict, ifstream &in)
{
string nextWord = "";
while(true)
{
//read in the next word from the dictionary
in >> nextWord;
if (in.fail()) break;
//sort letters alphabetically using SortWord, use that as the key
// and then add that key:value pair to the set.
kDict[SortWord(nextWord)].add(nextWord);
}
}
//this function prints a set
void PrintSet(Set<string> &inputSet)
{
Set<string>::Iterator it = inputSet.iterator();
while (it.hasNext())
{
cout << it.next() << endl;
}
}
int main ()
{
////debug the function: string SortWord(string inWord)
//cout << "Enter a word to sort" << endl;
//string tempString = GetLine();
//tempString = SortWord(tempString);
//cout << tempString;
//building the dictionary may take some time.
cout << "Loading the dictionary. This may take some time." << endl;
//read in the text file with all dictionary words
ifstream in;
in.open("enable1.txt");
//call the member function that will create our data structure
//this will be a MAP:
// - key: the alphabetized letters from a word, or the word's "signature"
// - value: a Vector of words with the matching signature
Map<Set<string> > keyedDictionary;
BuildDictionary(keyedDictionary, in);
while(true)
{
//prompt user for a word to solve
cout << "Enter a jumbled word to solve." << endl;
cout << "Type '0' to exit." << endl << endl;
string solveWord = GetLine();
if(solveWord == "0"){
break;
}
//sort the word into a signature key
solveWord = SortWord(solveWord);
//call the PrintSet(Set) member function to print the set of solutions for this signature key
PrintSet(keyedDictionary[solveWord]);
}
return 0;
}

char array/string is empty when sent to function

I have a function that at the moment doesn't do anything because the char array I send as parameter has no value. I can write out the data before the function and get the expected output but if I write out in the function nothing come out even if It's the first thing I do.
I first write out the string and then convert it to a char array. I have also tried with just a normal string as parameter with the same result.
std::cout << block;
block = this->removeNullCharacters(block.c_str());
Output of the first cout is : "0/"
The output of the function below is nothing. Nothing at all is shown up in the console.
std::string FileSystem::removeNullCharacters(const char * input){
std::string out = "";
for(int i = 0; i < 512; ++i){
std::cout << i << ": " << input[i];
/*if(input[i] == '\0'){
return out;
}
else{
out += input[i];
}*/
}
return out;
}
Not clear at all what you try to achieve or, in other words, you question is not complete.
input is a pointer to char and points to the first element of an array of chars of size 512.
out is an empty string and returned at the end of the function.
block is schizophren, a pointer to char and a std::string at the same time i guess. You need to fix this one really.
Try this. I think you want to pass a pointer to a sequence of chars to the function and concatenate each char to the string until the end of the sequence (which is terminated by \0). Forget about the size completely and simply use the null termination as a loop condition.
std::string FileSystem::removeNullCharacters(const char * input){
std::string out = "";
for(int i = 0; input[i] != '\0'; ++i){
std::cout << i << ": " << input[i];
out += input[i];
}
return out;
}
But you gotta make sure you pass in an array of chars or a valid pointer to char (which is the beginning of a sequence of chars and the last element is \0).

Getting "terminating with uncaught exception of type std::length_error: vector" error C++

I'm writing a program to help solve crossword puzzles. So I'm getting a word from a text list of all words in the english language, making each one a vector of chars, and comparing that vector to a vector of whatever starting letters I have. It runs fine and gives me good output, but every time I'm getting an error "libc++abi.dylib: terminating with uncaught exception of type std::length_error: vector".
Here's my code:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
#include <iterator>
using namespace std;
string getLetters() {
string word; // Get user letter, put in variable word
cout << "Enter a set of letters" << endl;
cin >> word;
return word;
}
int getLengthOfWord() {
int length; // Get length of word
cout << "Enter the number of letters in the word" << endl;
cin >> length;
return length;
}
// Change strings to vectors of chars
vector<char> stringToVector(string word) {
std::vector<char> v(word.begin(), word.end());
return v;
}
bool compareVectors(vector<char> userWord, vector<char> listWord, int length) {
if (listWord.size() != length) // Make sure the word from the list is the right length
{
return false;
}
int counter = 0; // Counter
for (int i = 0; i < userWord.size(); i++) { // Iterating through the two words
for (int j = 0; j < listWord.size(); j++) {
if (listWord[j] == userWord[i]) { // If the letters match
listWord.erase(listWord.begin() - 1 + j); // Erase the letter from the word
counter++; // Increase counter
break; // Break out of for loop
}
}
}
if (counter == userWord.size()) { // If there were as many matches as letters in user set
return true;
}
else {
return false;
}
}
int main() {
string example; // variable to put words
ifstream wordList; // New ifstream object
wordList.open("/Users/alexray/Dropbox/C++ Practice/WordJumbleSolver/wordsEn.txt"); //open word list
int length = getLengthOfWord(); // Get user input
string word = getLetters();
vector<char> vector1(stringToVector(word));
while (wordList.is_open()) {
getline(wordList, example); // Get word, put it in example variable
vector<char> vector2(stringToVector(example)); // Make word from list a vector
vector2.erase(vector2.end() - 1); // Erase escape character from end of word
if(compareVectors(vector1, vector2, length)) { // compare the vectors
cout << example << endl;
}
}
wordList.close(); // Close stream
return 0;
}
From googling around, I thought that it was a matter of my vector wasn't initially large enough to handle some of the words, but doing vector.reserve(some_number) before assigning a value to the vector didn't help anything. Also, I couldn't imagine that a vector would have any problems with <20 elements.
Thanks for the help! (I'm new to C++ so if there's something I should obviously be doing differently, let me know).
Edit: The file I'm working with is the wordsEn.txt file from this website: http://www-01.sil.org/linguistics/wordlists/english/
In my case it was a mismatch between C++ standard on two vcxproj projects.
I've simply aligned both projects to the same C++ standard (17) and it worked.
project ➤ Properties ➤ C/C++ ➤ Language ➤ C++ Language Standard
One issue I see is that you are not erasing the character you claim you want to erase:
listWord.erase(listWord.begin() - 1 + j);
This does not erase the jth character in the sequence.
The easiest example of this failing is if j == 0 at the start of the loop, and the first character matches.
Just simply do this instead:
listWord.erase(listWord.begin() + j);
I was looking in the wrong place the whole time. I looked at the number of words/lines in the file (109582) and changed the
while (wordList.is_open()) {
getline(wordList, example); // Get word, put it in example variable
vector<char> vector2(stringToVector(example)); // Make word from list a vector
vector2.erase(vector2.end() - 1); // Erase escape character from end of word
if(compareVectors(vector1, vector2, length)) { // compare the vectors
cout << example << endl;
}
counter++;
}
to
while (counter < 109582) {
getline(wordList, example); // Get word, put it in example variable
vector<char> vector2(stringToVector(example)); // Make word from list a vector
vector2.erase(vector2.end() - 1); // Erase escape character from end of word
if(compareVectors(vector1, vector2, length)) { // compare the vectors
cout << example << endl;
}
counter++;
}
It seems I was getting some sort of overflow error by trying to read in more lines than were available in the file.

passing array as parameter to a function

this script is supposed to output array values that were inputted by the user into array "store." I am trying to store all the char array values into string temp. I get the error on line 12: "[Error] invalid conversion from 'char*' to 'char' [-fpermissive]." Would appreciate any help!
Edit: so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so? The cmd only correctly couts the first string but after the space, it messes up.
#include <iostream>
#include <cstdlib>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50];
cout << "enter text: " << endl;
cin >> store;
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Using input from all answerers I finally got the fixed code:
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50] = {0};
cout << "enter text: " << endl;
cin.getline(store, 50);
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max && store[i]!=0)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Thanks everyone. i learned a lot!!!
When you get an input using "cin" your input automatically ends with 0 (NULL).
You just need to add one little piece of code to your while statement.
instead of this :
while (i < max)
use this :
while (i < max && store[i]!=0)
Now it will stop when the input string is finished and won't print any garbage existed in the array beforehand.
To show that cin does add terminating zero, i initialized the array to 46, and put a breakpoint after the cin
so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so?
Not sure what you mean by jumbled up. But since you did not tell us what you typed its hard to know it looks like it worked to me:
> ./a.out
enter text:
Plop
Plop�ȏU�
Notice that since my input is only 4 characters long. This means that a lot of the characters in the array still have undefined (ie random values). This is why I am seeing junk. To get past this initialize the array to have all 0 values.
char store[50] = {0};
Even bettern use a C++ object than handles longer strings.
std::string store;
std::getline(std::cin, store);
Note: passing arrays to functions by value is not a good idea. On the other end they have decayed to pointers and thus do not act like arrays anymore (they act like pointers whose semantics are similar but not identical).
If you must pass an array pass it by reference. But I would use a C++ container and pass that by reference (it is much safer than using C constructs). Have a look at std::string
The declaration of the function is wrong. Should be void coutArray(char *, int);
Look at the Implicit Conversion rules to understand what the compiler can do and what it cannot to do for you.
The issue with your program was that you were probably entering in less characters than the maximum size of the buffer. Then when you passed the maximum size as the parameter to coutArray, you assigned unfilled slots in the char array to temp. These unfilled slots could contain anything, as you have not filled them up to that point.
Your program is still correct, but what would be better would be to use read so that the number of bytes you specify is the minimum number of bytes that can be entered:
std::cin.read(store, 50);
Even better solution would be to use std::string:
std::string store;
std::cin >> store;
// or for the entire line
std::getline(std::cin, store);
It also follows that your coutArray should be changed to:
void coutArray(std::string);
// ...
void coutArray(std::string str)
{
std::cout << str << std::endl;
}
Look at this way
template<typename T, size_t N>
void MyMethod(T (&myArray)[N])
{
//N is number of elements, myArray is the array
std::cout<<"array elements number = "<<N<<endl;
//put your code
string temp;
temp.resize(N+1);//this is for performance not to copy it each time you use += operator
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
//call it like this
char arr[] = "hello world";
MyMethod(arr);

I am trying to return a Character Array but, I'm only getting the first letter returned

I'm working on a small little thing here for school. After hours of researching, and a ton of errors and logic reworking I've almost completed my little program here.
I'm trying to take user input, store it into the string, get a character array from the string ( dont ask why, I just have to put this into a character array ), then get the reversed order of the phrase that the user entered. Here is my code:
#include "stdafx.h"
#include <iostream>
#include <String>
#include <cstring>
using namespace std;
using namespace System;
#pragma hdrstop
char* getCharArray(string);
string reversePhrase( int, char* );
void main(void)
{
string sPhrase = "";
int sSize = 0;
string sReversed = "";
char* cPhrase = NULL;
cout << "Welcome to the You Type It & We'll Reverse it! [Version 1.0] " << endl;
cout << "This program will reverse your phrase, and count how many characters are in it!" << endl;
cout << "To begin just enter a phrase." << endl;
cout << "Enter a phrase: ";
getline( cin, sPhrase);
sSize = sPhrase.length();
cout << endl;
cPhrase = getCharArray(sPhrase);
sReversed = reversePhrase( sSize, cPhrase );
cout << sReversed;
system("pause");
}
string reversePhrase(int size , char* cPhrase)
{
string sReversed = "";
int place = size;
for ( int i = 0; i < size ; i ++ )
{
sReversed.append(1, cPhrase[place]);
cout << "Current string: " << sReversed << endl;
cout << "Current character: " << cPhrase[place] << endl;
place--;
}
return sReversed;
}
char* getCharArray(string sPhrase)
{
int size = 1;
size = sPhrase.length();
char* cArray = NULL;
cArray = new char[size];
for (int i = 0 ; i < size ; i++)
{
cArray[size] = sPhrase.at(i);
}
return cArray;
}
When I type in "ownage" into the program, this is what I get returned:
It is almost like my Character Array is getting garbage collected before it can use all of the characters. This is probably an easy fix but, I just don't see how I can get around this one.
Try rewriting getCharArray like this
char* getCharArray(string sPhrase)
{
int size = 1;
size = sPhrase.length();
char* cArray = NULL;
cArray = new char[size+1]; // NOTE
for (int i = 0 ; i < size ; i++)
{
cArray[i] = sPhrase.at(i); // NOTE
}
}
cArray[size]=0; // NOTE
return cArray;
}
Note that the assignment in the loop now uses the index variable. Also, you need to allocate one extra char in the array to set the null terminator for the string and then you need to set it at the end.
You'll also need to think about deallocating the array at some point
The bug is in this line:
cArray[size] = sPhrase.at(i);
That size should be your loop index.
You should probably look at using std::string more, and not poke around with character arrays when there's no need to.
Why use a char array at all? It's not only useless – it complicates the code substantially (the usage of your function is more difficult, and you've forgotten to free the memory allocated by new!). Why not just have the following function:
string reverse(string const& input);
(Passing the argument by const reference instead of by value saves you a copy!)
In fact, implementing the function only takes a single line using the features of the string class (one of its constructors takes two iterators):
string reverse(string const& input) {
return string(input.rbegin(), input.rend());
}
reversePhrase is also not correct. Try something like this:
string reversePhrase(int size , char* cPhrase)
{
string sReversed = "";
sReversed.resize(size);
int place = size - 1;
for ( int i = 0; i < size ; i ++ )
{
sReversed [i] = cPhrase[place];
cout << "Current string: " << sReversed << endl;
cout << "Current character: " << cPhrase[place] << endl;
place--;
}
return sReversed;
}
First, start the array with -1. After that, use a for loop with -1 and increment inside the loop. Then, you can get the first element of the array.