Dynamically allocated array C++ reads a sentence and prints the words - c++

On the input we get a sentence which we read until EOF. We need to add single words to dynamic array and then write them one on each line.
Input: Hello this, is an example.
Output:
Hello
this,
is
an
example
I have the following code and I can't figure out why it doesn't even add anything to the array.
#include <iostream>
#include <string>
using namespace std;
void addToArray(string newWord, string myArray[], int& arrayLength)
{
string * tempArray = new string[arrayLength + 1];
tempArray[arrayLength] = newWord;
for (int i = 0; i < arrayLength; ++i)
{
myArray[i] = tempArray[i];
}
arrayLength++;
myArray = tempArray;
delete [] tempArray;
}
int main()
{
string * arrayOfWOrds = new string[1000];
int arrayLength = 0;
string temp;
while (getline(cin, temp))
{
cout << temp << endl;
addToArray(temp, arrayOfWOrds, arrayLength);
}
cout << "Array" << endl;
for (int i = 0; i < arrayLength; ++i)
{
cout << arrayOfWOrds[i] << endl;
}
}

It's because you don't return the new array from the addToArray function. The change you make only happens in addToArray, it doesn't happen in main.
You also delete[] the wrong array, you delete the array you've just created.
You also copy the array elements in the wrong direction, i.e. from your new array to your old array.
Try this, I've renamed some of the variables for clarity. There is no temporary array in your function only a new array and an old array. Choosing good variable names is very important for writing working code. Bad variable names just confuse yourself.
string* addToArray(string newWord, string* oldArray, int& arrayLength)
{
string * newArray = new string[arrayLength + 1];
newArray[arrayLength] = newWord;
for (int i = 0; i < arrayLength; ++i)
{
newArray[i] = oldArray[i];
}
arrayLength++;
delete [] oldArray;
return newArray;
}
Then use it like this
arrayOfWOrds = addToArray(temp, arrayOfWOrds, arrayLength);

I see several issues here. To begin with, you set arrayLength = 0, so it's not going to iterate over the whole array if you have stuff already in it. If you don't have anything in it, there's no point in making it start off with 1000 items. Also, while (getline(cin,temp)) is an infinite loop, so it will never end and actually print the array. If you want to print the array after each addition, you need to move it into the while loop. There's no real reason to cout the number the user types either; they can already see the line they just typed.
More importantly, there are real issues with the dynamic allocation. You've created a static array (string * arrayOfWOrds = new string[1000];), then you're giving that to the function which makes a new array one item larger, sets the last item in that array to the new value, then iterates over the entire new array and duplicates the values to the old array. Basically, you're just inserting items into the static array at that point, and what you're inserting is a bunch of nothing (because the new array only has one item in it, and it's at arrayLength+1 which is outside the bounds of the original array).
You need to delete the old array, not the new array, which actually should be thrown on the heap and returned.
Basically, it should look more like this:
#include <iostream>
#include <string>
using namespace std;
string* addToArray(string newWord, string myArray[], int& arrayLength)
{
string * returnArray = new string[arrayLength + 1];
returnArray[arrayLength] = newWord;
for (int i = 0; i < arrayLength; ++i)
{
returnArray[i] = myArray[i];
}
arrayLength++;
delete [] myArray;
return returnArray;
}
int main()
{
const int startSize = 0;
string * arrayOfWords = new string[1];
int arrayLength = startSize;
string temp;
cout << "Input: ";
getline(cin, temp);
string word = "";
for (char c : temp){
if (c == ' '){
arrayOfWords = addToArray(word, arrayOfWords, arrayLength);
word = "";
} else word.push_back(c);
}
arrayOfWords = addToArray(word, arrayOfWords, arrayLength); // Don't forget the last word
for (int i = 0; i < arrayLength; ++i)
{
cout << arrayOfWords[i] << endl;
}
}

The array is unchanged, because you pass the pointer to the addToArray function, but it has no way to pass the new pointer back. You can fix this by changing the signature of the function to
void addToArray(string newWord, string *myArray[], int& arrayLength)
You also need to change the code accordingly, and fix problem with deallocation.
You can save yourself all the trouble and use std::vector in place of manually allocated dynamic array:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> arrayOfWOrds;
string temp;
while (getline(cin, temp))
{
cout << temp << endl;
arrayOfWOrds.push_back(temp);
}
cout << "Array" << endl;
for (size_t i = 0; i < arrayOfWOrds.size(); ++i)
{
cout << arrayOfWOrds[i] << endl;
}
}

