c++ Expression: string subscript out of range - c++

When I try debugging the code, it runs into the debugging error "c++ Expression: string subscript out of range"
Pretty sure the problem was brought while calling setCode().
How do I fix the code inside setCode()?
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[digit] = other.code[digit];
}
//set up the private values
void setCode(const string &temp, const int num);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, int num)
{
code[num] = temp[num];
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
aisbn.setCode(contents, count);
aisbn.setDigit(count);
simul.push_back(aisbn);
count++;
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}

When you create an instance of the test class, the string inside it is empty. This means that whenever you do e.g. code[something] you will be out of range. It doesn't matter what the index is.
You either need to set the string to a certain length from the start, and make sure that the index is within the range. Or to make sure that the index is within range by dynamically extending the string when needed.

You have to make sure that when this statement executes:
code[num] = temp[num];
both code and temp are at least of size num + 1.

Related

StringBuilder Class in C++ not working properly

I'm working on an assignment to create a class called StringBuilder that is used for fast string concatenation. I'm supposed to store strings in a dynamic array and have methods such as Append(string) which adds a new string to the dynamic array. The method I'm currently struggling with is GetString() that creates a single string on the heap that is the length of all the strings in the dynamic array that have been added thus far.
the code I have so far is:
okay my main problem is my GetString() function prints out hello over and over again until I force quit the program in Xcode. I don't understand what inside that method is making that happen.
My header file:
#pragma once
#include <string>
using namespace std;
class StringBuilder
{
public:
StringBuilder();
//~StringBuilder();
void GetString();
void AppendAll(string*, int);
void Length();
void Clear();
void Append(string userString);
void DoubleArray(string*& allWords, int newCapacity);
private:
string* p_array;
int capacity = 5;
};
my .cpp file :
#include "StringBuilder.hpp"
#include <iostream>
#include <string>
using namespace std;
----------
void StringBuilder::Append(string userString)
{
int nextWordPosition = 0;
for(int i=0; i < capacity ; i++)
{
p_array[i] = userString;
cout << p_array[i] << endl;
nextWordPosition +=1;
if(capacity == nextWordPosition)
{
capacity *=2;
DoubleArray(p_array, capacity * 2);
}
}
nextWordPosition++;
}
void StringBuilder::DoubleArray(string*& allWords, int newCapacity)
{
string* p_temp = new string[newCapacity];
for(int i =0; i < newCapacity / 2; i++)
{
p_temp[i] = allWords[i];
}
delete[] allWords;
allWords = p_temp;
}
void StringBuilder:: GetString()
{
for(int i=0; i < capacity ; i++)
{
cout << p_array[i]<< endl;
}
}
my main.cpp file :
#include <iostream>
#include <string>
#include "StringBuilder.hpp"
using namespace std;
int main()
{
string testString = "hello";
string test = "world!";
StringBuilder Builder1;
Builder1.Append(testString);
Builder1.Append(test);
Builder1.GetString();
return 0;
}

