Invalid null pointer - c++

I am trying to write a program that will parse a string and give each position of word. I cannot figure out why I am getting a
"DEBUG ASSERTION FAILED" Experssion: Invalid null pointer
window when it reaches the last word of the string.
char * pointer_char;
int pos = 0;
std::string str = "This test string will fail at this word..!. ";
int i = 0;
int length = str.length();
char * c = new char [str.size()+1];
std::copy(str.begin(), str.end(), c);
c[str.size()] = '\0';
cout << "Testing string is " << str << endl << endl;
pointer_char = strtok (c," ");
while(pointer_char != NULL)
{
cout << pointer_char << endl;
pointer_char = strtok(NULL, " .!");
string word = pointer_char;
size_t found= str.find(word);
if (found!=string::npos)
cout << "Position of " << word << " found at: " << int(found) << endl;
system("pause");
}
return 0;

The problem is you aren't checking the return value of strtok.
pointer_char = strtok(NULL, " .!");
string word = pointer_char;
You're only testing it at the top of the loop.
pointer_char = strtok(nullptr, " .!");
if (pointer_char == nullptr)
break;

Related

How to memoize a recursive problem to avoid re-calculating subproblems?

I am trying to solve this problem:
https://www.geeksforgeeks.org/count-possible-decodings-given-digit-sequence/
Example:
Input:
Input str = "121"
Total decoding:: 3 :: ABA AU LA
I am able to code this problem through recursion. But the code fails to process a bigger input sequence (for e.g., i/p str = 11111111111111111111111111111111111111111)
This is happening because I am calculating sub-problems again-and-again.
Can anyone help me by letting me know how to memoize below sample code?
PS - I know there are other ways to solve this problem. But I don't want to do that. I want to memoize this solution only. It will help me to build my concept. Please help.
Here is the code:
#include "iostream"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
namespace solution3
{
void solve(string str, string& out, vector<string>& v)
{
if (str.size() == 0)
{
v.push_back(out);
return;
}
//we have 2 choices:
//ch#1: take 1st char of str
//ch#2: take 1st and 2nd chars of str
if (str.size() >= 1)//ch#1: take 1st char of str
{
string out1 = out;
string str1 = str;
int num1 = stoi(str.substr(0, 1)); // converting string at index 0 to integer
if (num1) // we will not consider if the string at index 0 is zero.
{
out1.push_back(('#' + num1)); //<-- It will conevrt 1 into A; 2 into B; and so on.
str1 = str1.erase(0, 1);//erase the index 0 from str1.
solve(str1, out1, v);
}
}
if (str.size() >= 2)//ch#2: take 1st and 2nd chars of str
{
string out2 = out;
string str2 = str;
int num2 = stoi(str.substr(0, 2)); // converting string at index 0 and 1 to integer
// checking if num2 is a valid number for decoding.
// num2 should be - NON-ZERO, 1st char is not ZERO, is within the range of 1 and 26.
if (num2 && str[0] != '0' && num2 > 0 && num2 <= 26)
{
out2.push_back(('#' + num2));
//Erase 1st two chars from str
str2 = str2.erase(0, 1);//erase the index 0 from str1.
str2 = str2.erase(0, 1);//erase the index 0 from str1.
solve(str2, out2, v);
}
}
}
void alphacode(string str)
{
string out;
vector<string> v; //<-- To store all the Decodings
solve(str, out, v);
cout << "Total decoding:: " << v.size() << ":: ";
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
}
int main()
{
string str = "25114";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "3333333333";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "202";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "2010";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111111111111111111111111"; //<-- takes too much time! How to solve this?
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
return 0;
}
You can memoize each substring that you are currently working with, which you're forming after deleting one or two characters, depending on the case. Something like this:
#include "iostream"
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
map<string, vector<string>> dp;
namespace solution3
{
void solve(string str, string& out, vector<string>& v)
{
if (str.size() == 0)
{
v.push_back(out);
return;
}
//we have 2 choices:
//ch#1: take 1st char of str
//ch#2: take 1st and 2nd chars of str
if(dp.find(str) != dp.end()) {
vector<string> current = dp[str];
for(string s: current) {
v.push_back(s);
}
return;
}
if (str.size() >= 1)//ch#1: take 1st char of str
{
string out1 = out;
string str1 = str;
int num1 = stoi(str.substr(0, 1)); // converting string at index 0 to integer
if (num1) // we will not consider if the string at index 0 is zero.
{
out1.push_back(('#' + num1)); //<-- It will conevrt 1 into A; 2 into B; and so on.
str1 = str1.erase(0, 1);//erase the index 0 from str1.
solve(str1, out1, v);
}
}
if (str.size() >= 2)//ch#2: take 1st and 2nd chars of str
{
string out2 = out;
string str2 = str;
int num2 = stoi(str.substr(0, 2)); // converting string at index 0 and 1 to integer
// checking if num2 is a valid number for decoding.
// num2 should be - NON-ZERO, 1st char is not ZERO, is within the range of 1 and 26.
if (num2 && str[0] != '0' && num2 > 0 && num2 <= 26)
{
out2.push_back(('#' + num2));
//Erase 1st two chars from str
str2 = str2.erase(0, 1);//erase the index 0 from str1.
str2 = str2.erase(0, 1);//erase the index 0 from str1.
solve(str2, out2, v);
}
}
dp[str] = v;
}
void alphacode(string str)
{
string out;
vector<string> v; //<-- To store all the Decodings
solve(str, out, v);
cout << "Total decoding:: " << v.size() << ":: ";
// for (int i = 0; i < v.size(); i++)
// cout << v[i] << " ";
cout << endl;
}
}
int main()
{
string str = "25114";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "3333333333";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "202";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "2010";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111111111111111111111111"; //<-- takes too much time! How to solve this?
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
return 0;
}

Infinity Loop in Lexical Analyzer in C++

int main(int argc, char *argv[]) {
ifstream inFile;
int numOfLines = 0, numOfTokens = 0, numOfStrings = 0, maxStringLength = 0, l = 0, fileCount=0, mostCommonCount=0;
string inputFile, mostCommonList="", word;
for(int i = 1; i < argc; i++){
if(strpbrk(argv[i] , "-")){
if(flags.find(string(argv[i]))!=flags.end()) flags[string(argv[i])] = true;
else{
cerr << "INVALID FLAG " << argv[i] << endl;
exit(1);
}
}
else{
inFile.open(argv[i]);
fileCount++;
if(!inFile && fileCount==1){
cerr << "UNABLE TO OPEN " << argv[i] << endl;
exit(1);
}
else{
string line;
while(getline(inFile, line)) inputFile+=line+='\n';
if(fileCount>1){
cerr << "TOO MANY FILE NAMES" << endl;
exit(1);
}
}
}
}
int linenum = 0;
TType tt;
Token tok;
while((tok = getNextToken(&inFile, &linenum))!=DONE && tok != ERR){
tt = tok.GetTokenType();
word = tok.GetLexeme();
if(flags["-v"]==true){
(tt == ICONST||tt==SCONST||tt==IDENT) ? cout<<enumTypes[tok.GetTokenType()]<<"("<< tok.GetLexeme()<<")"<<endl : cout<< enumTypes[tok.GetTokenType()]<<endl;
}
if(flags["-mci"]==true){
if(tt==IDENT){
(identMap.find(word)!=identMap.end()) ? identMap[word]++ : identMap[word]=1;
if(identMap[word]>mostCommonCount) mostCommonCount = identMap[word];
}
}
if(flags["-sum"]==true){
numOfTokens++;
if(tt==SCONST){
numOfStrings++;
l = word.length();
if(l > maxStringLength) maxStringLength = l;
}
}
}
if(tok==ERR){
cout << "Error on line" << tok.GetLinenum()<<"("<<tok.GetLexeme()<<")"<<endl;
return 0;
}
if(flags["-mci"]==true){
cout << "Most Common Identifier: ";
if(!identMap.empty()){
word ="";
for(auto const& it : identMap){
if(it.second==mostCommonCount) word += it.first + ",";
}
word.pop_back();
cout << word << endl;
}
}
if(flags["-sum"]){
numOfLines = tok.GetLinenum();
numOfLines = tok.GetLinenum();
cout << "Total lines: " << numOfLines << endl;
cout << "Total tokens: " << numOfTokens << endl;
cout << "Total strings: " << numOfStrings << endl;
cout << "Length of longest string: " << maxStringLength << endl;
}
inFile.close();
return 0;
}
For some reason this code is running infinitely. I cannot figure out the source of error. I also do not know whether this file or the other linked file is causing this error so I posted the main program code. I think is one of the switch statements that causing this error but I am not sure. FYI: I am supposed to make a lexical analyzer so I had three files one lexigh.h (contains all the data types and all the functions), getToken.cpp(file that defines the functions from lexigh.h) and the main program which calls the methods and tests it.

Remove substring that contains certain pattern and ends with specific char

For example I have a string like following:
"VISITOR_INFO1_LIVE=USv90B-7CzI; LOGIN_INFO=e486e37a395be3f0e3b3237d090a6829c1oAAAB7IjQiOiAiREVMRUdBVEVEIiwgIjciOiAwLCAiMSI6IDEsICIzIjogMjAxMTk0MTMwNiwgIjgiOiA2MDgwMTg0NTEzNjQsICIxMCI6IDIzOTYyMTEyODczNH0=; PREF=f5=30;HSID=AHuJQBOVR0lQoRt_3; APISID=QaParXGsQcEPCzKg/A1smCfYrfMjxvfEPT; YSC=Vm3Amq5loFM";
I want to remove all the patterns that contains *SID (HSID,APISID here) upto ';'. I also want to remove substring "LOGIN_INFO= ....;"
So, output string should be "VISITOR_INFO1_LIVE=L80EDuHCEF8; PREF=f5=30";
Following is the solution I have come up with but I think performance can be improved:
const char *str ="VISITOR_INFO1_LIVE=USv90B-7CzI; LOGIN_INFO=e486e37a395be3f0e3b3237d090a6829c1oAAAB7IjQiOiAiREVMRUdBVEVEIiwgIjciOiAwLCAiMSI6IDEsICIzIjogMjAxMTk0MTMwNiwgIjgiOiA2MDgwMTg0NTEzNjQsICIxMCI6IDIzOTYyMTEyODczNH0=; PREF=f5=30;HSID=AHuJQBOVR0lQoRt_3; APISID=QaParXGsQcEPCzKg/A1smCfYrfMjxvfEPT; YSC=Vm3Amq5loFM";
char *Cookie = NULL;
cout << "original string is:\n" << str << "\n";
int len = strlen(str)+1;
cout << "length of original string is : " << len << "\n";
Cookie = new char[strlen(str)];
strncpy(Cookie,str,len);
char *p1 = strstr(Cookie,"LOGIN_INFO");
char *p2 = NULL;
if(p1){
p2 = strstr(p1,";")+1;
while(*p2 == ' ') p2++;
}
if(p1 && p2)
memmove(p1,p2,strlen(p2)+1);
char *ID = strstr(Cookie,"SID");
while( ID != NULL){
char *start_pos = NULL, *end_pos = NULL;
while((*ID != ';') && (*ID != Cookie[0]) && (*ID != ' ')){
--ID;
}
if(*ID == Cookie[0]) start_pos = ID;
else start_pos = ID+1;
end_pos = strstr(start_pos,";")+1;
while(*end_pos == ' ')
end_pos++;
memmove(start_pos,end_pos,strlen(end_pos)+1);
// }
/*else
std::cout << "does not find substr " << "\n";*/
// cout << "modified string is :" << Cookie << "\n";
ID = strstr(Cookie,"SID");
}
//cout << "final modified string is : " << Cookie << "\n";
char *Cookie_modified = NULL;
const char *pch = strstr(Cookie,"PREF");
if(pch != NULL){
const char *append = "&f2=8000000";
int len = strlen(Cookie) + strlen(append) + 1;
Cookie_modified = new char[len];
strncpy(Cookie_modified,Cookie,len);
Cookie_modified[len-1] = '\0';
char *p = strstr(Cookie_modified,"PREF");
strncpy(p+(strlen(p)),append,strlen(append));
cout << "modified Cookie is : " << Cookie_modified << "\n";
// cout << "length of modified cookie is : " << strlen(Cookie_modified) << "\n";
}
else{
cout << "do not find reference: " << "\n";
const char *append = ";PERF=f2=8000000";
int len = strlen(Cookie) + strlen(append) + 1;
Cookie_modified = new char[len];
Cookie_modified[len-1] = '\0';
strcat(Cookie_modified,Cookie);
strcat(Cookie_modified,append);
cout << "case 2: modified Cookie is: " << Cookie_modified << "\n";
}
delete[] Cookie;
delete[] Cookie_modified;
return 0;
}
Just use std::regex_replace with the following regex:
([^\s]*SID[^;]*;|[^\s]*LOGIN_INFO[^;]*;)
And replace with empty string.
Live Demo

