Recieving "string subscript out of range" error - c++

Doing this assignment where I parse information into a struct and I keep recieving an error saying "string subscript out of range" when trying to test. Cant figure out where I went wrong.
here is the struct
struct baby_type {
std::string name;
std::vector<int> yearsCount;
int total;
} ;
here is my function
baby_type Parse_Line(const std::string line )
{
baby_type baby;
std::string name;
std::string year;// = "0000";
std::string total;
int i = 0;
int k = 1;
int LengthOfOccurences = 0;
int DigitOfOccurences = 0;
while (line.at(i) != ',') {
name[i] = line.at(i);
i++;
}
baby.name = name;
i++;
while (k < 100) {
if (line.at(i) == ',') {
year.resize(LengthOfOccurences);
baby.yearsCount.at(k) = std::stoi(year);
//year = "0000";
i++;
k++;
DigitOfOccurences = 0;
LengthOfOccurences = 0;
}
else {
year.at(DigitOfOccurences) = line.at(i);
i++;
LengthOfOccurences++;
}
}
int m = 0;
int LengthOfLine = line.length();
while (i < LengthOfLine) {
total.at(m) = line.at(i);
m++;
i++;
}
baby.total = std::stoi(total);
return baby;
}

If you create empty std::string objects and then assign characters to specific positions. std::strings don't work that way.
In your first while loop, use
name.append(1,line.at(i));
The '1' is necessary because there is no simple std::append with just a character as parameter.

Related

Deleting Duplicate chars from a string

Hello I'm kind of new to coding and I am writing a code that deletes any duplicate characters on a string. Let's say the input string was ABBA, then the output should be "empty" since all of the duplicates were deleted. Another example would be if the input string was KKCCD, then the output should be "D" as the code would remove the K and C duplicates. The problem with my code is that when I type KKCCD, it returns KCD and it doesnt delete the duplicates entirely. Also if I we're to type "AA" the result comes back as "A" instead of "Empty". Any help in fixing my code will be much apreciated. Thanks.
include
#include <string.h>
using namespace std;
string deduplicate(string input){
int i;
int x;
int len= input.length();
string outputStr;
string strEmpty = "Empty";
if (input.length() == 1)
{return input;}
for(i = 0; i<len;i++){
for(x = i+1; x<len; x++){
if(input[i] == input[x]){
input.erase(x,1);
x--;}
}
len = input.length();
}
return outputStr = input;
if (input.length() == 0)
{return strEmpty;}
return outputStr = input;
}
int main()
{
string input;
cout << "Enter a string: " << endl;
cin >> input;
cout << deduplicate(input);
return 0;
}
Change your duplicate function to this
string deduplicate(string input){
int i;
int x;
int len= input.length();
string outputStr;
string strEmpty = "Empty";
if (input.length() == 1)
{return input;}
for(i = 0; i<len;i++){
for(x = i+1; x<input.length(); x++){ // This line
if(input[i] == input[x]){
input.erase(x,1);
input.erase(i,1); // and this line
x--;
}
}
len = input.length();
}
return outputStr = input;
if (input.length() == 0)
{return strEmpty;}
return outputStr = input;
}
You did delete the duplicate character but not original, so the second erase statement does it.
You are deleting the duplicate you find, but you never delete the original character. The most efficient way to achieve your goal is to use STL algorithms. You might want to check out this link: Remove all duplicate characters from a string (STL)
Generally speaking I do not think if that is a good idea to delete characters from a string you are iterating. It would be much better and cleaner to construct your output instead:
#include <string>
#include <iostream>
using namespace std;
string deduplicate(string input) {
string outputStr;
if (input.length() == 1) {
return input;
}
for ( int i = 0; i < input.length(); i++ ) {
// try to find character at the rest of the string
if ( input.find( input[i], i+1 ) == string::npos ) {
// try to find character in the front
if ( ( i > 0 ) && ( input.rfind( input[i], i-1 ) == string::npos ) ) {
outputStr += input[i];
}
}
}
return outputStr;
}
int main()
{
string input;
cout << "Enter a string: " << endl;
cin >> input;
cout << deduplicate(input) << endl;
return 0;
}
Here is a "brute force" implementation.
string deduplicate(string str)
{
size_t l = str.length();
bool bFound = false;
char character = 0;
for (int i = 0; i < l; i++)
{
character = str[i];
while (true)
{
size_t next = str.rfind(character);
if (next != std::string::npos)
{
if (bFound || (!bFound && next != i))
{
str.erase(next, 1);
bFound = true;
l--;
}
}
if (next == i)
{
if (bFound == true)
{
i--;
}
bFound = false;
break;
}
}
}
return str;
}