How come when I type a large number the output just repeats itself over and over? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
How come when I type a large number the output just repeasts itself over and over?
#include "stack.h"
#include <string>
#include <sstream>
#include <math.h>
using namespace std;
void convertBinaryToDecimal(string num, MyStack<int>& thestack);
int main() {
MyStack<int> thestack;
int input = -22222;
while (true) {
cout << "enter -999 to quit, Enter your binarty number: ";
cin >> input;
if (input == -999) {
cout << "Thank you, see you next time." << endl;
system("Pause");
break;
}
else {
string str = to_string(input);
convertBinaryToDecimal(str, thestack);
}
}
}
void convertBinaryToDecimal(string num, MyStack<int>& thestack) {
int remainder = 0;
int count = 0;
int dec_value = 0;
int n;
stringstream number(num);
number >> n;
while (n != 0) {
remainder = n % 10;
n /= 10;
dec_value += remainder * pow(2, count);
count++;
}
thestack.push(dec_value);
int value = thestack.top();
thestack.pop();
cout << "The equivalent decimal number is: " << value << endl;
}
.cpp file^
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
template<class Type>
class MyStack {
public:
int count;
MyStack(int mysize = 100) {
list = new int[mysize];
maxStackSize = mysize;
stackTop = 0;
count = 0;
}
MyStack(const MyStack<Type>& thestack) {
copyStack(thestack);
}
~MyStack() {
delete[] list;
}
void initializeStack();
bool isEmptyStack() const;
bool isFullStack() const;
Type push(const Type& newItem);
Type top()const;
void pop();
const MyStack<Type>& operator=(const MyStack<Type>& thestack) {
copyStack(thestack);
return *(this);
}
private:
int maxStackSize;
int stackTop;
Type* list;
void copyStack(const MyStack<Type>&);
};
template<class Type>
void MyStack<Type>::initializeStack() {
stackTop = 0;
}
template<class Type>
bool MyStack<Type>::isEmptyStack() const {
return (stackTop == 0);
}
template<class Type>
bool MyStack<Type>::isFullStack() const {
return (stackTop == maxStackSize);
}
template<class Type>
Type MyStack<Type>::push(const Type& newItem) {
if (isFullStack()) {
return NULL;
}
list[stackTop] = newItem;
stackTop++;
return list[stackTop - 1];
}
template<class Type>
Type MyStack<Type>::top()const {
if (isEmptyStack()) {
return NULL;
}
return list[stackTop - 1];
}
template<class Type>
void MyStack<Type>::pop() {
if (isEmptyStack()) {
}
else {
stackTop--;
}
}
template<class Type>
void MyStack<Type>::copyStack(const MyStack<Type>& thestack) {
delete[] list;
list = new Type[thestack.maxStackSize];
for (int i = 0; i < thestack.maxStackSize; i++) {
list[i] = thestack.list[i];
}
stackTop = thestack.stackTop;
maxStackSize = thestack.maxStackSize;
}
#endif//STACK_H_INCLUDED
header file^
When I type a large binary like "101010100100101010" the output repeats itself over and over. When I type a smaller binary like "1010" it's fine and gives me the correct output.
Any ideas? I am pretty sure it just crashes.
Edit: I've been testing it and it breaks after 10 digits.
Hm. I think the main problem ist that you are reading the binary number from a user into an int variable. So, if the the user enters 1000, you expect it to be 8, but in reality it is 1000(decimal). Then you convert 1000(decimal) into a string, which is then "1000". That is of course not good and one cause of your problem.
Integer variables can hold values up to a given boundary. You can find out in C++ using
#include <limits>
#include <iostream>
int main()
{
std::cout << std::numeric_limits<int>::max() << "\n";
return 0;
}
The result is machine dependent. A possible value is on a 32bit hardware is: 2147483647
So, now you enter a big string of '1's and '0's, e.g. "101010100100101010" And you expect to read a binary. But you try to put it in an integer. But the decimal number 101010100100101010 will not fit into an integer and so your complete intended functionality will not work as you expect.
The solution is to read the value from the user into a std::string and not into an int
Then you can convert the binary data in the std::string into a decimal.
For that you can use existing build in functions like:
#include <string>
#include <iostream>
int main()
{
const std::string testBinary{"101010100100101010"};
std::cout << std::stoul(testBinary,0,2) << "\n";
return 0;
}
Or a simple conversion with iterating through the string:
#include <string>
#include <iostream>
#include <algorithm>
int main()
{
const std::string testBinary{"101010100100101010"};
unsigned long decimalValue{0};
std::for_each(testBinary.rbegin(),testBinary.rend(), [&decimalValue] (const char& c) { decimalValue |= (c-'0'); decimalValue <<= 1; });
std::cout << decimalValue << "\n";
return 0;
}
The stack is not needed at all for this functionality. I am not sure, why you put it in. Maybe for academic purposes.
By the way, you can check for the correctness of a "binary string" with
if (std::all_of(testBinary.begin(), testBinary.end(), [](const char& c){ return c=='1' || c=='0';}))

Console keeps printing hexadecimal instead of contents in the array

I'm trying to create an array of size 100 filled with 0's. When I go to print out the area what prints is: 0x7fff5fbff54c. It seems to be printing out the address of the area and I am not sure why and how I should fix this so that it prints out what it is supposed to. Below is my code.
List.hpp
typedef int ElementType;
const int MAX = 100;
class List
{
public:
List();
bool Empty();
void InsertAtEnd(ElementType x);
void Delete(ElementType x);
void Display();
int Smallest();
int Largest();
int Range();
private:
int N;
ElementType listArray[MAX];
};
List.cpp
#include "List.hpp"
#include <iostream>
using namespace std;
List::List() {
listArray[99] = {0};
}
void List::Display() {
cout << listArray;
}
main.cpp
#include "List.hpp"
#include <iostream>
using namespace std;
int main() {
List list;
list.Display();
return 0;
}
That is because listArray is a pointer, you are printing the address of the pointer.. If you want to print the content you need to write a loop that will iterate through each element and print the values.
something like:
for (int i=0; i< MAX; ++i)
{
cout << listArray[i] << ", ";
}
cout << endl;
#πάνταῥεῖ is correct. Try this instead:
class List
{
public:
List();
bool Empty();
void InsertAtEnd(ElementType x);
void Delete(ElementType x);
void Display();
int Smallest();
int Largest();
int Range();
private:
int N;
ElementType listArray[MAX] = {0};
};
And remove the initialization from your constructor
Wouldn't you want a loop:
see this previous question:
loop through an array in c++
The code you have
List::List() {
listArray[99] = {0};
}
Just initializes the value of your listArray at index 99.
To initialize your array with all values as 0 you need to use the constructors initializer list:
List::List() : listArray {0} {
}

Fail to store values to the list

