Segmentation fault during counting of elements in array of strings c++ - c++

I am trying to solve an old problem found on topcoder. I am immediately stuck in trying to find the number of elements in an array of strings. Here is my code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
class MiniPaint {
private:
size_t numLines;
public:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
numLines++;
}
cout << numLines << '\n';
return 0;
}
};
int main() {
MiniPaint instance;
string picture[] = {"BBBBBBBBBBBBBBB", "WWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWW", "WWWWWBBBBBWWWWW"};
instance.leastBad(picture, 10);
return 0;
}
This code gives me a segmentation fault. Something is going wrong, the code is a little bit excessive for just the functionality of counting the number of elements but of course I want to extend the class to include more functionality. If anyone can explain what is going wrong here I would be grateful! Thanks in advance.
EDIT: when I expand the code by
cout << picture[numlines] << '\n';
in the while loop, to show the actual elements in the array, first the four proper strings are shown and then somehow it endlessly prints spaces to the terminal. So the problem lies somewhere in the fact that
picture[4].empty()
does not return true, even though picture has only four elements.

Your while loop condition assumes that the last string in the array is empty:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
But your input string array defined in main() is not terminated with an empty "" string.
So you may want to add this empty string terminator:
// inside main()
string picture[] = {..., "" /* Empty string terminator */ };
In addition, in modern C++ I'd encourage you to use array container classes instead of raw C-style arrays, typically std::vector<std::string>.
In this case, you can use the size() method to get the array size (i.e. element count), or just a range-for loop for iterating through the whole array.

You access the array out of bounds.
When you call picture[4] you want to access a string object which is not there end the call to the function empty() is on uninitialized memory.
You either need to store how big the array is and iterate until numLines<=3 or you can use a vector
std::vector<std::string> picture = ...
for(std::string line : picture)
{
//do stuff
}

You are out of array bounds at picture[numLines]. You should pass array length or calculate it and check the index numLines. Code will look like:
size_t length = sizeof(picture) / sizeof(*picture); // For VS use _countof macro
while (numLines < length && !picture[numLines].empty())
{
++numLines;
}

Related

How to limit the maximum size of vector?

I am trying to use a limited-size buffer like a queue to put some numbers at the back until it gets to a specific size (e.g. 10) and then remove one element from front when a new element is added to the back.
I have used a vector for this purpose, but after several times of running the program (in debug mode) suddenly, I am getting heap corruption errors like:
Critical error detected c0000374
in the middle of the run, and I think it should be related to memory issues, because the error goes away when I reduce the number of vectors.
So far I just use a vector and put the new value to it each time. For example, suppose the code is like this:
#include <iostream>
using namespace std;
vector<int> myvec;
int i = 0;
int main()
{
while(True) {
myvec.push_back(i);
i++;
}
return 0;
}
How can I limit the size of myvec to 10, so that when it contains 10 elements and a new element is being added to it, the first element is removed from the memory?
Is it a good idea to use vectors here, or I should use a queue instead?
You can do something like this->
#include <iostream>
using namespace std;
vector<int> myvec;
int i = 0;
int main()
{
while(True) {
if(myvec.size()==10)
{
myvec.pop_back();
}
myvec.push_back(i);
i++;
}
return 0;
}

Returning a string * type array from a function back into the main