How to convert any base to base 10 for big numbers

I want to convert a big number (100,000 digits) from any base to base 10. I'm using this code:
this is reading file method
string* ReadFile(string fileName) {
ifstream inFile(fileName);
string line;
string* myArray = new string[1000000];
if (inFile.is_open()) {
int count = 0;
while (getline(inFile, line)) {
myArray[count] = line;
count++;
}
inFile.close();
}
else
{
cout << "file is not open";
}
return myArray;}
convert every character to base 10 method
int val(char c){
if (c >= '0' && c <= '9')
return (int)c - '0';
else
return (int)c - 'A' + 10; }
any base to decimal
int Base2Dec(string* arr) {
int base = stoi(arr[0]);
string str = "";
int size = 0;
while (!arr[size].empty())
++size;
for (int i = size; i > 0; i--) {
str += arr[i];
}
int len = str.length();
int power = 1;
int num = 0;
for (int i = len - 1; i >= 0; i--)
{
if (val(str[i]) >= base)
{
printf("Invalid Number");
}
num += val(str[i]) * power;
power = power * base;
}
return num;}
and main method
int main(){
string* A = ReadFile("A2.txt"); cout << Base2Dec(A);
string* B = ReadFile("B.txt"); Base2Dec(B);
cin.get();}
it works but not for 100,000 digits ?! I know int type is limited and I am not allowed to use int64 so, I want to know what the solution is?!

c++ Function which returns data to a refrenced vector

I have a function that reads a text file and populates a vector which is referenced as an argument.
vect.push_back(TempArray);
is the line that causes my error. Any thoughts?
Error 1 error C2664: 'void std::vector<_Ty>::push_back(double *&&)' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'double *&&' d:\aul_c++_12102014\aul_c++_rk_version_12182014\aul\aul\projection.h 206 1 AUL
int projection::import_inputTables(string input_file, string output_file, int dimen, vector<double*> &vect, long col_filler, long row_filler, string delim, int OptArgVar)
{
long i=0,j=0,k=0;
int total_Col = dimen;
long MaxLinesNum = 100000;
const string DELIM = delim;
string Line;
string LineCell;
long LineCounter = 0;
long LinesRead = 0;
int LineReadPoint = 0;
//Determines number of lines to be read
if (OptArgVar == 0) //Read untill the end
{
MaxLinesNum = 100000;
}
else if (OptArgVar == 1)
{
MaxLinesNum = 1;
}
else if (OptArgVar == 2)
{
MaxLinesNum = 51;
}
ifstream input_stream;
input_stream.open(input_file);
if (input_stream.is_open())
{
while( MaxLinesNum > LinesRead )
{
getline(input_stream,Line);
if (LineCounter >= col_filler)
{
vector<double> TempArray;
for (j = 0; (j < total_Col); j++) //Column Loop
{
LineCell = Line.substr(0,Line.find(DELIM));
Line.erase(0,Line.find(DELIM) + DELIM.length());
TempArray.push_back(stod(LineCell));
}
vect.push_back(TempArray);
vector<double> ().swap(TempArray);
LinesRead++;
LineCounter++;
}
else
{
LineCounter++;
}
if (MaxLinesNum == LinesRead) //Read only the needed number of lines --- Will read entire file if OptArgVar is set to 0
break;
}
}
else
{
cout << "Could Not Open File" << endl;
}
//PRINT STATEMENT DO NOT DELETE
input_stream.close();
return vect.size();
/*ofstream out(output_file);
out.precision(10);
for (j = 0; j < vect.size(); j++){
for (i = 0; i <= total_Col; i++){
out << vect.at(j)[i]<< '\t';
}
out << '\n';
}
out.close();*/
}
Looks like
vector<double*> &vect
should be
vector<vector<double>> &vect