getting bus error : 10 with string append

I have a function that takes two strings and determines if they are the same. I am trying to tokenize the string and combine all of tokens into one string. This is what I have so far and I am getting Bus error :10.
any help appreciated.
#include <iostream>
#include <string>
using namespace std;
bool stringCheck(string s1, string s2){
string strCheck1 = "";
string strCheck2 = "";
char *cstr1 = new char[s1.length()]; // char array with length of string
strcpy(cstr1, s1.c_str()); // copies characters of string to char array
char *cstr2 = new char[s2.length()];
strcpy(cstr2, s2.c_str());
char *p1 = strtok(cstr1, " "); // creates a char array that stores token that
// is delimeted
cout << "p1 " << p1 << endl; ///outputs token that is found
strCheck1.append(p1); // appends token to string
cout << "strCheck1 " << strCheck1 << endl; // outputs string
while(p1 != NULL) // while the token is not a null character
{
cout<<"parsing" << endl;
p1 = strtok(NULL, " "); // continue to parse current string.
cout << "p1 " << p1 << endl;
strCheck1.append(p1);
cout << "str1 " << strCheck1 << endl;
}
char * p2 = strtok(cstr2, " ");
cout << "p2 " << p2 << endl;
strCheck2.append(p2);
cout << "strCheck2 " << strCheck2 << endl;
while(p2 != null){
p2 = strtok(NULL, " ");
strCheck2.append(p2);
cout << "str2 " << strCheck2 << endl;
}
if( strCheck1.compare(strCheck2) != 0)
{
return 0;
}
else return 1;
}
int main(void){
string s1 = "jam yoooo jay";
string s2 = "jam yoooo";
if(stringCheck(s1, s2) == 1){
cout << "strings same"<< endl;;
}
else{
cout << "strings not same" << endl;
}
}
is there a conditional statement I could pair up with
while(p1 != NULL)
I know this is a pretty silly function but just trying to polish up my skills. any help appreciated!
There are some things you must change:
char *cstr1 = new char[s1.length()];
c-string are null-terminated, so you need one more char to store the null character:
char *cstr1 = new char[s1.length() + 1];
(same for cstr2)
strCheck1.append(p1)
p1 cannot be a null pointer (see Assign a nullptr to a std::string is safe? for further details). So you have to check...
if (p1) strCheck1.append(p1);
(same for p2).
cout << p1 << endl
if p1 is a null pointer bad things can happen (see Why does std::cout output disappear completely after NULL is sent to it). So you have to check...
if (p1) { cout << "p1 " << p1 << endl; strCheck1.append(p1); }
(same for p2)
there is a memory leak (cstr1 / cstr2 must be deleted).
At the end it should work.
Probably you should consider other systems to extract tokens (where you haven't to mix std::string and c-string). E.g.:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string text("text-to-tokenize");
std::istringstream iss(text);
std::string token;
while(getline(iss, token, '-'))
std::cout << token << std::endl;
return 0;
}

