0

I have tried all possible ways. I think there is some logical error in the function findlink()
The purpose of this function is to find and return a pattern from the argument abc.
For example, if abc is "Hello,My name is **Lorem ipsum sit amet ** and I am a student.", then findlink will return "Lorem ipsum sit amet". i.e. it returns the text between double asterisk. But due to some reason I am getting segmentation fault, though I have debugged and figured out that the fault is concerned with this function only, but I am unable to discover why.

char *findlink(char *abc)
{
    if(abc==NULL)
        return NULL;
    cout<<"Findlink called for : "<<abc<<endl;
    int i=0,flag=0,flag1=0,len=0;
    char *link;
    for(i=0;i<strlen(abc)-1;i++)
    {
        if(abc[i]=='*' && abc[i+1]=='*' && flag==0)
        {
            flag=1;
            i+=2;
        }
        if(abc[i]=='*' && abc[i+1]=='*' && flag==1)
        {
            flag=0;
            flag1=1;
            i+=2;
        }
        if(flag==1 && flag1!=1)
            link[len++]=abc[i];
        if(flag1==1)
        {
            link[len++]='\0';
            cout<<"Returning "<<link<<endl;
            return link;
        }
    }
    cout<<"Returning NULL\n";
    return NULL;
}

.
Following is the full code for reference.

#include<iostream>
#include<fstream>
#include<string.h>
#include<stdio.h>
using namespace std;
ifstream infile;
ofstream outfile;
struct queue
{
    struct node *front;
    struct node *rear;
};
struct queue* createqueue()
{
    struct queue *temp=new queue;
    temp->front=NULL;
    temp->rear=NULL;
    return temp;
}
struct node
{
    struct node *next;
    char *value;
};
struct node * createnode(char *val)
{
    struct node *new1=new node;
    new1->next=NULL;
    new1->value=val;
    return new1;
}
struct queue *push(char *val,struct queue *queue1)
{
    struct node *new1=createnode(val);
    if(queue1->front==NULL && queue1->rear==NULL)
    {
        queue1->front=queue1->rear=new node;
        queue1->rear=new1;
        queue1->front=new1;
    }
    else
    {
        queue1->rear->next=new node;
        queue1->rear->next=new1;
        queue1->rear=queue1->rear->next;
    }
    return queue1;
}
struct queue *push(string val,struct queue *queue1) //overloaded function push for string arguments
{
    char* cstr = new char[val.length() +1]; 
    strcpy(cstr, val.c_str()); 
    queue1=push(cstr,queue1);
    return queue1;
};
struct queue *pop(struct queue *queue1)
{
    struct node *temp=new node;
    if(queue1->front==NULL)
        return NULL;
    else if(queue1->front==queue1->rear)
    {
        temp=queue1->front;
        queue1->front=NULL;
        queue1->rear=NULL;
        cout<<"POP: Poping: "<<temp->value<<endl;
        return queue1;
    }
    else
    {
        temp=queue1->front;
        queue1->front=queue1->front->next;
        cout<<"POP: Poping: "<<temp->value<<endl;
        return queue1;
    }
}
struct queue *scanitall(struct queue *queue1)       //reads the contents from outputproject.txt and pushes all the contents in a queue
{
    string line;
    infile.open("outputproject.txt");
    while(getline(infile,line))
    {                    
        char *line1=new char[line.length()+1];
        strcpy(line1,line.c_str());
        queue1=push(line1,queue1);
    }
    infile.close();
    return queue1;
}
int search(struct queue* queue1,char *val)  //returns 1 if val found in queue1 else 0
{
    //cout<<"SEARCH called\n";
    if(queue1->front==NULL || queue1->rear==NULL)
        return 0;
    struct node *temp=new node;
    temp=queue1->front;
    while(temp)
    {
        if(strcmp(temp->value,val)==0)
            return 1;
        temp=temp->next;
    }
    return 0;
}
char *findlink(char *abc)
{
    if(abc==NULL)
        return NULL;
    cout<<"Findlink called for : "<<abc<<endl;
    int i=0,flag=0,flag1=0,len=0;
    char *link;
    for(i=0;i<strlen(abc)-1;i++)
    {
        if(abc[i]=='*' && abc[i+1]=='*' && flag==0)
        {
            flag=1;
            i+=2;
        }
        if(abc[i]=='*' && abc[i+1]=='*' && flag==1)
        {
            flag=0;
            flag1=1;
            i+=2;
        }
        if(flag==1 && flag1!=1)
            link[len++]=abc[i];
        if(flag1==1)
        {
            link[len++]='\0';
            cout<<"Returning "<<link<<endl;
            return link;
        }
    }
    cout<<"Returning NULL\n";
    return NULL;
}
struct queue *processit(struct queue *queue1,char *abc) //identifies link text in inputproject.txt
{
    //cout<<"PROCESSIT called\n";
    ofstream outfile;
    outfile.open("outputproject.txt",ios::app);
    if(!outfile)
        cout<<"PROCESSIT: Error file not opened!\n";
    char *link;
    link=findlink(abc);
    if(link)
        cout<<"Caught: "<<link<<endl;
    if(link)
        if(search(queue1,link)==0)
            {
                cout<<"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
                outfile<<link<<endl;
                queue1=push(link,queue1);
            }
    outfile.close();
    return queue1;
}
void openallfiles(struct queue *queue1)
{
    if(!queue1->rear)
        cout<<"Queue Empty\n";
    else
    {
        struct node *temp=new node;
        temp=queue1->front;
        string line;
        while(temp)
        {
            ifstream infile;
            infile.open(temp->value);
            if(!infile)
            {
                cout<<"openallfiles:File not opened\n";
                return;
            }
            while(getline(infile,line))
            {
                cout<<line<<endl;
            }
            infile.close();
            if(temp)
                temp=temp->next;
        }
    }
}/*
struct queue *findlinks(struct queue *crawl1,ifstream infile)
{

}
crawl(struct queue *crawl1)
{
    ifstream infile1,infile2;
    infile1.open("inputproject.txt");
    crawl1=findlinks(crawl1,infile1);
}*/
void display(struct queue *queue1)
{
    if(queue1->front)
    {
        struct node *temp=queue1->front;
        while(temp)
        {
            cout<<"data:"<<temp->value<<endl;
            temp=temp->next;
        }
    }
    else{
        cout<<"Sorry queue empty\n";
    }
}
int main()
{
    struct queue *queue1=createqueue();
    struct queue *crawl1=createqueue();
    queue1=scanitall(queue1);       //push all contents of outputproject.txt in  a queue
    display(queue1);
    //cout<<"Poping:\n";
    /*while(queue1->rear)
        queue1=pop(queue1);*/
    string line;
    char *line1;
    infile.open("inputproject.txt");
    while(getline(infile,line))
    {
        line1=new char[line.length()+1];
        strcpy(line1,line.c_str());
        queue1=processit(queue1,line1);
    }
    infile.close();
    openallfiles(queue1);
    return 0;
}
1
  • Don't use strncpy until you're read and understood its documentation. It is not a "safe" dropin replacement for strcpy. If your source string is too long, strncpy will postpone the buffer overrun; it won't prevent it. Commented Apr 29, 2016 at 18:33