char* pointer alloted to char array,and outputted within for

I have defined the struct chararray as follows.
struct chararray
{
char* lhs;
char* rhs;
};
Now, I have two arrays la[l] and ra[l](both have all l values defined). I assign that to the struct,and return the function.
chararray s;
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &la[0];
s.rhs = &ra[0];
return s;
In main , I ouptut
for(int i = 1; i < l;i++){
cout << *(s.rhs + i);
}
Now,I get gibberish as output.
But if I output *(s.rhs + 0) and *(s.rhs + 1) and ... [ the values 0,1,.. are explicitly included ], I get correct output!
Why doesnt the for loop work?
PS - My entire code is -
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
struct chararray
{
char* lhs;
char* rhs;
};
chararray getcenter(char in[],int l){
int open_count = 0;
int open = 0;
int first = 0;
int last = 0;
int limit;
int close_count = 0;
char lhs[l],rhs[l];
for(int i = 0; i < l;i++){
lhs[i] = ' ';
rhs[i] = ' ';
}
for(int i = 0; in[i]!='\0';i++){
int flag = 0;
if(in[i] == '('){
if(flag == 0){first = i;flag = 1;}
open++;
}
if(in[i] == '('){
last = i;
}
limit = i;
}
for(int i = 0; in[i]!='\0';i++)
{
//cout << "entrt" << endl;
int temp;
if(in[i] == '(') { open_count++; }
if(in[i] == ')') { close_count++; }
if((open_count == close_count) && (open_count != 0) && (open_count != open))
{
//cout << open_count << endl;
for(int j = 0;j < i+1;j++)
{
lhs[j] = in[j];
}
lhs[i+1] = ' ';
lhs[i+2] = ' ';
for(int j = i+3; in[j]!='\0';j++)
{
lhs[j] = ' ';
rhs[j-i-3] = in[j];//Assuming no space between -> and rhs
temp = j;
}
for(int j = temp;rhs[j] != '\0';j++){
rhs[j] = ' ';
}
for(int j = temp;lhs[j] != '\0';j++){
lhs[j] = ' ';
}
break;
}
}
chararray s;
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &lhs[0];
s.rhs = &rhs[0];
return s;
}
int main()
{
string input;
cin >> input;
int l=input.length()+1;
char in[l];
strcpy(in, input.c_str());
chararray s = getcenter(in,l);
for(int i = 1; i < l;i++){
//cout << *(s.rhs + i); - Doesnt work
}
cout << *(s.lhs + 5); // Works!
return 0;
}
Your for loop is starting at i=1, and when you explicitly set the values you are using 0 and 1. Decide where you want to start, and try it again.
Try this:
for(int = 0 ; i < l; i++)
cout << *(s.rhs + i);
Note that you are actually risking a memory leak with these lines of code:
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &lhs[0];
s.rhs = &rhs[0];
You are allocating 1 char and storing its address in s.lhs, then resetting s.lhs to the address of lhs[0]. There is no need for the two first lines with the new in them. So replace that code with this: (also note that &lhs[0] is the same as lhs)
s.lhs = lhs;
s.rhs = rhs;

Why is this function printing an x instead of 1?

I have written a small program for run length encoding.
void runLengthEncoding (string& str)
{
int k=0;
int count =1;
for (unsigned i=1, count=1; i<str.size(); ++i)
{
if ( str[i] == str[k])
{
count +=1;
}
else
{
str[++k] = count+'0';
str[++k] = str[i];
count = 1;
}
}
str[++k] = count + '0';
str.resize(k);
}
When I call this function using
string s = "wwwwaaadexxxxxx";
runLengthEncoding (s);
cout << endl << s;
It is printing - "w4a3d1e1x"
It should print - "w4a3d1e1x6"
My doubt is why it is not printing the last count?
Instead of using
str.resize(k)
i need to use
str.resize(k+1);
If you delete for count initialization, and resize correctly, you got it:
void runLengthEncoding (string& str)
{
int k=0;
int count =1;
for (unsigned i=1; i<str.size(); ++i)
{
if ( str[i] == str[k])
{
count +=1;
}
else
{
str[++k] = count+'0';
str[++k] = str[i];
count = 1;
}
}
str[++k] = count + '0';
str.resize(++k);
}