Why this program gives a Segmentation Fault while calling a function?

This is a part of my program while I run this program I get a segmentation fault. I've narrowed it down to the line:
checkBase(ptr1, ptr2)
i'm passing both of these as pointers. and they are declare as char* and its a runtime error not compile time.
file contains
< a href = "http://www.google.com"> www.spam.google.com < /a >
in this case ptr1 = www.google.com and ptr2 = spam.google.com
while(inf){
count++;
getline(inf, line);
//cout << "*******" << count << "*******" << endl <<line << endl;
p = new char[line.length()+1];
strcpy(p, line.c_str());
if(strstr(p, "href")){
ptr = strstr(p, "href");
while(ptr[0]!='\0'){
ptr += 1;
if(ptr[0] == 'w' && ptr[1] == 'w' && ptr[2] == 'w'){
cout << ptr << endl;
ptr = strtok(ptr, "\"");
cout << "add1 " << ptr << endl;
add1 = ptr;
ptr1 = ptr;
ptr = strtok(NULL, "> ");
add2 = ptr;
ptr2 = ptr;
cout << "ptr1: " << ptr1 << endl << "ptr2: " <<ptr2 << endl;
if(add1 == add2)
cout << "There is an exact match at line: " << count << endl << line << endl;
else{
cout << "in else" << endl;
checkBase(ptr1, ptr2); //THIS GIVES A SEGMENTATION FAULT
}
}
}
}
}
void checkBase(char *add1, char *add2){
cout << "here" << endl;
char *base1[1000000], *base2[1000000];
int count1 = 0, count2 = 0;
base1[count1] = strtok(add1, ".");
while(base1[count1] != NULL){
count1++;
base1[count1] = strtok(NULL, ".");
cout << base1[count1] << endl;
}
base2[count2] = strtok(add2, ".");
while(base2[count2] != NULL){
count2++;
base2[count2] = strtok(NULL, ".");
}
cout << base2[count2-1] << endl;
if(((strcmp(base1[count1-1],base2[count2-1])) != 0) && (strcmp(base1[count1-2], base2[count2-2]) != 0)){
//if((strcmp(base1[count1-1], base2[count2-1]) != 0)){
cout << "Bases do not match: " << endl
<< base1[count1-2] << "." << base1[count1-1] << " and "
<< base2[count2-2] << "." << base2[count2-1] << endl;
//}
}
else{
cout << "Bases match: " << endl
<< base1[count1-2] << "." << base1[count1-1] << " and "
<< base2[count2-2] << "." << base2[count2-1] << endl;
}
}
I have no idea why this is giving a segmenation fault.
char *base1[1000000], *base2[1000000];
No doubt this is causing stack overflow. The stack is limited in size, and creating arrays more than a few kb in size is a bad idea. Try allocating them on the heap, for example vector<char *> base1(1000000)
You should also calculate the exact size required and allocate that much, or push_back on the vector.
A couple of problems, beyond the stack overflow already mentioned by #Neil Kirkwell
Those shouldn't be while loops solely conditioned on base1[count1] != NULL; you should also make sure count1 is less than the number of elements in the array.
If either count2 or count1 is 0 or 1 you will be trying to reference index of -1 and -2... not so good.
use strrchr to search backwards and make your life easier
It's wasteful to build those arrays entirely, since you only seem to care about the last two tokens, you only need two pointers in each.
i.e.
char *one_a = NULL, *one_b = NULL, *two_a=NULL, *two_b = NULL;
char *temp = strtok(add1, ".");
while (temp) {
one_b = one_a;
one_a = temp
temp = strtok(NULL, ".");
}
char *temp = strtok(add2, ".");
while (temp) {
two_b = two_a;
two_a = temp
temp = strtok(NULL, ".");
}
//now just compare one_a with two_a and one_b with two_b and you're done.