Make dynamically allocated object type string - c++

I need to make dynamically allocated object type of string to store sentences and after that sentences should be sorted in alphabetical order using std::sort.
This would be correct solution using char array:
#include <cstring>
#include <iostream>
#include <new>
#include <string>
#include <algorithm>
int main() {
std::cout << "How many senteces: ";
int n;
std::cin >> n;
std::cin.ignore(1000, '\n');
char ** sentence = nullptr;
std::cout << "Enter senteces:" << std::endl;
try {
sentence = new char * [n];
for (int i = 0; i < n; i++)
sentence[i] = nullptr;
for (int i = 0; i < n; i++) {
char temp[1000];
std::cin.getline(temp, 1000);
sentence[i] = new char[strlen(temp) + 1];
strcpy(sentence[i], temp);
}
std::sort(sentence, sentence + n, [](const char * a,
const char * b) {
return std::strcmp(a, b) < 0;
});
std::cout << "Sorted sentences:" << std::endl;
for (int i = 0; i < n; i++)
std::cout << sentence[i] << std::endl;
for (int i = 0; i < n; i++)
delete[] sentence[i];
delete[] sentence;
} catch (...) {
std::cout << "Problems with memory!";
return 0;
}
return 0;
}
When I try to convert this to dynamically allocated array type of string, like this:
#include <cstring>
#include <iostream>
#include <new>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::cout << "How many senteces: ";
int n;
std::cin >> n;
std::cin.ignore(1000, '\n');
std::string ** sentence = nullptr;
std::cout << "Enter senteces:" << std::endl;
try {
sentence = new std::string * [n];
for (int i = 0; i < n; i++)
sentence[i] = nullptr;
for (int i = 0; i < n; i++) {
std::string temp;
std::getline(std::cin, temp);
sentence[i] = new std::string[temp.length() + 1];
temp = sentence[i];
}
std::sort(sentence, sentence + n, [](std::string a,
std::string b) {
for (char & c: a) c = std::toupper(c);
for (char & c: b) c = std::toupper(c);
return a < b;
});
std::cout << "Sorted sentences:" << std::endl;
for (int i = 0; i < n; i++)
std::cout << sentence[i] << std::endl;
for (int i = 0; i < n; i++)
delete[] sentence[i];
delete[] sentence;
} catch (...) {
std::cout << "Problems with memory!";
return 0;
}
return 0;
}
I get a bunch of errors. Could you explain me how to convert this program of dynamically allocation of char array to dynamically allocated string array on a correct way?

