I have the task to write a function char * stringReplace(const char * str, const char * what, const char * with) which replaces "what" with "with" on a new string with the correct length. So Inside the function I created dynamic array, which the function returns. But my question is how can I delete it after, as If i try to delete it in the main function, after i use it, it says it's undefined. Aren't dynamic arrays without a scope or I'm wrong?
Here's my code:
#include <iostream>
#include <string.h>
using namespace std;
bool areTheSame(const char * str, const char * what, unsigned p)
{
return areEqual;
}
unsigned howManyTimes(const char * str, const char * what)
{
}
char * stringReplace(const char * str, const char * what, const char * with)
{
}
int main()
{
char str[1000];
char what[1000];
char with[1000];
cout << "Enter your string\n";
cin.getline(str, 1000);
cout << "\nEnter \"what\" you want to replace\n";
cin.getline(what, 1000);
if (strlen(str) < strlen(what))
{
cout << "\"What\" contains more characters than the string!\n";
return 0;
}
cout << "\nEnter with what you want to replace it\n";
cin.getline(with, 1000);
cout << "\nYour string with replaced words looks like\n";
cout << stringReplace(str, what, with) << endl;
return 0;
}
P.S I deleted parts of the code as I found the answer I wanted and there is still time for the task, and I'm not sure I'm allowed to post my code publicly
You have to delete it in order to avoid memory leak. You can do something like this:
int main()
{
char str[1000];
char what[1000];
char with[1000];
char *replaced;
cout << "Enter your string\n";
cin.getline(str, 1000);
cout << "\nEnter \"what\" you want to replace\n";
cin.getline(what, 1000);
if (strlen(str) < strlen(what))
{
cout << "\"What\" contains more characters than the string!\n";
return 0;
}
cout << "\nEnter with what you want to replace it\n";
cin.getline(with, 1000);
cout << "\nYour string with replaced words looks like\n";
replaced = stringReplace(str, what, with);
cout << replaced << endl;
delete [] replaced;
return 0;
}
However note that this isn't the best pratice to split allocation/deallocation responsibility.
Related
// Function displays course information
// instructor defaults to Staff
// enrollment defualts to 30
// main() demonstrates function can be called three ways
#include<iostream>
using namespace std;
int main()
{
void displayCourseInfo(char, char* = "Staff", int = 30);
displayCourseInfo("ENG101");
displayCourseInfo("PSY151", "Bossert");
displayCourseInfo("CIS200", "Edwards", 24);
return 0;
}
void displayCourseInfo(char course, char* instructor, int enrollment)
{ cout << course << " taught by " << instructor <<
" enrollment " << enrollment << endl;
}
When I try to run this code I get
this error message. It says that I cannot convert *const char to char.
Thank you for your time and help.
String literals in C++ (opposite to C) have types of constant character arrays. For example the string literal "Staff" has the type const char [6].
Used in expressions array designators with rare exceptions are converted to pointers to their first elements. So the string literal "Staff" used as an argument is converted to a pointer of the type const char *.
The first parameter of the function displayCourseInfo is declared as having the type char while you are trying to pass a string literal as an argument.
A valid program can look the following way
// Function displays course information
// instructor defaults to Staff
// enrollment defualts to 30
// main() demonstrates function can be called three ways
#include<iostream>
using namespace std;
int main()
{
void displayCourseInfo( const char *, const char * = "Staff", int = 30 );
displayCourseInfo("ENG101");
displayCourseInfo("PSY151", "Bossert");
displayCourseInfo("CIS200", "Edwards", 24);
return 0;
}
void displayCourseInfo( const char *course, const char *instructor, int enrollment)
{
cout << course << " taught by " << instructor
<< " enrollment " << enrollment << endl;
}
Its output is
ENG101 taught by Staff enrollment 30
PSY151 taught by Bossert enrollment 30
CIS200 taught by Edwards enrollment 24
This happens because "test in quotes" is by default const char*.
Values with const in their declaration cannot be changed.
You can't pass const variable to function that takes non-const parameters.
You could just make function's parameters const:
#include<iostream>
using namespace std;
void displayCourseInfo(const char *);
void displayCourseInfo(const char *, const char *);
void displayCourseInfo(const char *, const char *, const int);
int main() {
displayCourseInfo("ENG101");
displayCourseInfo("PSY151", "Bossert");
displayCourseInfo("CIS200", "Edwards", 24);
return 0;
}
void displayCourseInfo(const char *course, const char *instructor) {
cout << course << " taught by " << instructor <<
" enrollment " << 30 << endl;
}
void displayCourseInfo(const char *course) {
cout << course << " taught by " << "Staff" <<
" enrollment " << 30 << endl;
}
void displayCourseInfo(const char *course, const char *instructor, const int enrollment) {
cout << course << " taught by " << instructor <<
" enrollment " << enrollment << endl;
}
I have these two set of char arrays:
char t1[]={'1','2','\0','\0'};
char t2[]={'1','2','3','4'};
I want to write a function to convert them to string, but the string size for t1 should be 2 and for t2 should be 4.
string convert(char * data)
{
return string(data);
}
Does a good job for t1, but crashes on t2 (t2 is not null terminated).
string convert(char * data)
{
return string(data,data+4);
}
Does a good job for t2, but the size of generate string for t1 is 4 and not 2.
What is the best way to write a simple and fast function to do this correctly?
You can take an array by reference. If you're only interested in arrays of size 4:
std::string convert(char const(&data)[4])
{
return std::string(data, std::find(data, data + 4, '\0'));
}
If you want something more general, you can make it a template:
template<size_t N>
std::string convert(char const(&data)[N])
{
return std::string(data, std::find(data, data + N, '\0'));
}
If you know what is the length of the character array I may suggest you the following:
#include <string>
#include <iostream>
std::string sconvert(const char *pCh, int arraySize){
std::string str;
if (pCh[arraySize-1] == '\0') str.append(pCh);
else for(int i=0; i<arraySize; i++) str.append(1,pCh[i]);
return str;
}
int main(){
char t1[]={'1','2','\0','\0'};
char t2[]={'1','2','3','4'};
std::string str = sconvert(t1, 4);
std::cout << str << " : " << str.size() << std::endl;
str = sconvert(t2, 4);
std::cout << str << " : " << str.size() << std::endl;
}
I figured this question had been asked a million times but I can't find the answer anywhere. Should be simple. Ok so I have a struct in my .h file:
struct question{
string programNum;
string programDesc;
string programPoints;
string programInput;
char programQuestion;
};
And then I have function initiated in the .h and arguments in .cpp:
void setQuestionFileName(question q, char fileName){
q.programQuestion = fileName;
}
Ok all is well so far. Now in main I have the issue of trying to store argv[1] in programQuestion:
char* fileName = argv[count+1];
followed by:
setQuestionFileName(questions[count],fileName);
cout << questions[count].programQuestion << endl;
I'm not real good with pointers so if anyone could help me store the char* argv into the char questions[count].programQuestion that would be amazing. Thank you!
I'm going to post the code, I think it may work better that way. This is the .h:
using namespace std;
// Data
struct question{
string programNum;
string programDesc;
string programPoints;
string programInput;
char* programQuestion;
};
void setQuestionFileName(question* q, char* fileName);
void display(question* q);
void display(question* q);
This is the .cpp
using namespace std;
void setQuestionFileName(question* q, char* fileName){
strcpy(q->programQuestion, fileName);
}
void display(question* q){
cout << "Description = " << q->programDesc << endl;
cout << "Number of Points = " << q->programPoints << endl;
cout << "Name of Question File = " << q->programQuestion << endl;
}
// Not used or tested yet
int myCompare (const void * a, const void * b ) {
const char *pa = *(const char**)a;
const char *pb = *(const char**)b;
return strcmp(pa,pb);
}
And main.cpp:
using namespace std;
int main(int argc, char* argv[]){ //or char** argv
question* questions[argc-1]; //Array of questions to be filled by loop.
int sizeOfQuestions = argc; //number of questions passed in at run time
int numLines = 0; //number of lines in file
for(int i=0;i<argc;i++){ //Test loop to make sure the command line file names are read in
std::cout << argv[i] << " says hello" << std::endl;
}
for(int count=0;count<sizeOfQuestions-1;count++){ //This loop places the information from the files into structs
//char fileName = argv[count+1];
char* fileName = argv[count+1];
cout << "Problem number: " << count+1 << "\t Working with file " << fileName << endl;
std::fstream questionFile (fileName, std::fstream::in); //Open the file
if(questionFile.good()){
cout << "File Opened" << endl;
setQuestionFileName(questions[count],fileName);
cout << questions[count]->programQuestion << endl;
getline(questionFile,questions[count]->programNum);
getline(questionFile,questions[count]->programDesc);
getline(questionFile,questions[count]->programPoints);
getline(questionFile,questions[count]->programInput);
display(questions[count]);
questionFile.close();
}else{
cout << "Could not open file!!!" << endl;
}
}
return 0;
}
The way it is now, I'm getting a segmentation fault.
Change your programQuestion from char to char*
And, this function
void setQuestionFileName(question q, char fileName){
q.programQuestion = fileName;
}
I think it should be
void setQuestionFileName(question& q, char* fileName){
strcpy(q.programQuestion, fileName);
}
Hardly there is a file with only 1-character name.
I am working on an assignment that requires me to read in several lines of text from a file, and at the end use qsort to sort the words used alphabetically and display a count of how many times each word was used. I realized I'm going to have to tokenize the strings as they are read in from the file. The only problem is that the individual tokens kind of disappear after you do it so I have to add them to a list. I'm bad at explaining, so here's my code:
#include<iostream>
#include<string>
#include<algorithm>
#include<stdlib.h>
#include<fstream>
using namespace std;
int compare(const void* , const void*);
const int SIZE = 1000;
const int WORD_SIZE = 256;
void main()
{
cout << "This program is designed to alphabetize words entered from a file." << endl;
cout << "It will then display this list with the number of times " << endl;
cout << "that each word was entered." << endl;
cout << endl;
char *words[SIZE];//[WORD_SIZE];
char temp[100];
char *tokenPtr, *nullPtr= NULL;
char *list[SIZE];
string word;
int i = 0, b = 0;
ifstream from_file;
from_file.open("prob1.txt.txt");
if (!from_file)
{
cout << "Cannot open file - prob1.txt";
exit(1); //exits program
}
while (!from_file.eof())
{
from_file.getline(temp, 99);
tokenPtr = strtok(temp, " ");
while (tokenPtr != NULL)
{
cout << tokenPtr << '\n';
list[b] = tokenPtr;
b++;
tokenPtr = strtok(nullPtr, " ");
}
word = temp;
transform(word.begin(), word.end(), word.begin(), ::tolower);
words[i] = list[i];
i++;
}
from_file.close();
qsort(words, i, WORD_SIZE, compare);
int currentcount = 1 ;
int k;
for( int s = 0; s < i; s++ )
{
for( k = 1; k <= s; k++)
{
if( words[s] == words[k] )
{
currentcount++;
}
currentcount = 1;
words[k] = "";
}
cout << words[s] << " is listed: " << currentcount << " times." << endl;
words[s] = "";
}
}
int compare(const void* p1, const void *p2)
{
char char1, char2;
char1 = *(char *)p1; // cast from pointer to void
char2 = *(char *)p2; // to pointer to int
if(char1 < char2)
return -1;
else
if (char1 == char2)
return 0;
else
return 1;
}
The only thing missing is the compare function, but the program works fine, up until the qsort, wherein it crashes, but it doesn't tell me why. Can anybody shed some insight/help me fix this up?
Again, this IS an assignment. (I was told I need to specify this?)
The array words is an array of pointers to char:
char* words[SIZE]; // SIZE elements of type `char*`
So the third parameter WIDTH should be the width of a pointer to char.
qsort(words, i, sizeof(char*), compare);
Also your implementation of compare is not working as you expect.
You are passing pointers to the compare. But they are pointers at the elements. You need to de-reference the pointers to get the values:
int compare(const void* p1, const void *p2)
{
char const* x = *(char**)p1;
char const* y = *(char**)p2;
This does not compare strings:
if( words[s] == words[k] )
This just compares two pointers. To compare the strings they point at use strcmp()
if( strcmp(words[s], words[k]) == 0)
This should stop the crashes, but there is a lot more improvements to this code we can do:
Once you get it working you should post it here https://codereview.stackexchange.com/ for a review.
Quick disclaimer, this is a contrived example meant to simulate an issue I am seeing in my homework problem. To that end, using strings is out of the question; I can only use char arrays as per the instructor :(
What I am trying to do is continuously read input from the keyboard and store it in a vector . The problem is, whatever data I add to the vector is lost as soon as the addData function ends (when I try to view it, I see \320\366\277_\377). I believe this is due to the fact I am using a vector<char*>, so the vector can only use the data for as long as the pointer exists. However, my code cannot compile if I change it to a vector<char>, as I get errors saying cannot convert char* to char.
So, how can I save a char array (not a single char) to a vector element? Or, is there perhaps a better approach to this that would avoid the problem altogether?
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int MAX_BUFFER_SIZE = 80;
// class declaration
class Example {
public:
void getData ();
void addData ( char * newData );
void displayData ();
private:
vector<char*> vec;
};
// main function
int main () {
bool quitProg;
int quit;
quitProg = false;
Example shoopDaWhoop; // buffers cannot overflow if you shoop da whoop
while (!quitProg) {
shoopDaWhoop.getData();
shoopDaWhoop.displayData();
cout << "Type 1 if you want to exit... ";
cin >> quit;
if (quit == 1) {
quitProg = true;
}
}
return 0;
}
void Example::getData () {
char userInput [MAX_BUFFER_SIZE];
cout << "Enter text: ";
cin.get(userInput, MAX_BUFFER_SIZE - 1, '\n');
if ( cin.fail() ) { // data is invalid
// clear and reset input stream
cin.clear(ios::goodbit);
cin.ignore(INT_MAX,'\n');
// alert user they entered bad data
cout << "That was bad data!" << endl;
}
else {
// data is good, pass it to addData
addData( userInput );
}
}
void Example::addData ( char * newData ) {
vec.push_back(newData);
cout << "You entered: " << vec.back() << endl;
}
void Example::displayData () {
for (int i=0; i<vec.size(); i++) {
cout << "Item " << i << ": " << vec[i] << endl;
}
}
Go with the vector<char>, but instead of
vec.push_back(newData);
Use:
size_t len = strlen(newData);
vec.insert(vec.end(), newData, newData + len);
Or does it actually need to be an vector of char arrays?
Use a std::vector<std::string>, that should "just work" with your existing code.
Since you cant do this with std::string (which would have been the proper way to use the language), the you a nested vector, like this:
std::vector<std::vector<char> > vex; // notice the space between the '>' chars, older compilers may need it this way
Then in your addData function:
std::vector<char> tmp;
while(*newData)
tmp.push_back(*newData++);
vec.push_back(tmp);
vector<char*> will only hold pointers - you want it to hold characters. To display the text, you'll have to iterate through the vector and print each character.
vector<char> vec;
void Example::addData ( char * newData ) {
cout << "You entered: ";
while (*newData) {
vec.push_back(*newData);
cout << (*newData);
++newData;
}
cout << endl";
}
If you want multiple strings you can use another vector.