An error when dynamically allocating memory for a char* - c++

So the main problem is there is run time error in the code:
char *wordBank[]= {new char[numWords+1]};
char buffer1[41];
for(int i=0; i<numWords;i++){
ifile >> buffer1;
int len = strlen(buffer1);
cout << buffer1<<"and"<<len <<endl;
wordBank[i] = new char[len + 1];
strncpy(wordBank[i], buffer1,len);
cout << wordBank[i]<<"and"<<len <<endl;
}
is it starts to mess up with what is in wordBank. It gets the words from a txt file into buffer1 and then copy if into the dynamically allocated char* array of wordBank. However I always get segmentation fault and the words are all incorrect. What did I do wrong?

You can simplify the code using C++ instead of C:
vector<string> wordBank(numWords);
string buffer1;
for (int i = 0; i < numWords; i++) {
ifile >> buffer1;
size_t len = buffer1.length();
cout << buffer1 << "and" << len << endl;
wordBank[i] = buffer1;
cout << wordBank[i] << "and" << len << endl;
}
Or even simpler, but adding error checking:
vector<string> wordBank(numWords);
for (int i = 0; i < numWords; i++) {
if (ifile >> wordBank[i])
cout << wordBank[i] << "and" << len << endl;
else { // no more words
wordBank.resize(i); // chop off the unused portion
break;
}
}

This line is wrong:
char *wordBank[] = {new char[numWords+1]};
wordBank is an array with one element, the value of that one element is a pointer to a character array with numWords+1 characters. When you access wordBank[1] you're outside the bounds of the array, which results in undefined behavior.
What you apparently want is:
char **wordBank = new char*[numWords];
This creates a dynamically-allocated array of numWords char* elements, which you will then assign in the for loop.
I don't see any need for numWords+1.

Related

How to save a string into dynamic char array

The array should be dynamic, but it is fixed.
Printing the array gives nothing.
I'm trying to create a dynamic char array, get a string line from user, save line string char by char into the array.
#include <iostream>
#include <string>
using namespace std;
int main()
{
char* lenptr = NULL; // declare a pointer initialized with null
int leng, arrsz;
string mystr;
cout << "enter a string: ";
getline(cin, mystr); // input a line of string
leng = mystr.length(); // get length of string
cout << "string length: " << leng << endl;
lenptr = new char[leng+1]; // declare a dynamic char array with length+1
for (int i = 0; i < leng; i++)
{
lenptr[i]=mystr[i]; // fill array with saved string
}
lenptr[leng] = '\0'; // save '\0' in last array cell
arrsz = sizeof(lenptr); // get size of array
cout << "size of array after saving " << leng << " chars: " << arrsz << endl;
cout << "string in array: ";
for (int j = 0; j < leng; j++) // print array
{
lenptr[j];
}
cout << endl;
// delete pointer
delete[] lenptr;
lenptr = NULL;
system("pause"); // pause system
return 0;
}
enter a string: helloworld
string length: 10
size of array after saving 10 chars: 8
string in array:
Press any key to continue . . .
You can't get the size of an array allocated with new[]. Although std::string is the recommended way to go about this, a vector would've been a more viable choice if the string absolutely had to be stored in a data structure.
At any rate, your program wasn't printing the characters of the array because you forgot a std::cout in the for loop:
for (int j = 0; j < leng; j++) // print array
{
cout<<lenptr[j];
}
and to actually print out the size of the array just use the leng variable you defined earlier:
cout << "size of array after saving " << leng << " chars: " << leng + 1 << endl;

Cannot Delete a pointer array inside a stuct pointer (c++)