2 Answers 2

2

The string class has a constructor that takes a NULL-terminated C-string. No use of strncpy() in your case. To convert from a C-String to a string you do it directly. Example:

char MyCharArray[] = "Whatever";

std::string MyStandardString(MyCharArray); // done

On the other hand, to convert a string to a C-String you can use the built in function of the class string which is the apply of the D3 rule:

char YourCharArray = YourString.c_str();

But that is considered bad practice, why? Because when your string "dies", so your char array.

You, instead, need to use something like this:

std::string YourString = "hello world";
char* YourCharArray = new char[YourString.length() + 1]; // notice the "new", means your pointer "allocated" new memory just for itself

std::strcpy(YourCharArray, YourString.c_str());
delete[] YourCharArray; // this and only this will kill your CharArray. Which you "HAVE" to in order to "free" the memory once your program ends executing 

Look here for Documentation on C-String to string and Here for string to C-String

Advice: Don't practice the use of using namespace std; Why? Look here: Why is “using namespace std” in C++ considered bad practice?.

Sign up to request clarification or add additional context in comments.

6 Comments

sir,why should i avoid using namespace std?
@rahul I edited my answer and added a reference for you.
I think the problem is deeper than this. The problem code calls push which ends up storing a pointer to the local array. Technically, the next time round the while-loop this pointer is invalid (although in practise it will always be the same). The means that every node ends up holding the same (random) string.
@FirstStep, Sir thank you so so much, I had been debugging this code for 2 weeks but not got any satisfactory answer until now,thank you very much
@FirstStep , sir I have edited the question for seg fault.Can you help me?
|
0

The problem is that struct node holds a pointer to char. If you trace down all the calls nothing allocates a copy of line1, so all the nodes end up pointing at the same buffer. (Technically, it is undefined behaviour because line1 ceases to exist each time round the while loop, in practise though, they will all point to the same place on the stack.)

The fix is to make struct node hold a std::string, and then instead of calling strncpy, you can just push the string.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.