string in="dasd adas ads adsada adsa asd ads",out;
stringstream ss(in);
vector<string> vr;
while(ss>>out)
{
vr.push_back(out);
//cout<<out<<endl;
}
for(int i=0;i<vr.length();i++)
{
cout<<vr[i]<<endl;
}
try doing this

Related

Having trouble with my C++ program. Involes resizing an integer array dynamically

Here is what I have so far: http://cpp.sh/54vn3
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
#include <cstdlib>
using namespace std;
int *reSIZE(int *&original, int &SIZE, const int &maxSIZE); //function prototype resize
void sortFUNC(int *&original, int &SIZE, const int &maxSIZE); //function prototype sortFUNC
int main()
{
int SIZE = 4; //size of current array
int maxSIZE = 10; //size of final array
int *original = new int[SIZE] {5, 7, 3, 1}; //old(current) array
cout << "Elements in array: "; //test output
reSIZE(original, SIZE, maxSIZE); //call function resize
cout << endl << endl; //blank line
cout << "Elements in array in increasing order: "; //test output
sortFUNC(original, SIZE, maxSIZE); //call function sortFUNC
cout << endl << endl;
return 0;
}
int *reSIZE(int *&original, int &SIZE, const int &maxSIZE)//function definition
{
int *temporiginal = new int[SIZE + 3]; //(final)new array
for (int i = 0; i < SIZE; i++) //copy old array to new array
{
temporiginal[i] = original[i];
cout << original[i] << setw(3);
}
delete[] original; //delete old array
original = temporiginal; //point old array to new array
return temporiginal;
}
void sortFUNC(int *&original, int &SIZE, const int &maxSIZE)
{
for (int i = 0; i < SIZE; i++)
{
int smallest = original[i];
int smallestINDEX = i;
for (int m = i; m < SIZE; m++)
{
if (original[m] < smallest)
{
smallest = original[m];
smallestINDEX = m;
}
}
swap(original[i], original[smallestINDEX]);
}
int *temporiginal = new int[SIZE + 3];
for (int i = 0; i < SIZE; i++)
{
temporiginal[i] = original[i];
cout << original[i] << setw(3);
}
delete[] original;
original = temporiginal;
}
I want to add a few elements at the end of the array in main, but when I do, the program crashes when I run it. The resize function that I created is supposed to expand the function in main to hold 10 elements. The one in main originally holds 4. The new array is supposed to change that to 10. How do I add three more integers to the array in main without it crashing? Is my resize function wrong? Or is it a problem in my main? The program that is shown right now works as is. But when I add another integer in the array in main, it crashes. Like, if I add a 2 after the 1.
Thanks.
Edit: I was able to add elements at the end of the array in main by adding them in the resize function.
cpp.sh/35mww
Like mentioned earlier, maxSIZE isn't being used. There are more useless stuff as well. I have to clean this up, but I figured out what I was trying to figure out. I don't know how to use structures yet. I know that there are a lot of different ways to write a program. I'm just a beginner.
Thanks, everyone.
You need to modify the value of size everytime you call the function rezise other wise even if u call the function resize 3 times u always will have SIZE+3 on your array size.After call resize try
original[4] = 0;
original[5] = 0;
original[6] = 0;
and after that try to do this.
original[7] = 0;
you should be able to see your mistake

C++ Dynamic data – how to obtain it and how to get rid of it

The code below – it's a skeleton of a program operating on the dynamic collection of data. The idea is to use a structure containing two fields: the first stores the number of elements in collections, and the second is the actual collection (a dynamically allocated vector of ints). As you can see, the collection is filled with the required amount of pseudo-random data.
Unfortunately, the program requires completion, as the most important function.
Here's what i expect from the function:
if the collection is empty, it should allocate a one-element vector and store a new value in it.
if the collection is not empty, it should allocate a new vector with a length greater by one than the current vector, then copy all elements from the old vector to the new one, append a new value to the new vector and finally free up the old vector.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Collection {
int elno;
int *elements;
};
void AddToCollection(Collection &col, int element) {
//the first part of the funtion
if (col.elno==0){
col.elements= new int[1];
col.elements[0]= element;
}
//this is the second part but i do not know how to do it.
//Please help me to complete***************
else {
int *temp;
temp = new[];
}
}
void PrintCollection(Collection col) {
cout << "[ ";
for(int i = 0; i < col.elno; i++)
cout << col.elements[i] << " ";
cout << "]" << endl;
}
int main(void) {
Collection collection = { 0, NULL };
int elems;
cout << "How many elements? ";
cin >> elems;
srand(time(NULL));
for(int i = 0; i < elems; i++)
AddToCollection(collection, rand() % 100 + 1);
PrintCollection(collection);
delete[] collection.elements;
return 0;
}
vector container is originally dynamic container. so u can use vector.
Just declare vector variable in structure and use it in AddToCollection function.
struct Collection {
int elno;
std::vector<int> elements;
};
void AddToCollection(Collection &col, int element) {
col.elements.push_back(element);
col.elno++;
}
like this.
Here is what you are looking for:
void AddToCollection(Collection &col, int element)
{
if(col.elements == NULL)
{
col.elements = new int[1];
col.elements[0] = element;
col.elno = 1;
}
else
{
int *newArr = new int[col.elno+1];
for(int i = 0; i < col.elno; i++)
{
newArr[i] = col.elements[i];
}
newArr[col.elno] = element;
delete[] col.elements;
col.elements = new int[col.elno+1];
for(int i = 0; i < col.elno+1; i++)
{
col.elements[i] = newArr[i];
}
delete[] newArr;
newArr = NULL; // avoid dangling pointer
col.elno++;
}
}
For sure using vector container is a great ideea but the exercise require no modification to the main function. The objective of this exercise is to help the student to understand dynamically allocated memory.