Im having trouble with the syntax here. We are studying structures and pointers in class currently and are tasked with creating a dynamic array of a single structure with a pointer array inside to both be allocated and deleted by the end of the program. (Hopefully that made sense)
Here are the snippits of code im working with, note how the entry of scores works:
std::cin << stuArray[i].stuScore[j]
But then the deletion in a similar manner, does not:
delete[] stuArray[count].stuScore[j];
Deletion Code:
do
{
for (unsigned short j = 0; j < numTests; j++)
{
delete[] stuArray[count].stuScore[0]; //Syntax???????
}
count++;
} while (count < numStudents);
delete[] stuArray;
Score Entry Code (Which Works)
bool ScoreEntry(Student * stuArray, unsigned short numStudents, unsigned short numTests)
{
//Local Variables
unsigned short idTempChoice = 0;
//Get Id Number
std::cout << "\nChoose a student by ID and enter the test scores: ";
std::cin >> idTempChoice;
//Id lookup
for (unsigned short i = 0; i < numStudents; i++)
{
//Id Check
if (idTempChoice == stuArray[i].stuId)
{
std::cout << "Student selected: " << stuArray[i].stuName << std::endl;
//Score Entry
for (unsigned short j = 0; j < numTests; j++)
{
std::cout << "Test " << j + 1 << "'s Score: ";
std::cin >> stuArray[i].stuScore[j];
}//End For Loop j
return true;
}
}//End For Loop i
//Student Id not found
std::cout << "Student not found!\n";
return false;
}
Allocation Code (Struct):
void MemAllocation(Student * &stuArray, unsigned short &numStudents)
{
//Get Number of students
std::cout << "How many students have taken the test: ";
std::cin >> numStudents;
std::cout << std::endl;
//Dynamically allocate pointers
stuArray = new Student[numStudents];
}
Allocation Code (Pointer inside struct):
for (unsigned short i = 0; i < numTests; i++) //Allocate Dynamic array for each student
{
stuArray[i].stuScore = new float[numTests];
}
This is Literally all the code you need reference, this is not a bug its a syntax problem :)
Try delete[] stuArray[count].stuScore;
not delete[] stuArray[count].stuScore[j];
delete [] is made to delete an array allocated with new type[n]
You want to delete the pointer to the memory, not the actual memory.
You can delete delete[] stuArray[count].stuScore but not delete[] stuArray[count].stuScore[j] - drescherjm
Fixed using:
do
{
delete[] stuArray[count].stuScore;
count++;
} while (count < numTests);

Cannot convert string to const char/string* to int*

Firstly, I want to say that I'm a beginner. Sorry for my stupid questions.
My program should ask for the amount of words you want to put in. It's specifically said that this tab length is the length of pointers tab pointing to the words tab (may sound confusing, but English isn't my first language, my apologies, I also dont really understand pointers yet).
The words tab should also have exact length for each word, hence the strlen. What am I doing wrong?
int il,len;
string x;
cout<<"Amount of words: ";
cin>>il;
int **t;
t=new int*[il];
for(int i=0; i<il; i++)
{
cout<<"Word: ";
cin>>x;
len=strlen(x);
t[i]=new string[len];
cout<<endl;
}
cout<<"You wrote:"<<endl;
for(int i=0; i<il; i++)
{
cout<<t[i];
delete [] t[i];
}
delete[] t;
strlen() doesn't take a class string object but instead it takes a pointer to character string char*:
len = strlen(x); // error so correct it to:
len = x.length();
also you cannot initialize a pointer to an integers to class string:
int **t;
t[i]=new string[len];
you really want an array of strings but the code is really a mess so if you want this how:
int il;
cout << "Amount of words: ";
cin >> il;
string *t;
t = new string[il];
for(int i = 0; i < il; i++)
{
cout << "Word: ";
cin >> t[i]; // there's no need for a temporary string `x`; you can directly input the elements inside the loop
cout << endl;
}
cout << "You wrote: " << endl;
for( int i = 0; i < il; i++)
cout << t[i] << endl;
delete[] t;

How do I count words and lines that were input as a cstring array

