I have this piece of code that puts a random string in an char pointer array:
char * str[100] = {0};
const int elems = sizeof(str)/sizeof(str[0]),size=5;
srand(time(0));
for(int i=0;i<elems;i++){
char rString[size] = {0};
for(int j = 0;j<size;j++){
rString[j] = 97+rand()%26;
}
rString[size] = '\0';
str[i] = new char[size];
strcpy(str[i],rString);
}
for(int i=0;i<elems;i++){
cout<<str[i]<<endl;
}
But str[0] is polluted or empty.
Your rString[size] = '\0'; writes to an element out of bounds! The last element is rString[size-1]. Anything after this will be undefined behaviour.
To fix this (but keeping 5-character strings), you need to increase size to 6 and change your loop limits and null-terminator index, as follows:
int main()
{
char* str[100] = { 0 };
const int elems = sizeof(str) / sizeof(str[0]), size = 6; // Add space for nul-terminator
srand(time(0));
for (int i = 0; i < elems; i++) {
char rString[size] = { 0 };
for (int j = 0; j < size-1; j++) { // End BEFORE last character
rString[j] = 97 + rand() % 26;
}
rString[size-1] = '\0'; // Last element is at [size-1] NOT [size]
str[i] = new char[size];
strcpy(str[i], rString);
}
for (int i = 0; i < elems; i++) {
std::cout << str[i] << std::endl;
}
// And, for good measure, don't forget to free the allocated strings:
for (int i = 0; i < elems; i++) {
delete[] str[i];
}
return 0;
}
Alternatively (if you insist on using raw pointers and C-style strings), you can just change your rString declaration and str[i] allocation lines to use size+1 (less typing):
//...
char rString[size+1] = { 0 };
//...
str[i] = new char[size+1];
But you really should consider using more modern C++ techniques, like std::string and std::vector, in place of your dynamic arrays. Here's a version using those STL containers:
int main()
{
std::vector<std::string> str(100);
const int elems = str.size(), size = 5;
srand(time(0));
for (int i = 0; i < elems; i++) {
std::string rString {""};
for (int j = 0; j < size; j++) {
rString += static_cast<char>(97 + rand() % 26);
}
str[i] = rString;
}
for (int i = 0; i < elems; i++) {
std::cout << str[i] << std::endl;
}
return 0;
}
Feel free to ask for further clarification and/or explanation.
Related
int vorkommen(const char* s, const char* m) {
int lengthS = 0;
int lengthM = 0;
while (s[lengthS] != '\0') {
lengthS++;
}
while (m[lengthM] != '\0') {
lengthM++;
}
char textS[lengthS - 1];
char textM[lengthM - 1];
for(int i = 0; i < lengthS; i++) {
textS[i] = s[0];
s++;
}
for(int i = 0; i < lengthM; i++) {
textM[i] = m[0];
m++;
}
int match = 0;
for(int i = 0; i < lengthS; i++) {
for(int j = 0; j <= lengthM; j++) {
if(j == lengthM) {
match++;
} else if(textS[i + j] != textM[j]) {
break;
}
}
}
return match;
}
void Aufgabe_7() {
char first[256];
char second[256];
cin.getline(first, sizeof(first));
cin.getline(second, sizeof(second));
int test = vorkommen(first, second);
cout << test;
}
int main() {
Aufgabe_7();
return 0;
}
You see here a program which only task is it, to read in two texts and compare how often the text of the second char pointer is contained in the first char pointer.
For that I wrote this little program, it works and all but if the second char pointer contains only 1 letter the output of textS[0] is always equals to textM[0].
I have written a class with char** class field(which is dynamic 2d array) named visa(basically i want there to be countries which a person has visited) and countriesVisited(in fact size of the array). I intentionally didn't use strings. I've added a class method, which adds countries to the mentioned array, but when i try to delete the array elements i get HEAP CORRUPTION detected: after Normal block (#158):
void ForeignPassport::addCountry(const char* country) {
char** tmp = new char* [countriesVisited + 1];
for (int i = 0; i < countriesVisited+1; i++) {
tmp[i] = new char[strlen(country)];
}
for (int i = 0; i < countriesVisited; i++) {
int f = 0;
while (visa[i][f-1] != '\0') {
tmp[i][f] = visa[i][f];
f++;
}
}
for (int i = 0; i <= strlen(country); i++) {
if (i == strlen(country)) {
tmp[countriesVisited][i] = '\0';
break;
}
tmp[countriesVisited][i] = country[i];
}
countriesVisited++;
for (int i = 0; i < countriesVisited-1; i++) {
delete[]visa[i];
}
visa = tmp ;
}
tmp[i] = new char[strlen(country)];
here you are allocating memory in amounts of strlen(country)
but in this loop:
for (int i = 0; i <= strlen(country); i++) {
if (i == strlen(country)) {
tmp[countriesVisited][i] = '\0';
break;
}
tmp[countriesVisited][i] = country[i];
}
here you are accessing to the memory which is not allocated and this not allowed,
so change the condition to i < strlen(country)
emphasized textThe task is to write an insertion sort with string comparison function. I have done this and my code is working on the small cases. However, it fails to perform successfully in the online problem checker quitting with "Memmory Limit" verdict. What are your recommendations to optimize memory usage?
UPD I have figured out that I do the wrong thing. I should sort an array of pointers to the strings rather than strings themselves to avoid copying like this:
arr[j + 1] = arr[j];
However, due to my little knowledge of pointers I fail to understand how to do it correctly. What are your suggestions?
I have already done the following:
use C-style strings of the fixed (255 chars) size which is given in the statement
sort an array of pointers to these strings
pass string to the comparison function less by pointer.
Here is my source code:
#include <cstdio>
const int kMaxStringSize = 200;
bool less(char **s1, char **s2) {
int i = 0;
while ((*s1)[i] == (*s2)[i]) {
if ((*s1)[i] == '\0' || (*s2)[i] == '\0') {
break;
}
i++;
}
if ((*s1)[i] != '\0') {
if ((*s1)[i] < (*s2)[i]) {
return true;
} else {
return false;
}
} else {
if ((*s2)[i] != '\0') {
return true;
} else {
return false;
}
}
}
int main() {
int n;
std::scanf("%d\n", &n);
char **arr;
arr = new char*[n];
for (int i = 0; i < n; i++) {
char *temp = new char[kMaxStringSize];
fgets(temp, 256, stdin);
arr[i] = temp;
}
for (int i = 1; i < n; ++i) {
int j = i - 1;
char *temp = arr[i];
for ( ; (j >= 0) && less(&temp, &arr[j]); --j) {
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
for (int i = 0; i < n; i++) {
printf("%s", arr[i]);
}
for (int i = 0; i < n; i++) {
delete[] arr[i];
}
delete []arr;
return 0;
}
Each string is using the maximum space available, however maybe only needing a few characters.
char temp[257] = '\0'; // bigger than given to fgets
for (int i = 0; i < n; i++) {
fgets(temp, 256, stdin);
char * t = new char[ strlen( temp ) + 1];
strcpy( t, temp );
arr[i] = t;
}
I designed a dynamic array with an update function that deep copies the contents of the original into a temp array, then doubles the size then puts the contents of temp array into the new one.
This is the function:
T& operator[](const unsigned i)
{
if(i >= SIZE)
{
T *temp = new T[SIZE];
for(int i = 0; i< SIZE; ++i)
{
temp[i]=data[i];
}
delete[] data;
SIZE *= 2;
data = new T[SIZE];
for(int j = 0; j< SIZE; ++j)
{
data[j]=temp[j];
}
delete[] temp;
}
return data[i];
};
This function works with all data types except strings like:
Vector<string> s;
string str1 = "1";
string str2 = "2";
s[0] = str1;
s[1] = str2;
cout<< s[0]<< s[1]<< '\n';
However with ints for example:
Vector<int> in;
for(i = 0; i < 11; i++){
in[i] = i;
}
for(i = 0; i < 11; i++){
cout<< "int test"<< '\n';
cout<< in[i]<< '\n';
}
The update works perfectly fine.
anyone of you know why?
Thank you.
I have a huge array of unsigned chars (called main_data) containing some data, which is being refreshed once in a while. I would like to create an array (called plot_data) of pointers to every n-th element of main_data. The idea is to upload new data to main_data from external source and to have reduced plot_data automatically available for my plot. Here is my closest try (it is written in Managed C++, VC++ 2010, WinForms project):
int mainDataSize = 64;
int plotDataSize = 8;
unsigned char* main_data = new unsigned char[mainDataSize];
for (int i = 0; i < mainDataSize; i++) {
main_data[i] = 2 * (i % 32);
}
unsigned char* plot_data = new unsigned char[plotDataSize];
for (int i = 0; i < plotDataSize; i++) {
int idx = (int)(mainDataSize / plotDataSize * i);
plot_data[i] = main_data[idx];
}
printf("Original data:\n");
for (int i = 0; i < mainDataSize; i++) {
printf("%d ", main_data[i]);
}
printf("\n\nData for plot:\n");
for (int i = 0; i < plotDataSize; i++) {
printf("%d ", plot_data[i]);
}
Then, after modification of main_data, I would expect that printing array of pointers would give me modified values. Here is the code for modification and printing:
for (int i = 0; i < mainDataSize; i++) {
main_data[i] = i;
}
printf("\n\nChange made - Main data:\n");
for (int i = 0; i < mainDataSize; i++) {
printf("%d ", main_data[i]);
}
printf("\n\nChange made - Plot data:\n");
for (int i = 0; i < plotDataSize; i++) {
printf("%d ", plot_data[i]);
}
I have been trying to fix this for few hours and it seems I don't get something, which should be relatively simple. Please, help me to understand my mistake.
I would like to create an array (called plot_data) of pointers
The code you posted does not create an array of pointers. It creates a dynamic array of unsigned char's.
If you want to create an array of pointers:
unsigned char** plot_data = new unsigned char*[plotDataSize];
Then in the loop:
plot_data[i] = main_data + idx;
Note this is bad code because there are memory leaks everywhere
I also recommend you use std::vector, as your code will leak memory if the proper calls to delete[] are not done.
#include <vector>
//...
std::vector<unsigned char> main_data(mainDataSize);
//...
std::vector<unsigned char*> plot_data(plotDataSize);
The leaks are now gone.
You are creating an array of chars, not an array of char *'s. You need to change your code to use an array of pointers:
int main()
{
int mainDataSize = 64;
int plotDataSize = 8;
unsigned char ** main_data = new unsigned char * [mainDataSize];
for (int i = 0; i < mainDataSize; i++) {
main_data[i] = new unsigned char(2 * (i % 32));
}
unsigned char ** plot_data = new unsigned char * [plotDataSize];
for (int i = 0; i < plotDataSize; i++) {
int idx = (int)(mainDataSize / plotDataSize * i);
plot_data[i] = main_data[idx];
}
printf("Original data:\n");
for (int i = 0; i < mainDataSize; i++) {
printf("%d ", *main_data[i]);
}
printf("\n\nData for plot:\n");
for (int i = 0; i < plotDataSize; i++) {
printf("%d ", *plot_data[i]);
}
for (int i = 0; i < mainDataSize; i++) {
*main_data[i] = i;
}
printf("\n\nChange made - Main data:\n");
for (int i = 0; i < mainDataSize; i++) {
printf("%d ", *main_data[i]);
}
printf("\n\nChange made - Plot data:\n");
for (int i = 0; i < plotDataSize; i++) {
printf("%d ", *plot_data[i]);
}
for (int i = 0; i < mainDataSize; i++) {
delete main_data[i];
}
delete[] main_data;
delete[] plot_data;
return 0;
}