Doubling of an arbitrary array of strings

1: My goal is to create two arbitrary arrays using pointers: one with names, another one with corresponding numbers. From my previous question, I know that doubling an array is a good way to deal with arbitrary sizes. So, I am trying to double both arrays correspondingly. But while the doubling of an int array goes well, array of strings does not double. Could you explain, what is the problem with that?
2: Is there an alternative to the creation of arbitrary array of strings to store list of names?
Here is the part of the code:
string *pn = new string [size];
int *pd = new int [size];
while (x != 0) {
if (size == k+1) {
pn = doubn (pn, size);
pd = doubd (pd, size);
}
pn[k] = name;
pd[k] = val;
cout << "Another entry? (0 for exit)";
cin >> x;
getline (cin, name, ',');
cin >> val;
++k;
}
for (int i = 0; i<k; ++i) {
cout << pn[i] << " - " << pd[i] << " days"; }
del (pn, pd, k);
cin.get ();
cin.ignore();
}
string* doubn (string *pn, int size) {
string* pnn = new string [size*2];
for (int i = 0; i < size; ++i) {
pnn [i] = pn[i]; }
delete pn;
return pnn; }
int* doubd (int *pd, int size) {
int *pdn = new int [size*2];
for (int i = 0; i<size; ++i) {
pdn [i] = pd[i];}
delete pd;
return pdn;}
To have arbitrary sized arrays, use vectors.
Vectors are a part of the C++ Standard Template Library (STL) and required the #include<vector> header.
For more information, check this out: http://www.cplusplus.com/reference/vector/vector/
Also, you should be using delete [] instead of delete.
You use delete on memory allocated by new[], you should use delete[] instead.
Using std::vector would be simpler and less error prone anyway.

VC++ Runtime Error : Debug Assertation Failed