It looks like you think std::string "corresponds to" char, but it corresponds to char*.
You want std::string* sentence = nullptr;.
(A lot of the point of this exercise is to notice how much easier it gets when you don't need to allocate the strings yourself.)
int main() {
try {
std::cout << "How many sentences: ";
int n;
std::cin >> n;
std::cin.ignore(1000, '\n');
std::cout << "Enter sentences:" << std::endl;
std::string* sentence = new std::string [n];
for (int i = 0; i < n; i++) {
std::getline(std::cin, sentence[i]);
}
std::sort(sentence, sentence + n, [](std::string a,
std::string b) {
for (char & c: a) c = std::toupper(c);
for (char & c: b) c = std::toupper(c);
return a < b;
});
std::cout << "Sorted sentences:" << std::endl;
for (int i = 0; i < n; i++)
std::cout << sentence[i] << std::endl;
delete[] sentence;
} catch (...) {
std::cout << "Problems with memory!";
}
}

Related

Code won't run, getting stuck at while loop

When I try to run the program visual studio code gets stuck at the while look and won't run the code. When copy and pasting the code to an online compiler the code runs. Also I can't use vectors or reverse from the library.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
using namespace std;
void reverse(double* a, int size)
{
double* left = a;
double* right = a + size - 1;
while (left < right)
{
double temp = *left;
*left++ = *right;
*right-- = temp;
}
}
int main()
{
int size = 0;
float input;
double* a = new double[size];
int capacity = 10;
cout << "Please enter the values: ";
while (cin >> input)
{
if (cin.fail())
{
cin.clear();
}
if (size == capacity) {
capacity *= 2;
}
a[size++] = input;
if (size == capacity)
{
capacity *= 2;
double* b = new double[capacity];
for (int i = 0; i < size; i++)
{
b[i] = a[i];
}
delete[] a;
a = b;
}
}
cout << "The input values are: ";
for (int i = 0; i < size; i++)
{
cout << a[i];
if (i < size - 1)
cout << ", ";
}
cout << endl;
reverse(a, size);
cout << "The reversed values are: ";
for (int i = 0; i < size; i++)
{
cout << a[i] << " ";
if (i < size - 1)
cout << ", ";
}
cout << endl;
return 0;
}
I tried using a break command it didn't work. I'm expecting the code to run the function and take in all the inputs and print the array and its reverse
can you check if this is the answer you wanted, I made the input variable integer type where you were using float/double type, I thought it is the problem, also you did not update the input in the while loop so I used while(input--) . These are the changes I have made I do not know if this is the answer you wanted. I added the comment where I made changes to the code. Hope it is helpful.
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
using namespace std;
void reverse(double* a, int size)
{
double* left = a;
double* right = a + size - 1;
while (left < right)
{
double temp = *left;
*left++ = *right;
*right-- = temp;
}
}
int main()
{
int size = 0;
int input; // I made input variable integer type you were using float type
double* a = new double[size];
int capacity = 10;
cout << "Please enter the values: ";
cin >> input ; // took the value of the input variable here
while (input--) // you did not decrement the input variable
{
if (cin.fail())
{
cin.clear();
}
if (size == capacity) {
capacity *= 2;
}
a[size++] = input;
if (size == capacity)
{
capacity *= 2;
double* b = new double[capacity];
for (int i = 0; i < size; i++)
{
b[i] = a[i];
}
delete[] a;
a = b;
}
}
cout << "The input values are: ";
for (int i = 0; i < size; i++)
{
cout << a[i];
if (i < size - 1)
cout << ", ";
}
cout << endl;
reverse(a, size);
cout << "The reversed values are: ";
for (int i = 0; i < size; i++)
{
cout << a[i] << " ";
if (i < size - 1)
cout << ", ";
}
cout << endl;
return 0;
}```

Run Time Check Error # 2

#include <string.h>
#include "BubbleSort.h"
void BubbleSort(char Str[])
{
int i;
int NumElements;
bool Sorted;
char Temp;
NumElements = strlen(Str);
do {
Sorted = true;
NumElements--;
for (i = 0; i < NumElements; i++)
if (Str[i] > Str[i + 1])
{
Temp = Str[i];
Str[i] = Str[i + 1];
Str[i + 1] = Temp;
Sorted = false;
}
} while (!Sorted);
}
/////////////////////////////////////////////
#include <iostream>
#include "Bubblesort.h"
using namespace std;
void main() {
int Num;
char Array[20];
cout << "How many numbers would you like to enter?" << endl;
cin >> Num;
cout << "Enter your numbers:" << endl;
for (int i = 0; i < Num; i++)
{
cin >> Array[i];
}
cout << "Here are the numbers you entered:" << endl;
for (int i = 0; i < Num; i++)
{
cout << Array[i] << " ";
}
cout << endl << endl;
BubbleSort (Array);
cout << "Here are your sorted numbers:" << endl;
for (int i = 0; i < Num; i++)
{
cout << Array[i] << " ";
}
cout << endl;
}
////////////////////////////////////////////////////////
#ifndef BUBBLE_SORT_H
#define BUBBLE_SORT_H
void BubbleSort(char[]);
#endif
I get a Run Time Error stating that Num was corrupted. Can anyone help pinpoint the problem in my code?
Thanks
char Array[20] while the Num you input is larger than 20, it will corrupt.
Better use vector and push_back
One mistake is that you're calling strlen on a char array that is not guaranteed to be NULL terminated:
NumElements = strlen(Str);
Thus NumElements has an undetermined value.
You need to either:
1) pass the actual number of characters that are to be sorted as a parameter, along with the array and getting rid of the call to strlen:
BubbleSort(Array, Num);
//...
void BubbleSort(char Str[], int NumElements)
or
2) Make sure the char array you're passing is null terminated

Can't return dynamic string from a function

I was writing some code challenge from reddit about encrypting strings and I came up with something like this:
#include <iostream>
#include <string>
using namespace std;
string encrypt(string sentence);
int main()
{
string sentence;
int i = 0;
cout << "Welcome. Enter a sentence: ";
getline(cin, sentence);
cout << sentence << endl;
encrypt(sentence);
cout << endl << endl;
system("pause");
return 0;
}
string encrypt(string sentence)
{
int i = 0;
int x = (sentence.size());
string *encrypted_sentence = new string[sentence.size()];
int *wsk = new int[sentence.size()];
for (i = 0; i < x; i++)
{
wsk[i] = sentence[i];
}
for (i = 0; i < x; i++)
{
if (wsk[i] == ' ')
continue;
else if (islower(wsk[i]))
{
if (wsk[i] <= 99)
wsk[i] = (wsk[i] + 23);
else
wsk[i] = (wsk[i] - 3);
}
else
{
if (wsk[i] <= 67)
wsk[i] = (wsk[i] + 23);
else
wsk[i] = (wsk[i] - 3);
}
}
for (i = 0; i < x; i++)
{
//cout << static_cast <char> (wsk[i]);
encrypted_sentence[i] = wsk[i];
}
return *encrypted_sentence;
}
My problem is, that there is nothing that gets returned. After I run the program I get nothing in return. Can anybody point me in the right direction with this? What have I missed?
First main() returns an int always. void main() is not standard. Secondly:
string encrypted_sentence = new string[sentence.size()];
Will not even compile. encrypted_sentence is of type std::string but you are trying to assign to it a std::string *. Third you should avoid using using namespace std;
Update:
I believe you are trying to output the encrypted string at:
cout << endl << endl;
But all this is doing is outputting 2 newlines and flushing the output twice. If you want to display the encrypted string then you either need to capture the return of the encrypt() function and display it or encrypt() can take the string in by reference. IF you change encrypt() to take a reference then it would become:
void encrypt(string & sentence)
{
string *encrypted_sentence = new string[sentence.size()]; // get rid of this line as it is not needed.
//...
for (i = 0; i < x; i++)
{
sentence[i] = wsk[i];
}
}
And then you would output the string with:
cout << sentence << endl;
In case anyone would seek an answer to this question, I've come up with this, and I'm pretty sure it finally works how I wanted it to:
#include <iostream>
#include <string>
std::string encrypt(std::string to_encrypt);
int main()
{
std::string sentence;
std::string result;
std::cout << "Welcome. Please enter a sentence: ";
getline(std::cin, sentence);
result = encrypt(sentence);
std::cout << "Result: " << result << std::endl;
system("pause");
return 0;
}
std::string encrypt(std::string to_encrypt)
{
int i = 0;
int x = (to_encrypt.size());
std::cout << std::endl << "x = " << x << std::endl;
int *temp = new int[to_encrypt.size()];
for (i = 0; i < x; i++)
{
temp[i] = to_encrypt[i];
}
for (i=0; i < x; i++)
{
if (temp[i] == ' ')
continue;
else if (islower(temp[i]))
{
if (temp[i] <= 99)
temp[i] = temp[i] + 23;
else
temp[i] = temp[i] - 3;
}
else
{
if (temp[i] <= 67)
temp[i] = temp[i] + 23;
else
temp[i] = temp[i] - 3;
}
}
std::string encrypted;
for (i = 0; i < x; i++)
{
encrypted += (static_cast <char> (temp[i]));
}
return encrypted;
}
The code is obviously wrong. string *encrypted_sentence = new string[sentence.size()]; allocates an ARRAY of strings! Not a single string. Judging from that, you can see how your code is wrong.

how to save the sorted arrays in textfile?

I have a program that sorted arrays how can i save in text file?
for example: the sorted arrays is: 1, 2, 3, 4, 5.
how can i save in text file named. Sorted elements".
I've tried many ways but the sorted array wouldn't save in text file.
I am a newbie so I find it difficult.
here is my code.
#include <iostream>
using namespace std;
int main() {
cout << "Enter number of element:";
int n; cin >> n;
int a[n];
for(int i=0;i<n;i++)
{
cout << "element number " << (i+1) << " : ";
cin >> a[i];
}
int e=1, d=3;
int i, j, k, m, digit, row, col;
int length = sizeof(a)/sizeof(int);
int bmat[length][10];
int c[10];
for(m=1;m<=d;m++)
{
for(i=0;i<10;i++)
{
c[i]=-1;
}
for(i=0;i<length;i++)
{
digit=(a[i]/e)%10;
c[digit]++;
row=c[digit];
col=digit;
bmat[row][col]=a[i];
}
k=-1;
for(i=0;i<10;i++)
{
if(c[i]!=-1)
{
for(j=0;j<=c[i];j++)
{
k++;
a[k]=bmat[j][i];
}
}
}
e=e*10;
}
cout << endl;
cout << "Sorted array:" << endl;
for(int i=0;i<n;i++)
{
cout << a[i] << " , ";
}
cout << endl;
system("pause");
return 0;
}
//Use this code
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;
int main()
{
int n = 0;
cout << "Enter number of element:";
cin >> n;
//Data Structure
std::vector<int> list;
//push back element in vector
for(register int i=0;i<n;++i)
list.push_back(rand()%10 + 1);
//do shuffling before sorting because rand() generates increasing order number
std::random_shuffle(list.begin(),list.end());
std::sort(list.begin(),list.end());
ofstream textfile;
textfile.open ("E:\\example.txt");
for(size_t i= 0;i<list.size();++i)
textfile << list[i] <<" ";
textfile.close();
}
If you can write the sorted array to std::cout, then you can write it to a file. In C++, the console is the same as a file.
Put this at the end of main:
cout << "Sorted array:" << endl;
print_array( std::cout, a, n ); // Show the results to the user.
std::ofstream save( "array.txt" ); // Open a new file (or overwrite).
print_array( save, a, n ); // Save the results for later.
system("pause");
return 0;
}
and put the printing code in a new function, which may be defined before main:
void print_array( std::ostream & s, int * a, int n ) {
for(int i=0;i<n;i++)
{
s << a[i] << " , ";
}
s << endl;
}
#include<iostream>
#include<fstream>
using namespace std;
int compare(int, int);
void sort(int[], const int);
int compare(int x, int y){
return(x > y);
}
void swap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
void display(int array[], int n){
for (int i = 0; i<n; i++) {
cout << array[i] << " ";
}
cout << endl;
}
void writeToFile(int array[], int n){
ofstream myfile;
myfile.open("example.txt");
for (int i = 0; i<n; i++) {
myfile << array[i];
if (i != n - 1){
myfile << ", ";
}
}
myfile.close();
}
void sort(int table[], const int n) {
for (int i = 0; i < n; i++){
for (int j = 0; j < n - 1; j++) {
if (compare(table[j], table[j + 1]))
swap(&table[j], &table[j + 1]);
}
}
}
int main(){
int quantity;
int* tab;
ofstream outfile;
cout << "Enter number of element: ";
cin >> quantity;
tab = new int[quantity];
cout << "Element:\n\n" << endl;
for (int i = 0; i < quantity; i++){
int x = i;
cout << "#" << ++x << ":";
cin >> tab[i];
}
sort(tab, quantity);
cout << "The Sorted Elements are: ";
display(tab, quantity);
writeToFile(tab, quantity);
cout << endl;
getchar();
getchar();
//system("pause");
return 0;
}
in short, add this block to your code:
ofstream myfile;
myfile.open("example.txt");
for (int i = 0; i<n; i++) {
myfile << array[i];
if (i != n - 1){
myfile << ", ";
}
}
myfile.close();
You can use C++ fstream class, since you want to output, you can use ofstream here. You should just replace some "cout" with ofstream instance:
At the beginning of the code state it:
ofstream ofs("./sorted_elem.txt", ofstream::out);
When want to output:
ofs << "Sorted array:" << endl;
for(int i=0;i<n;i++)
{
ofs << a[i] << " , ";
}
ofs << endl;
In C++ you really want to use std::vector or some other nice container for storing arrays of numbers. For writing an array to file you need to open the file and individually write each element to the file (all untested).
#include <fstream>
int main()
{
std::ofstream fp("output.txt");
int data[5]; // todo: fill
for (unsitned i = 0; i < 5; ++i)
{
fp << data[i] << ' ';
}
}
And to read again:
#include <fstream>
int main()
{
std::ifstream fp("output.txt");
// todo: Determine the size of the array or guess it (don't guess it!)
unsigned array_size = 5;
int data[array_size];
int n = 0;
while (fp.good() && n < array_size) fp >> data[n++];
}
But because we are using C++, we can use std::vector:
#include <fstream>
#include <vector>
int main()
{
std::vector<int> me(5); // todo: fill
std::ofstream fp("output.txt");
for (size_t i = 0; i < me.size(); ++i) fp << me[i] << ' ';
// C++11: for (int d : me) fp << d << ' ';
}
And,
#include <fstream>
#include <vector>
int main()
{
std::ifstream fp("output.txt");
std::vector<int> data;
double buf;
while (fp >> buf) data.push_back(buf); // no longer need to guess
}
I think, the copy option was not demonstrated here so far.
Please check this code. (Assuming your vector is ready to use, I've skipped it).
The example uses a C-array and a vector. Please use the later in your code whenever possible. But however, for copy-function both work:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <fstream>
int main () {
int a[10]={0,1,2,3,4,5,6,7,8,9};
std::vector<int> v; for (int i=0; i<10; ++i)v.push_back(i*10); //0, 10, 20,...
std::ofstream fs_a( "c:/temp/out_a.txt" );
//store space separated
std::copy ( a, a+sizeof(a)/sizeof(a[0]), std::ostream_iterator<int>( fs_a, " ") );
//store coma-separated, as one-liner
std::copy ( v.begin(), v.end() ), std::ostream_iterator<int>( std::ofstream( "c:/temp/out_v.txt" ), ",") );
return 0;
}

pthread_create passing in dynamic vector array into argument

how do I cast a void pointer vector array into a vector array?
vector<string>* vArray = new vector<string[numThreads];
p_thread_create(&my_thread[1], NULL, &function, (void)* vArray[1]);
void* function (vector<string> vArray[])
{
//?? casting?
}
when passed in as argument (void)* vArray[1] it says invalid cast...
And can pthread create take in more arguments, say 2, if the function takes 2 parameters? Thanks
Here's my complete code
#include <iostream>
#include <iomanip>
#include <iterator>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <pthread.h>
#include <queue>
using namespace std;
int array[5] = { 0, 0, 0, 0, 0 };
void* readData(void* arg)
{
string fileName = "Wisconsin.txt";
cout << "HERE!"<< endl;
ifstream cities(fileName.c_str());
string line;
while(!cities.eof()){
getline(cities, line);
if(line != "") {
int commaPos = line.find(',');
int popul = atoi(line.substr(commaPos + 2).c_str());
int x = popul;
if (x >= 1 && x <= 999)
{
array[0]++;
} else
if (x >= 1000 && x <= 9999)
{
array[1]++;
} else
if (x >= 10000 && x <= 99999)
{
array[2]++;
} else
if (x >= 100000 && x <= 999999)
{
array[3]++;
} else
if (x >= 1000000)
{
array[4]++;
}
} // end of IF
} // end of while
}
int main()
{
int numThreads;
ifstream ifs("states.txt");
std::string str((std::istreambuf_iterator<char>(ifs)),
std::istreambuf_iterator<char>());
stringstream ss(str);
int fileCount = 0;
string fileName;
while (ss >> fileName)
{
fileCount++;
}
cout << fileCount;
string* filesArr = new string[fileCount];
ss.clear();
ss.seekg(0, std::ios::beg);
for (int i = 0; i < fileCount; i++)
{
ss >> filesArr[i];
}
cout << "Enter number of threads: ";
cin >> numThreads;
vector<string>* vArray = new vector<string>[numThreads];
for (int i = 0; i < fileCount; i++)
{
vArray[i % numThreads].insert(vArray[i % numThreads].begin(), filesArr[i]);
}
//queue<string>* queueArr = new queue<string>[numThreads];
//for (int i = 0; i < fileCount; i++)
// queueArr[i % numThreads].push(filesArr[i]);
for(int i = 0; i < numThreads; i ++)
{
cout << endl;
cout << "FOR THREAD " << i + 1 << ":" << endl;
for (std::vector<string>::iterator it = vArray[i].begin(); it != vArray[i].end(); it++)
{
cout << *it << endl;
}
}
pthread_t my_thread[numThreads];
int ret = pthread_create(&my_thread[1], NULL, &readData, (void*)(vArray+1));
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
///////////// ERROR HERE!
pthread_join(my_thread[1], ret);
// for (int id = 0; id < numThreads; id++)
// {
//}
pthread_join(my_thread[1]);
cout << endl;
printf("%-20s", "1-999:");
cout << array[0] << endl;
printf("%-20s", "1,000 - 9,999:");
cout << array[1] << endl;
printf("%-20s", "10,000-99,999:");
cout << (array[2]) << endl;
printf("%-20s", "100,000-999,999:");
cout << (array[3]) << endl;
printf("%-20s", "1,000,000+:");
cout << (array[4]) << endl;
//int pos;
//string token;
//while ((pos = s.find(delimiter))
cin.get();
return 0;
}
pthread join doesn't seem to be working now.. compiling it return me: too few arguments to function 'int pthread_join(pthread_t, void**)
After cleaning up your code:
#include <iostream>
#include <vector>
using namespace std;
const int numThreads = 10;
void * thread_body (void * param)
{
// retrieve parameter
string& prm = *(string *)param;
// use it
cout << prm << endl;
return NULL;
}
int main() {
vector<string >threadPrm(numThreads);
vector<pthread_t>threadId (numThreads);
threadPrm[1] = "Hello";
pthread_create(&threadId[1], NULL, thread_body, &threadPrm[1]);
pthread_join (threadId[1], NULL);
return 0;
}
You don't seem to be comfortable with
vectors
pointers and references
variable naming
Also, trying to shut the compiler up with static casts is a sure way to produce silly code.
The point is usually to make the code run, not to compile it at all cost.
Lastly, you can answer your own question about the number of parameters a posix thread can take by reading the manual