This program should read a paragraph from a text file provided by the user and then store each line in a ragged char array and count the total number of words and lines of the paragraph then display the result.
I can't figure out why does the number of lines keep giving me the result of 3
and why the number of words is always missing 2 words.
please help and keep in mind that I'm no professional just started learning c++ recently.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
ifstream infile;//declarations
char filename[45];
char **data = 0;
char **temp = 0;
char *str = 0;
char buffer[500], c;
int numoflines = 0, numofwords = 0;
cout << "Please enter filename: ";//prompt user to enter filename
cin >> filename;
infile.open(filename);//open file
if (!infile)//check if file was successfully opened
{
cout << "File was not successfully opened" << endl << endl;//display error message
return 0;
} //end of if
data = new char*[numoflines];
while (!infile.eof())
{
temp = new char*[numoflines + 1];
for (int i = 0; i < numoflines; i++)
{
infile.getline(buffer, 500);//read line
for (int i = 0; i < strlen(buffer); i++)//count number of words in line
{
c = buffer[i];
if (isspace(c))
numofwords++;
}
str = new char[strlen(buffer) + 1];//allocate a dynamic array
strcpy(str, buffer);
data[i] = str;
temp[i] = data[i];
}//end of for
infile.getline(buffer, 500);
for (int i = 0; i < strlen(buffer); i++)//count number of words in line
{
c = buffer[i];
if (isspace(c))
numofwords++;
}
temp[numoflines] = new char[strlen(buffer) + 1];
strcpy(temp[numoflines], buffer);
delete[] data;
data = temp;
numoflines++;
}
cout << "Number of words: " << numofwords << endl;
cout << "Number of lines: " << numoflines << endl;
return 0;
}
The concept of number of lines is a viewing concept only. It's not encoded into the file. The following single paragraph can be displayed on one line or 16 lines depending upon the size of the editor window:
If you wanted to specify a char width of the window, lines could be calculated from that, but as is, paragraphs and wordcount are as good as you will do. And given a successfully opened ifstream infile that is fairly simple to obtain:
auto numoflines = 0;
auto numofwords = 0;
string paragraph;
while(getline(infile, paragraph)) {
numofwords += distance(istream_iterator<string>(istringstream(paragraph)), istream_iterator<string>());
++numoflines;
}
cout << "Number of words: " << numofwords << "\nNumber of lines: " << numoflines << endl;
NOTE:
Visual Studio supports inline construction of an istringstream so if you're not using that you'll need to construct on a separate line.

Returning a substring using c++ within a class

SO I have a substring function that takes in the start location of the substring and its length. With that it should extract the characters within and return them as a string, without actually using any string function.
//default constructor that sets the initial string to the value "Hello World"
MyString::MyString()
{
char temp[] = "Hello World";
int counter(0);
while(temp[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = temp[i];
}
//copy constructor
MyString::MyString(const MyString &source)
{
int counter(0);
while(source.String[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char[Size];
for(int i = 0; i < Size; i++)
String[i] = source.String[i];
}
Here is my substring function:
MyString MyString::Substring(int start, int length)
{
char* leo = new char[length+1];
for(int i = start; i < start + length+ 1; ++i)
{
leo[i-start] = String[i];
}
MyString sub;
delete [] sub.String;
sub.String = leo;
sub.Size = length+1;
return sub;
}
With this code from the main.cpp file:
int main (int argc, char **argv)
{
MyString String1; // String1 must be defined within the scope
const MyString ConstString("Target string"); //Test of alternate constructor
MyString SearchString; //Test of default constructor that should set "Hello World".
MyString TargetString (String1); //Test of copy constructor
cout << "Please enter two strings. ";
cout << "Each string needs to be shorter than 256 characters or terminated by /\n." << endl;
cout << "The first string will be searched to see whether it contains exactly the second string. " << endl;
cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator
if(SearchString.Find(TargetString) == -1) {
cout << TargetString << " is not in " << SearchString << endl;
}
else {
cout << TargetString << " is in " << SearchString << endl;
cout << "Details of the hit: " << endl;
cout << "Starting position of the hit: " << SearchString.Find(TargetString) << endl;
cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(TargetString), TargetString.Length()-1)<<"\n";
}
It returns:
Please enter two strings. Each string needs to be shorter than 256 characters or terminated by /
.
The first string will be searched to see whether it contains exactly the second string.
forever
more
morev World is not in forever
Any thoughts on why it actually isn't outputting the words from user input without the extra characters? I'm lost.
for(int i = start; i < length+1; i++)
This isn't working the way you want it to. It should be:
for (int i = start; i < start + length; ++i)
You have an off-by-one error, and your ending condition makes no sense once you realize what it's saying.
Take a substring starting at index 2, with length 5. The characters to be copied are at indices 2 to 6, which fits the condition.
Inside, though, you have another problem. Unless i starts at 0, you're not copying into the proper array indices. It should be:
sub [i - start] = String [i];
That way you'll start filling sub at index 0.
Also, once you're done, you need to null-terminate it:
sub [length] = '\0';
That way it won't run past the end.
You might consider using the std::copy algorithm:
MyString MyString::Substring(int start, int length)
{
char* sub;
sub = new char[length + 1];
sub[length] = '\0';
std::copy(String + start, String + start + length, sub);
return MyString(sub);
}
(I am assuming that String is some char * data member of MyString objects.)
MyString MyString::Substring(int start, int length)
{
char* sub;
sub = new char[length+1];
sub[length] = '\0';
int j = 0;
for(int i = start; i < start + length; ++i)
{
sub[j] = String[i];
++j;
}
return MyString(sub);
}
Something like this.