Currently I am getting an runtime "assertation error"
Here is the error:
I'm reading words from a text file into dynamically allocated arrays.
this block of code is where I am filling the new arrays.
I know the problem is being caused by this block of code and something about my logic is off just can't see what it is.
//fill new arrays
for( int y = 0; y < new_numwords; y++)
{
for( int i = 0; i < NUM_WORDS; i++)
{
if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
{
New_SentenceArry[y] = SentenceArry[i];
New_WordCount[y] = WordCount[i];
y++;
}
}
}
Also how would I pass this dynamically allocated 2D array to a function? (the code really needs to be cleaned up as a whole)
char** SentenceArry = new char*[NUM_WORDS]; //declare pointer for the sentence
for( int i = 0; i < NUM_WORDS; i++)
{
SentenceArry[i] = new char[WORD_LENGTH];
}
Here is the full extent of the code.. help would be much appreciated!
Here is what is being read in:
and the current output (the output is how it's suppose to be ):
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
#include <iomanip>
using std::setw;
using std::left;
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
int main()
{
const int NUM_WORDS = 17;//constant for the elements of arrays
const int WORD_LENGTH = 50;//constant for the length of the cstrings (NEED TO GIVE THE VALUE ZERO STILL!)
short word_entry = 0; //declare counter
short new_numwords= 0; //declare new word count
char EMPTY[1][4]; //NULL ARRAY
EMPTY[0][0] = '\0';//define it as null
char** SentenceArry = new char*[NUM_WORDS]; //declare pointer for the sentence
for( int i = 0; i < NUM_WORDS; i++)
{
SentenceArry[i] = new char[WORD_LENGTH];
}
int WordCount[NUM_WORDS];//declare integer array for the word counter
for(int i = 0; i < NUM_WORDS; i++)//fill int array
{
WordCount[i] = 1;
}
int New_WordCount[NUM_WORDS] = {0};
ifstream read_text("DataFile.txt"); //read in our text file
if (read_text.is_open()) //check if the the file was opened
{
read_text >> SentenceArry[word_entry];
//REMOVE PUNCTUATION BEFORE BEING READ INTO THE ARRAY
while (!read_text.eof())
{
word_entry++; //increment counter
read_text >> SentenceArry[word_entry]; //read in single words of the text file into the array SentenceArry
char* ptr_ch;//declare our pointer that will find chars
ptr_ch = strstr( SentenceArry[word_entry], ",");//look for "," within the array
if (ptr_ch != NULL)//if true replace it with a null character
{
strncpy( ptr_ch, "\0" , 1);
}//end if
else
{
ptr_ch = strstr( SentenceArry[word_entry], ".");//look for "." within the array
if (ptr_ch != NULL)//if true replace it with a null character
{
strncpy( ptr_ch, "\0" , 1);
}//end if
}//end else
} //end while
}//end if
else
{
cout << "The file could not be opened!" << endl;//display error message if file doesn't open
}//end else
read_text.close(); //close the text file after eof
//WORD COUNT NESTED FOR LOOP
for(int y = 0; y < NUM_WORDS; y++)
{
for(int i = y+1; i < NUM_WORDS; i++)
{
if (strcmp(SentenceArry[y], EMPTY[0]) == 0)//check if the arrays match
{
y++;
}
else
{
if (strcmp(SentenceArry[y], SentenceArry[i]) == 0)//check if the arrays match
{
WordCount[y]++;
strncpy(SentenceArry[i], "\0" , 3);
}//end if
}//end if
}//end for
}//end for
//find how many arrays still contain chars
for(int i = 0; i < NUM_WORDS; i++)
{
if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
{
new_numwords++;
}
}
//new dynamic array
char** New_SentenceArry = new char*[new_numwords]; //declare pointer for the sentence
for( int i = 0; i < new_numwords; i++)
{
New_SentenceArry[i] = new char[new_numwords];
}
//fill new arrays
for( int y = 0; y < new_numwords; y++)
{
for( int i = 0; i < NUM_WORDS; i++)
{
if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
{
New_SentenceArry[y] = SentenceArry[i];
New_WordCount[y] = WordCount[i];
y++;
}
}
}
//DISPLAY REPORT
cout << left << setw(15) << "Words" << left << setw(9) << "Frequency" << endl;
for(int i = 0; i < new_numwords; i++) //compare i to the array constant NUM_WORDS
{
cout << left << setw(15) << New_SentenceArry[i] << left << setw(9) << New_WordCount[i] << endl; //display the contents of the array SentenceArry
}
//DEALLOCATION
for( int i = 0; i < NUM_WORDS; i++)//deallocate the words inside the arrays
{
delete [] SentenceArry[i];
}
for(int i = 0; i < new_numwords; i++)
{
delete [] New_SentenceArry[i];
}
delete [] SentenceArry; //deallocate the memory allocation made for the array SentenceArry
delete [] New_SentenceArry;//deallocate the memory allocation made for the array New_SentenceArry
}//end main
There are several issues with the code, not withstanding that this could be written using C++, not C with a sprinkling of C++ I/O..
Issue 1:
Since you're using c-style strings, any copying of string data will require function calls such as strcpy(), strncpy(), etc. You failed in following this advice in this code:
for( int y = 0; y < new_numwords; y++)
{
for( int i = 0; i < NUM_WORDS; i++)
{
if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
{
New_SentenceArry[y] = SentenceArry[i]; // This is wrong
New_WordCount[y] = WordCount[i];
y++;
}
}
}
You should be using strcpy(), not = to copy strings.
strcpy(New_SentenceArry[y], SentenceArry[i]);
Issue 2:
You should allocate WORD_LENGTH for both the original and new arrays. The length of the strings is independent of the number of strings.
char** New_SentenceArry = new char*[new_numwords]; //declare pointer for the sentence
for( int i = 0; i < new_numwords; i++)
{
New_SentenceArry[i] = new char[new_numwords];
}
This should be:
char** New_SentenceArry = new char*[new_numwords]; //declare pointer for the sentence
for( int i = 0; i < new_numwords; i++)
{
New_SentenceArry[i] = new char[WORD_LENGTH];
}
Issue 3:
Your loops do not check to see if the index is going out of bounds of your arrays.
It seems that you coded your program in accordance to the data that you're currently using, instead of writing code regardless of what the data will be. If you have limited yourself to 17 words, where is the check to see if the index goes above 16? Nowhere.
For example:
while (!read_text.eof() )
Should be:
while (!read_text.eof() && word_entry < NUM_WORDS)
Issue 4:
You don't process the first string found correctly:
read_text >> SentenceArry[word_entry]; // Here you read in the first word
while (!read_text.eof() )
{
word_entry++; //increment counter
read_text >> SentenceArry[word_entry]; // What about the first word you read in?
Summary:
Even with these changes, I can't guarantee that the program won't crash. Even it it doesn't crash with these changes, I can't guarantee it will work 100% of the time -- a guarantee would require further analysis.
The proper C++ solution, given what this assignment was about, is to use a std::map<std::string, int> to keep the word frequency. The map would automatically store similar words in one entry (given that you remove the junk from the word), and would bump up the count to 1 automatically, when the entry is inserted into the map.
Something like this:
#include <string>
#include <map>
#include <algorithm>
typedef std::map<std::string, int> StringMap;
using namespace std;
bool isCharacterGarbage(char ch)
{ return ch == ',' || ch == '.'; }
int main()
{
StringMap sentenceMap;
//...
std::string temp;
read_text >> temp;
temp.erase(std::remove_if(temp.begin(), temp.end(), isCharacterGarbage),temp.end());
sentenceMap[temp]++;
//...
}
That code alone does everything your original code did -- keep track of the strings, bumps up the word count, removes the junk characters from the word before being processed, etc. But best of all, no manual memory management. No calls to new[], delete[], nothing. The code just "works". That is effectively 5 lines of code that you would just need to write a "read" loop around.
I won't go through every detail, you can do that for yourself since the code is small, and there are vast amounts of resources available explaining std::map, remove_if(), etc.
Then printing out is merely going through the map and printing each entry (string and count). If you add the printing, that may be 4 lines of extra code. So in all, practically all of the assignment is done with effectively 10 or so lines of code.
Remove below code.
for(int i = 0; i < new_numwords; i++)
{
delete [] New_SentenceArry[i];
}

copying elements from one array to another

I am getting a crash error at run time and not sure what exactly to do with the function or how to get the data for it.
FUNCTION DETAILS
Write a function that accepts an int array and size as arguments, then create a new array that is one element bigger than the given. Setting the first element to 0, then copying over what is in the argument array to the new array.
MAIN DETAILS
Use in a program reading int n from input, then read int n from file data name data
passing it to element shifter, then printing it to output (one per line).
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
int main() {
fstream infile;
infile.open("D:\\data.txt");
int n, x;
infile >> x;
cout << "size of array: ";
cin >> n;
const int ARRAY_SIZE = n + x;
int elements[ARRAY_SIZE];
element_shift(elements, ARRAY_SIZE);
system("PAUSE");
return EXIT_SUCCESS;
}
First of all ARRAY_SIZE declared in the main function is not a constant variable but defined at run-time depending on user inputs. This means that the array elements should be created dynamically. On the other hand you read some x variable which is only used to define the size of the array and didn't initialized the array at all. I guess that the problem statement is to read the size of the array from the input, then the data of the array from the file.
There are also lot of mistakes in element_shift function.
Your code should look like something similar to this:
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
void element_shift(int* elmts, int size)
{
int new_size = size + 1;
int* shifter = new int[new_size];
shifter[0] = 0;
for(int i = 0; i < size; ++i)
{
shifter[i + 1] = elmts[i];
}
delete [] elmts;
elmts = shifter;
}
int main()
{
fstream infile;
infile.open("D:\\data.txt");
int n;
cout << "size of array: ";
cin >> n;
int* elements = new int[n];
for (int i = 0; i < n; ++i) {
infile >> elements[i];
}
element_shift(elements, n);
for (int i = 0; i < n; ++i) {
std::cout << elements[i] << std::endl;
}
return EXIT_SUCCESS;
}
First off, you spend alot of time creating the shifted array but don't return it back.
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
The elmt_sft pointer is never assigned. You are trying to access memory that is not there by using *elmt_sft. This may be causing your error. Also this function has no way of returning the new array shifter because that variable is locally declared and will disappear once the function exits. If you want to create something new in the function and still have it in memory once the function exits, I recommend creating the array dynamically and returning a pointer to it.
This is untested but should start you in the right direction. It will return a separate dynamically allocated array that will not override your other one.
int* element_shift(int elmts[], int size) {
int *result_array = new int[size + 1]; //dynamically create new array MAKE SURE TO DELETE
result_array[0] = 0; //set 0 index to 0
for (int i = 1; i < size + 1; i++)//start at 1 of the result and put value in
{
result_array[i] = elmts[i - 1];
}
return result_array; //returning pointer
}