I'm new to C++ and I am working on a function to shuffle strings
It takes an array of strings, shuffles them, and returns them back to the main.
I am returning a pointer to an array of strings called shuffled. The problem I have is that when I try to save that new pointer to the array to another pointer in the main, I start getting weird values that either reference to a file location in my computer or a bunch of numbers.
I'll post the entire code here but really what you want to look at is the return types, how I return it and how I save it in main. Please tell me why my pointer is not referencing the working array that is created in the function. Here's the code:
#include <cstdio>
#include <string>
#include <ctime>
#include <new>
#include <cstdlib>
using namespace std;
const char * getString(const char * theStrings[], unsigned int stringNum)
{
return theStrings[stringNum];
}
string * shuffleStrings(string theStrings[])
{
int sz = 0;
while(!theStrings[sz].empty())
{
sz++;
}
sz--;
int randList[sz];
for(int p = 0; p < sz; p++)
{
randList[p] = sz;
}
srand(time(0));//seed randomizer to current time in seconds
bool ordered = true;
while(ordered)
{
int countNumberInRandList = 0;//avoid having a sz-1 member list length (weird error I was getting)
for(int i = 0; i < sz; i++)
{
int count = 0;
int randNum = rand()%(sz+1);//get random mod-based on size
for(int u = 0; u < sz; u++)
{
if(randList[u] != randNum)
{
count++;
}
}
if(count == sz)
{
randList[i] = randNum;
countNumberInRandList++;
}
else
i--;
}
//check to see if order is same
int count2 = 0;
for(int p = 0; p < sz; p++)
{
if(randList[p] == p)
{
count2++;
}
}
if(count2 < sz-(sz/2) && countNumberInRandList == sz)
{
ordered = false;
}
}
string * shuffled[sz];
for(int r = 0; r < sz; r++) //getting random num, and str list pointer from passed in stringlist and setting that value at shuffled [ random ].
{
int randVal = randList[r];
string * strListPointer = &theStrings[r];
shuffled[randVal] = strListPointer;
}
for(int i = 0; i < sz; i++)
{
printf("element %d is %s\n", i, shuffled[i]->c_str());//correct values in a random order.
}
return *shuffled;
}
int main()
{
string theSt[] = {"a", "b", "pocahontas","cashee","rawr", "okc", "mexican", "alfredo"};
string * shuff = shuffleStrings(theSt);//if looped, you will get wrong values
return 0;
}
Strings allocate their own memory, no need to give them the "length" like you would have to do for char arrays. There are several issues with your code - without going into the details, here are a few working/non-working examples that will hopefully help you:
using std::string;
// Returns a string by value
string s1() {
return "hello"; // This implicitly creates a std::string
}
// Also returns a string by value
string s2() {
string s = "how are you";
return s;
}
// Returns a pointer to a string - the caller is responsible for deleting
string* s3() {
string* s = new string;
*s = "this is a string";
return s;
}
// Does not work - do not use!
string* this_does_not_work() {
string s = "i am another string";
// Here we are returning a pointer to a locally allocated string.
// The string will be destroyed when this function returns, and the
// pointer will point at some random memory, not a string!
// Do not do this!
return &s;
}
int main() {
string v1 = s1();
// ...do things with v1...
string v2 = s2();
// ...do things with v2...
string* v3 = s3();
// ...do things with v3...
// We now own v3 and have to deallocate it!
delete v3;
}
There are a bunch of things wrong here -- don't panic, this is what happens to most people when they are first wrapping their brains around pointers and arrays in C and C++. But it means it's hard to put a finger on a single error and say "this is it". So I'll point out a few things.
(But advance warning: You ask about the pointer being returned to main, your code does indeed do something wrong with that, and I am about to say a bunch of things about what's wrong and how to do better. But that is not actually responsible for the errors you're seeing.)
So, in shuffleStrings you're making an array of pointers-to-string (string * shuffled[]). You're asking shuffleStrings to return a single pointer-to-string (string *). Can you see that these don't match?
In C and C++, you can't actually pass arrays around and return them from functions. The behaviour you get when you try tends to be confusing to newcomers. You'll need to understand it at some point, but for now I'll just say: you shouldn't actually be making shuffleStrings try to return an array.
There are two better approaches. The first is to use not an array but a vector, a container type that exists in C++ but not in C. You can pass arrays around by value, and they will get copied as required. If you made shuffleStrings return a vector<string*> (and made the other necessary changes in shuffleStrings and main to use vectors instead of arrays), that could work.
vector<string *> shuffleStrings(...) {
// ... (set things up) ...
vector<string *> shuffled(sz);
// ... (fill shuffled appropriately) ...
return shuffled;
}
But that is liable to be inefficient, because your program is then having to copy a load of stuff around. (It mightn't be so bad in this case, because a smallish array of pointers isn't very large and because C++ compilers are sometimes able to figure out what you're doing in cases like this and avoid the copying; the details aren't important right now.)
The other approach is to make the array not in shuffleStrings but in main; to pass a pointer to that array (or to its first element, which turns out to be kinda equivalent) into shuffleStrings; and to make shuffleStrings then modify the contents of the array.
void shuffleStrings(string * shuffled[], ...) {
// ... (set things up) ...
// ... (fill shuffled appropriately) ...
}
int main(...) {
// ...
string * shuffled[sz];
shuffleStrings(shuffled, theSt);
// output strings (main is probably a neater place for this
// than shuffleStrings)
}
Having said all this, the problems that are causing your symptoms lie elsewhere, inside shuffleStrings -- after all, main in your code never actually uses the pointer it gets back from shuffleStrings.
So what's actually wrong? I haven't figured out exactly what your shuffling code is trying to do, but that is where I bet the problem lies. You are making this array of pointers-to-string, and then you are filling in some of its elements -- the ones corresponding to numbers in randList. But if the numbers in randList don't cover the full range of valid indices in shuffled, you will leave some of those pointers uninitialized, and they might point absolutely anywhere, and then asking for their c_strs could give you all kinds of nonsense. I expect that's where the problem lies.
Your problem has nothing to do with any of the stuff you are saying. As you are a beginner I would suggest not presuming that your code is correct. Instead I would suggest removing parts that are not believed to be problematic until you have nothing left but the problem.
If you do this, you should quickly discover that you are writing to invalid memory.
part two : you can't seem to decide on the type of what you are returning. Are you building a pointer to an array to return or are you returning an array of pointers.... you seem to switch between these intermittently.
part three : read #Gareth's answer, he explains about passing parameters around nicely for your instance.