It seems the attribute test aisbn is successfully storing the data invoking setCode(), setDigit(). But The trouble starts failing while I attempt these values to store into list<test> simul
The list attribute takes the value of digit after setDigit() but the code. How can I put both code and digit into the list attribute? I can't see where the problem is. The code:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[i] = other.code[i];
}
//set up the private values
void setCode(const string &temp, const int num);
void setCode(const string &temp);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, const int num)
{
if((int)code.size() <= num)
{
code.resize(num+1);
}
code[num] = temp[num];
}
void test::setCode(const string &temp)
{
code = temp;
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
const string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
cout << contents << '\n';
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
It looks like you are having issues with your for loop, you need to modify your for loop like so:
for(testitr = simul.begin(); testitr !=simul.end(); testitr++)
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
although, push_back does not invalidate iterators for std::list I think it is more readable to set the iterator where you are using it. Based on your response you also need to modify the copy constructor:
test(const test &other): code(other.code), digit(other.digit) {}
^^^^^^^^^^^^^^^^
how about using the vector
std::vector<test> simul;
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
iterators, pointers and references related to the container are invalidated.
Otherwise, only the last iterator is invalidated.

c++ reference to function pointer dynamically

I have one application in which following task are to be done
1.) UI application will send command code (integer value).
2.) DLL interface(in c++) will get that integer value and execute corresponding command function.
commands name and command code are maintained as
#define PING 50
there will be 500 commands and applying SWITCH CASE will not sound good. so i decided to implement function pointer in my code as below
#include "stdafx.h"
#include<iostream>
#define PING 20
using namespace std;
//extern const int PING = 10;
void ping()
{
cout<<"ping command executed";
}
void get_status(void)
{
cout<<"Get_status called"<<endl;
}
class ToDoCommands
{
public:
void getCommand( void (*CommandToCall)() );
};
void ToDoCommands::getCommand( void (*CommandToCall)())
{
void (*CommandToCall1)();
CommandToCall1 = CommandToCall;
CommandToCall1();
}
int main()
{
int code;
ToDoCommands obj;
cout<<"enter command code";
cin>>code; // if UI send 50 then Ping function get executed as #define PING 50
obj.getCommand(ping); // here m passing ping manually..
//obj.getCommand(get_status);
return 0;
}
how can i pass command name corresponding to command code in
obj.getCommand(ping);
You are almost there: make a std::map of std::string to function pointer, initialize it with data pairing a string name to a corresponding function pointer, and then use that map at runtime to pick the correct pointer based on the string parameter passed in.
#include <iostream>
#include <string>
#include <map>
using namespace std;
void ping() {
cout << "ping" << endl;
}
void test() {
cout << "test" << endl;
}
int main() {
map<string,void(*)()> m;
m["ping"] = ping;
m["test"] = test;
// I am using hard-coded constants below.
// In your case, strings will come from command line args
m["test"]();
m["ping"]();
return 0;
}
Link to a demo with std::map.
Here is how you can do it without a map (it will be slower because of the linear search, but you can fix it by ordering names alphabetically and using binary search).
#include <iostream>
#include <cstring>
using namespace std;
void ping() {
cout << "ping" << endl;
}
void test() {
cout << "test" << endl;
}
typedef void (*fptr_t)();
int main() {
const fptr_t fptrs[] = {test, ping};
const char *names[] = {"test", "ping"};
const char *fname = "test";
for (int i = 0 ; i != 2 ; i++) {
if (!strcmp(fname, names[i])) {
fptrs[i]();
break;
}
}
return 0;
}
Link to a demo with arrays.
Declare an array of function pointers. Where you treat the index as your "code". For example:
void foo(){
printf("foo\n");
}
void bar(){
printf("bar\n");
}
int main(void)
{
void (*code_to_function[100])();
int code;
code_to_function[0] = foo;
code_to_function[1] = bar;
printf("Enter code: ");
scanf("%d", &code);
code_to_function[code]();
return 0;
}
Please note that for this rudimentary example, inputting integer code other than 0 and 1 will result in a segfault.
I should say #dasblinkenlight is right but if you don't want to use std::map you should implement a map yourself. This can be buggy and not a optimized way, but if you don't want to use STL, it seems you should implement it yourself.
You can use 2 arrays with corresponding indices. One of them is a char * array and another one is function pointers. They are better to be encapsulated in a class named something like MyMap.
class MyMap {
public:
...
inline void add(char *name, (void (*ptr)(void)) ) {
names_[currIndex_] = name; // Or stcpy
ptrs_[currIndex_] = ptr;
currIndex_++;
}
inline (void(*)(void)) get(char *name) {
int foundIndex = -1;
for (int i = 0; i < currIndex_; i++) {
// Find matching index
}
if (foundIndex_ >= 0) {
return ptrs_[foundIndex_];
}
return NULL;
}
private:
int currIndex_;
char *names_[10];
(void (*ptrs_[10])(void));
};