Why does printing a string array output hexadecimal?

Why does the following program print "0x2ffee4" to the console?
#include <string>
#include <iostream>
using namespace std;
int main() {
string city1[] = "toronto";
cout << city1;
return 0;
}
The first line shouldn't compile, but there's a GCC bug that makes it compile and behave equivalently to something like
std::string city1[] = {"toronto", "toronto", "toronto", "toronto",
"toronto", "toronto", "toronto", "toronto"};
(8, because "toronto" is 8 characters including the terminating null. Yes, that means that if you used "Chargoggagoggmanchauggagoggchaubunagungamaugg", it would create an array of 46 strings, each storing "Chargoggagoggmanchauggagoggchaubunagungamaugg".)
Needless to say, you shouldn't rely on a compiler bug.
Under GCC's buggy behavior, city1 would be an array of std::strings; there's no operator << overload that support printing such a thing. Instead, in std::cout << city1, the array decays to a pointer to its first element, and the address stored in the pointer is printed instead.
You probably meant to write std::string city1 = "toronto";. One string, not an array of it.
The answer given by T.C. is correct, I would also like to mention that if you was expecting to print out "toronto" to the console using cout then you would want to do this:
include <string>
include <iostream>
int main() {
using namespace std;
// string city1[] = "toronto"; // Compiler Error - Do Next Line Instead
string city1[] = { "toronto" };
cout << city1[0];
return 0;
}
Any time you want to initialize an array of any type during declaration you need to use = { }; To set each array's element separated by commas. Look at this code sample:
#include <string>
#include <iostream>
int main() {
using namespace std;
string cities[] = { "New York", "Philadelphia", "Chicago", "Boston" };
// Same As Above Except Size Of Array Is Defined First Then The Elements
string cities[4];
cities[0] = "New York";
cities[1] = "Philadelphia";
cities[2] = "Chicago";
cities[3] = "Boston";
unsigned index = 0;
for ( ; index < 4; index++ ) {
cout << cities[index] << endl;
}
return 0;
}
If you are not initializing the array when declaring it then you must specify the array's size.
int main() {
int iArray[]; // Compiler Error
int iArray[] = { 4, 3, 2, 1, 6 }; // Okay and is the same as
int iArray[5]; // Okay
iArray[0] = 4;
iArray[1] = 3;
iArray[2] = 2;
iArray[3] = 1;
iArray[4] = 6;
return 0;
}
If you are not using the bracket operator with an index value to send to the console output stream std::cout then the hex value you are getting is correct as
T.C had already stated; it is returning the address of the first index. This is why in c / c++ arrays and pointers are similar (they are not the same, but behave almost like one another). The main difference with arrays is that they are constant in size, the size has to be known at compile time, and can not be dynamically changed in size without having to store the contents into a temp variable while creating a new array with a larger size then copying all the data into the new array and then cleaning up the old array. With pointers they do not behave this way, pointers can be dynamically allocated on the heap using new, but also must be deleted when that variable has no more use to prevent memory leaks, if the pointer is delete before hand and something tries to access it that memory address is no longer valid and doesn't belong to the caller, these are normally seen as unhandled exceptions, heap corruption, etc. and will crash your program. The same goes for arrays when you try to index them past their bounds.
#include <iostream>
int main() {
// Arrays Are 0 Indexed
int iArray[3] = { 1, 2, 3 };
// If you try to do this to access the last element
std::cout << iArray[3] << std::endl; // Program Will Crash
// Since Arrays Are 0 Indexed And The Size Of The Array Is 3
// The 3rd Value Is Indexed At 2, And By Trying To Index Location Of Array
// At 3, This Memory Doesn't Belong To You, And It Is Undefined Behavior.
// This Memory Could Contain Nothing, Random Data, Or Even Data That Belongs To
// Something Else Which If Changed Can Even Cause System Failure
return 0;
}

Read File then Create Array Function C++

I am new to C++ and lately I was having trouble reading a file. That problem is now fixed. What I'd like to do now is to use the file I read to create an array, but all this has to be done in a function, this means the function has to return an array so I can use it on the main. The process I follow:
Read File
Create Array
Return Array Adress.
In the main: Use function to put an array in a variable.
My code so far:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
void imprimeArreglo (int[],int);
int* leeArreglo(string&);
int i;
void imprimeArreglo(int a[])
{
cout << a[i] << endl;
}
int* leeArreglo(string nombre)
{
ifstream arch(nombre.c_str());
string tamStr;
int tam;
if(arch.is_open())
{
getline(arch,tamStr);
tam=atoi(tamStr.c_str());
int arr[tam];
for(int i=0;i<tam;i++)
{
arch >> arr[i];
}
int *ret=arr;
return ret;
}
return 0;
}
int main()
{
string nombre = "arr.txt";
int *a= leeArreglo(nombre.c_str());
imprimeArreglo(a);
return 0;
}
What my arr.txt file looks like:
10
9 8 22 33 76 0 23 100 -8 45
I think this should print (with imprimeArreglo(a)):
9 8 22 33 76 0 23 100 -8 45
But the only thing I get in the console is:
2292592 Which I think it's a memory adress??? What am I doing wrong? Is there a better way to do it without using vectors?
Thanks in advance!
This would be a simple way of doing it:
#include <iterator>
#include <vector>
#include <fstream>
std::vector<int> fileContents(const std::string& filename)
{
ifstream inputFile(filename.c_ctr());
std::istream_iterator<int> end;
std::istream_iterator<int> it(inputFile);
return std::vector<int>(it, end);
}
This reads all the numbers into a vector. You may have to modify it to ignore the first 10, for example by calling std::advance(it, 1); just after initializing it.
You are returning a reference to a local variable. When your function go out of scope the array arr is freed and therefore the address return is just garbage.
If you want to return an address that lives after the function is called, do something like:
int *arr = new int[tam];
Then the address will be valid after the function is called but in terms of design this is not great as you leave the responsibility to free the array on the caller.
I would personally wrap all of this in a class and and have the array member of it.
Ok after some research and consulting, I got the answer! Thank you everyone for helping me :). This is the code that made the things happens (USING ARRAYS!!)
int* readArray(string name)
{
ifstream fil(name.c_str());
string sizeStr;
int size;
if(fil.is_open())
{
getline(fil,sizeStr);
size=atoi(sizeStr.c_str());
int* arr = new int[size+1];
for(int i=1;i<size+1;i++)
{
fil >> arr[i];
}
//We stash the size in the first position ;)
arr[0]=size;
//cout << arr[0]<< "\n";
//We point to the position of the array + 1. (The 0 pos is used for the size)
int *ret=arr+1;
return ret;
delete[] ret;
}
else cout << "ERROR...!\n";
return 0;
}
As you can see my function returns a pointer. And I delete it. (Still need to see if that delete[] is well positioned tho.)
Also since what I return is a pointer I can't really know what the size of my array is using sizeof(arr)/sizeof(int). So what I did is to save it into a position of the array, that way I can call it whenever I want by using array[-1].
Thank you all again!

Modifying a recursive string reverse function

I am doing some recursive exercises. The previous one was to make a reverse() function for a string which basically removes the first character and then combines the solution. I managed to do that, here is the source code (the entire source) The current task is to modify this function (the following exercise in the book) by adding a helper function which reverses a substring of the string. At this moment I am stuck at this. It is my understanding that you use helper functions when you need to pass additional arguments or something and this function takes none so I really have no idea how to approach this problem. Help appreciated.
#include <iostream>
#include <string>
using namespace std;
void reverse(string& text)
{
if (text.length() == 0)
{
return;
}
if (text.length() == 1)
{
return;
}
else
{
string firstLetter = text.substr(0,1);
text = text.substr(1, text.length()-1);
reverse(text);
text += firstLetter;
}
}
int main()
{
string a = "tyu";
reverse(a);
cout << a << endl;
return 0;
}
A guy suggested to use parameters, ect, this is my try with it:
#include <iostream>
#include <string>
using namespace std;
//is actually doing the hard work
void reverse1(string& input, int a, int b)
{
// base case
if( a >= b)
{
return;
}
//swap the characters
char tmp;
tmp = input[a];
input[a] = input[b];
input[b] = tmp;
//create the boundries for the new substring
a++;
b--;
//call the function again
reverse1(input, a, b);
}
// sets the parameters and calls the helper function
void strreverse(string& input)
{
reverse1(input, 0, input.length()-1);
}
int main()
{
cout << "Please enter the string which you want to be reversed:";
string a;
cin >> a;
strreverse(a);
cout << a << endl;
return 0;
}
The goal is probably to avoid creating all of the intermediate substrings. The helper function will take iterators, or a start and end index in addition to the string begin reversed.
Try to implement reversing so that there is only one instance of std::string (i.e. work with it as with an array). Then you will need a helper function with additional parameters (at least one parameter - which index to reverse now).
I would implement reverse here as series of exchanges: a[0] <-> a[n-1], a[1] <-> a[n-2] etc. where n is length of the string.
You can define a helper function that takes a start and an end index of the substring which it will reverse.
The function should exchange the element at the start index with that at the end index IFF the difference between the start and the end indices is 1. Otherwise, it places a recursive call to itself by decrementing the end index and incrementing the start index. You will need to keep check on the condition if the start and end index become same though.