🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: alt.comp.lang.learn.c-c++
9 messages
9 total messages Started by SKAS Tue, 28 May 2002 07:53
Program crashes at end
#447
Author: SKAS
Date: Tue, 28 May 2002 07:53
170 lines
4143 bytes
I've written a class for string datatype.  The program runs fine but crashes
in the end . However if I initialize the variable po in the main function
 int i, po= 8;) instead of getting it from the user (cin >>po) the program
exits nicely and doesn't crash.
I'll be very grateful for any assistance. I'm using turbo c++ 3.0.

Thanks


#include <iostream.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>

class string
{
 private:
      char *head;
      int len;
 public:
      string()
   {
   }

  string(int l)
  {
   len=l;
   head=new char[len];
  }

  string(char a[])
  {
   strcpy(head,a);
  }

  ~string()
  {
     delete head;
  }

  int length();
  char atindex(int);
  int substring(char []);
  void print();
  void concatenate(char []);
  void upper();
  void lower();
  void proper();
  int compare(char []);
};

int string::length()
{
 int index=0;
 while (*(head+index))
  index++;
 len=++index;
 return index;
}

void string::print()
{
 int index=0;
 while (*(head+index))
 {
  cout<<*(head+index);
  index++;
 }
}

char string::atindex(int index)
{
    return *(head+index);
}

void string::upper()
{
 int index=0;
 while (*(head+index))
 {
  if ((*(head+index)>=97) && (*(head+index)<=122))
   *(head+index)-=32;
  index++;
 }
}

void string::lower()
{
 int index=0;
 while (*(head+index))
 {
  if ((*(head+index)>=65) && (*(head+index)<=90))
   *(head+index)+=32;
  index++;
 }
}

void string::proper()
{
 int index=0;
 while (*(head+index))
 {
  if (((index==0)||(*(head+index-1)==32))&&((*(head+index)>=97) &&
(*(head+index)<=122)))
   *(head+index)-=32;
  else if ((*(head+index)>=65) && (*(head+index)<=90))
   *(head+index)+=32;
  index++;
 }
}

int string::substring(char a[])
{
 int index=0,i,flag=-1;
 while (*(head+index))
 {
  if(*(head+index) == *a)
  {
   flag=index;
   i=1;
   while (*(a+i))
   {
    if (*(head+index+i) != *(a+i))
    {
     flag=-1;
     break;
    }
    else
     i++;
   }
  }
  if (flag != -1)
   return flag;
  else
   index++;
 }
 return flag;
}

void main(void)
{
 char sub[30],j;
 int i,po;
 string s1("the 1st and most IMPORTANT thing");
 clrscr();
 s1.print();
 cout<<endl<<"The length of string (including null character)=
"<<s1.length();
 cout<<"\nEnter the index for a single character value: ";
 cin>> po;  /* NOTE : IF INITIALIZE PO ABOVE INSTEAD OF GETTING IT FROM THE
USER. PROGRAM WORKS FINE*/
  cout<<"\nThe character at position "<<po<<" is \""<<s1.atindex(po)<<"\"";
 s1.upper();
 cout<<"\nThe string converted to upper case: ";
 s1.print();
 s1.lower();
 cout<<"\nThe string converted to lower case: ";
 s1.print();
 s1.proper();
 cout<<"\nThe string converted to proper case: ";
 s1.print();
 cout<<"\nEnter a substring to be searched in the main string: ";
 gets(sub);
 i=s1.substring(sub);
 if (i != -1)
  cout<<"The position of \""<<sub<<"\" is at index = "<<i;
 else
  cout<<"Substring not found!!!";
 getch();
}
Re: Program crashes at end
#448
Author: Neal E. Coombes
Date: Tue, 28 May 2002 07:14
198 lines
5231 bytes
SKAS wrote:
> 
> I've written a class for string datatype.  The program runs fine but
> crashes in the end . However if I initialize the variable po in the
> main function  int i, po= 8;) instead of getting it from the user
> (cin >>po) the program exits nicely and doesn't crash.
> I'll be very grateful for any assistance. I'm using turbo c++ 3.0.
> 
> Thanks
>
> #include <iostream.h>
> #include <conio.h>
> #include <stdio.h>
> #include <string.h>

#include <iostream>
#include <cstdio>
#include <cstring>
// no such beast as conio.h in standard C++ 

> class string
> {
>  private:
>       char *head;
>       int len;
>  public:
>       string()
>    {
>    }
> 
>   string(int l)
>   {
>    len=l;
>    head=new char[len];
>   }
> 
>   string(char a[])
>   {
>    strcpy(head,a);  // OUCH: you forgot to allocate memory!
>   }

How about:
    string(char a[])
    {
      head = new char[strlen(a)];
      strcpy(head, a);
    }

>   ~string()
>   {
>      delete head;
>   }
> 
>   int length();
>   char atindex(int);
>   int substring(char []);
>   void print();
>   void concatenate(char []);
>   void upper();
>   void lower();
>   void proper();
>   int compare(char []);
> };
> 
> int string::length()
> {
>  int index=0;
>  while (*(head+index))
>   index++;
>  len=++index;
>  return index;
> }
> 
> void string::print()
> {
>  int index=0;
>  while (*(head+index))
>  {
>   cout<<*(head+index);
>   index++;
>  }
> }
> 
> char string::atindex(int index)
> {
>     return *(head+index);
> }
> 
> void string::upper()
> {
>  int index=0;
>  while (*(head+index))
>  {
>   if ((*(head+index)>=97) && (*(head+index)<=122))
>    *(head+index)-=32;
>   index++;
>  }
> }
> 
> void string::lower()
> {
>  int index=0;
>  while (*(head+index))
>  {
>   if ((*(head+index)>=65) && (*(head+index)<=90))
>    *(head+index)+=32;
>   index++;
>  }
> }
> 
> void string::proper()
> {
>  int index=0;
>  while (*(head+index))
>  {
>   if (((index==0)||(*(head+index-1)==32))&&((*(head+index)>=97) &&
> (*(head+index)<=122)))
>    *(head+index)-=32;
>   else if ((*(head+index)>=65) && (*(head+index)<=90))
>    *(head+index)+=32;
>   index++;
>  }
> }
> 
> int string::substring(char a[])
> {
>  int index=0,i,flag=-1;
>  while (*(head+index))
>  {
>   if(*(head+index) == *a)
>   {
>    flag=index;
>    i=1;
>    while (*(a+i))
>    {
>     if (*(head+index+i) != *(a+i))
>     {
>      flag=-1;
>      break;
>     }
>     else
>      i++;
>    }
>   }
>   if (flag != -1)
>    return flag;
>   else
>    index++;
>  }
>  return flag;
> }
> 
> void main(void)

int main()  // no such thing as void main()!

> {
>  char sub[30],j;

out of curiosity, what's j for?

HTH
Neal

>  int i,po;
>  string s1("the 1st and most IMPORTANT thing");
>//  clrscr();
>  s1.print();
>  cout<<endl<<"The length of string (including null character)=
> "<<s1.length();
>  cout<<"\nEnter the index for a single character value: ";
>  cin>> po;  /* NOTE : IF INITIALIZE PO ABOVE INSTEAD OF GETTING IT FROM THE
> USER. PROGRAM WORKS FINE*/
>   cout<<"\nThe character at position "<<po<<" is \""<<s1.atindex(po)<<"\"";
>  s1.upper();
>  cout<<"\nThe string converted to upper case: ";
>  s1.print();
>  s1.lower();
>  cout<<"\nThe string converted to lower case: ";
>  s1.print();
>  s1.proper();
>  cout<<"\nThe string converted to proper case: ";
>  s1.print();
>  cout<<"\nEnter a substring to be searched in the main string: ";
>  gets(sub);
>  i=s1.substring(sub);
>  if (i != -1)
>   cout<<"The position of \""<<sub<<"\" is at index = "<<i;
>  else
>   cout<<"Substring not found!!!";
>//  getch();
> }

-- 
char*a(char*b,char c){while(*b!=c&&*b)++b;return b;}int main(){\
char*d=".CEfmc oliaNbkHrse\n", *e="lNoCs\nofrHli\nlbC  \nl cscs\
c\nbsHNa",*f=a(d,'a'),*g=e;int putchar(),h=f-d;while(*e++){if(!\
*e)e=g;h+=a(d,*e++)-f;putchar(d[h]);if(!*e)e=g;++e;}return 0;}
Re: Program crashes at end
#449
Author: Panu Mantylahti
Date: Tue, 28 May 2002 09:43
130 lines
4746 bytes
In comp.lang.c++ SKAS <f93c0532@yahoo.com> wrote:
> I've written a class for string datatype. The program runs fine but
> crashes in the end.

Your constructor is broken, as are a few more things; see below.

BTW: you seem to save whitespaces, like writing cout<<"foo"<<endl; I'd
advise you to make more liberal use of those, like cout << "foo << endl;
It is more readable, IMHO.

> I'm using turbo c++ 3.0.

Okay, since TC3 is old an compiler, I won't whine about using old header
names. Remember though conio.h is non-standard, and won't work in other
than Borland's products.

>   string(char a[])
>   {
>    strcpy(head,a);
>   }

Head is a char pointer, which doesn't necessilary point anywhere. In
your code, you say

string s1("the 1st and most IMPORTANT thing");

which calls for appropriate constructor, i.e. such that takes a char
array as parameter. The constructor never allocates the memory for the
new string, and that's a mistake. Let's remake the constructor like
this:

string(char *a){
 try{
  a=new char[strlen(a)+1]; // allocate new array and add 1 for \0 terminator
 }
 catch(bad_alloc &b){ // check if the allocation worked OK.
  std::cout << b.what();
  exit(1);
 }

 strcpy(head, a);
 // you might even want to check the head has equal length with a.
}

>   ~string()
>   {
>      delete head;
>   }

Invalid destructor, head is allocated with new char[], thus you must
delete[] it:

~string(){
 delete []head;
}

> void string::print()
> {
>  int index=0;
>  while (*(head+index))
>  {
>   cout<<*(head+index);
>   index++;
>  }
> }

cout is buffered, so it won't necessilary print anything onto screen.
You can force it by printing a std::endl, or std::flush;

Add cout << flush or cout << endl after the while loop. (Since TC3,
IIRC, doesn't support namespaces, you won't need the std:: -prefix.
Should be used in standard C++ though...)


> char string::atindex(int index)
> {
>     return *(head+index);
> }

Does the user know the 1st character lives in location 0? This is
self-evident for any programmer, but the rest of us get confused as they
ask the 1st char and get H instead of T.

> void string::upper()
> {
>  int index=0;
>  while (*(head+index))
>  {
>   if ((*(head+index)>=97) && (*(head+index)<=122))
>    *(head+index)-=32;
>   index++;
>  }
> }

I find this style ugly. You can easily find the length of your head
array by strlen() function call, and use it as an upper limit for loop
instead of string pointers.

By the way... you are modifying the original string. After a case change
the original is lost. Consider

Original string (1st char uppercase, rest lowercase)
ORIGINAL STRING (all uppercase)
original string (all lowercase)

Maybe you want to store the original string and modify a temporary one
instead.

> void main(void)

Main should return an int.

>  gets(sub);

Never, ever use gets! Gets is EVIL. The problem is, gets doesn't check
whether your input is longer than the buffer you assign to it. If you
input more than what will fit into the buffer, you might crash the
application. Even worse, this is excactly the same idea behind so many
IIS worms are cracking into web servers.

Use
std::cin.ignore(1, '\n'); // to get rid of last endline entered
std::cin.getline(sub, 29, '\n'); // read up to 29 chrs to the 30 chr buffer


-P

-- 
Thou shalt not follow the Null Pointer,
for at its end Madness and Chaos lie.
Re: Program crashes at end
#450
Author: Dave Mikesell
Date: Tue, 28 May 2002 12:27
11 lines
1528 bytes
"SKAS" <f93c0532@yahoo.com> wrote in message news:<acv9rh$sopon$1@ID-31123.news.dfncis.de>...

> I've written a class for string datatype.  

Unless this is a homework assignment, use std::string.  That's what
it's there for.  If it is homework or if you insist on writing your
own string class, whittle the code down to the smallest compilable
chunk that exhibits the problem and then post that.  Chances are
you'll find the problem before you have to post again.

<snip>
Re: Program crashes at end
#451
Author: Dan Cernat
Date: Tue, 28 May 2002 12:45
94 lines
3301 bytes
"SKAS" <f93c0532@yahoo.com> wrote in message news:<acv9rh$sopon$1@ID-31123.news.dfncis.de>...
> I've written a class for string datatype.  The program runs fine but crashes
> in the end . However if I initialize the variable po in the main function
>  int i, po= 8;) instead of getting it from the user (cin >>po) the program
> exits nicely and doesn't crash.
> I'll be very grateful for any assistance. I'm using turbo c++ 3.0.
> 
> Thanks
> 
> 
> #include <iostream.h>
> #include <conio.h>
> #include <stdio.h>
> #include <string.h>
> 
> class string
> {
>  private:
>       char *head;
>       int len;
>  public:
>       string()
>    {
>    }
^^^^^^^ initialize head in the default constructor:
    string():head(0) {}
> 
>   string(int l)
>   {
>    len=l;
>    head=new char[len];
>   }
> 
>   string(char a[])
>   {
>    strcpy(head,a);
^^^^^^^^^ trouble - head is not initialized before strcpy
>   }
    string(const char* a)
    {
        l = strlen(a);
        head = new char[l + 1];
        
        strcpy(head, a);
    }


> 
>   ~string()
>   {
>      delete head;
>   }

// code snipped

> 
> void main(void)
> {
>  char sub[30],j;
>  int i,po;
>  string s1("the 1st and most IMPORTANT thing");
^^^^^^^^^^^^^^^^^ call to the trouble constructor

>  clrscr();
>  s1.print();
>  cout<<endl<<"The length of string (including null character)=
> "<<s1.length();
>  cout<<"\nEnter the index for a single character value: ";
>  cin>> po;  /* NOTE : IF INITIALIZE PO ABOVE INSTEAD OF GETTING IT FROM THE
> USER. PROGRAM WORKS FINE*/
>   cout<<"\nThe character at position "<<po<<" is \""<<s1.atindex(po)<<"\"";
>  s1.upper();
>  cout<<"\nThe string converted to upper case: ";
>  s1.print();
>  s1.lower();
>  cout<<"\nThe string converted to lower case: ";
>  s1.print();
>  s1.proper();
>  cout<<"\nThe string converted to proper case: ";
>  s1.print();
>  cout<<"\nEnter a substring to be searched in the main string: ";
>  gets(sub);
>  i=s1.substring(sub);
>  if (i != -1)
>   cout<<"The position of \""<<sub<<"\" is at index = "<<i;
>  else
>   cout<<"Substring not found!!!";
>  getch();
> }


po has nothing to do with it. it was just a side effect.

Dan
Re: Program crashes at end
#452
Author: gbayles
Date: Tue, 28 May 2002 13:10
29 lines
1725 bytes
"SKAS" <f93c0532@yahoo.com> wrote in message news:<acv9rh$sopon$1@ID-31123.news.dfncis.de>...
> I've written a class for string datatype.  

Presumably as a learnng exercise.

> ... The program runs fine but crashes in the end.

IME, this usually means the dtor is accessing invalid memory.

> class string
> {
>  private:
>       char *head;
>       int len;
>  public:
>       string()
>    {
>    }

Always initialize member variables in every ctor. This one allows
you to declare a string with unpredictable values for head and len.
 
>   ~string()
>   {
>      delete head;
>   }

So it can blow up here when the object is destroyed as the program
exits.
Re: Program crashes at end
#453
Author: Emmanuel Delahaye
Date: Thu, 30 May 2002 19:23
50 lines
2172 bytes
In 'borland.public.cpp.turbocpp', "SKAS" <f93c0532@yahoo.com> wrote in
news:acv9rh$sopon$1@ID-31123.news.dfncis.de: 

> I've written a class for string datatype.  The program runs fine but

It doesn't works fine because it invokes an undefined behaviour.

<...>

> #include <iostream.h>
> #include <conio.h>
> #include <stdio.h>
> #include <string.h>
> 
> class string
> {
>  private:
>       char *head;
>       int len;
>  public:
>       string()
>    {
>    }

What is this one made for?
 
>   string(int l)
>   {
>    len=l;
>    head=new char[len];
>   }
> 
>   string(char a[])
>   {
>    strcpy(head,a);

'head' was never initialized. You probably want:

    len = strlen (a) + 1;
    head = new char[len];
    strcpy (head, a);

>   }

-- 
-ed- emdel at noos.fr
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
C-library: http://www.dinkumware.com/htm_cl/index.html
"Mal nommer les choses c'est ajouter du malheur au monde."
Albert Camus.
Re: Program crashes at end
#454
Author: Emmanuel Delahaye
Date: Thu, 30 May 2002 19:24
20 lines
1700 bytes
In 'borland.public.cpp.turbocpp', "Neal E. Coombes"
<Neal.Coombes@telus.net> wrote in news:3CF32E4B.5F6E812E@telus.net: 

> How about:
>     string(char a[])
>     {
>       head = new char[strlen(a)];

       head = new char[strlen(a) + 1];

>       strcpy(head, a);
>     }


-- 
-ed- emdel at noos.fr
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
C-library: http://www.dinkumware.com/htm_cl/index.html
"Mal nommer les choses c'est ajouter du malheur au monde."
Albert Camus.
Re: Program crashes at end
#455
Author: Neal E. Coombes
Date: Fri, 31 May 2002 03:17
15 lines
1502 bytes
Emmanuel Delahaye wrote:
>
> > How about:
> >     string(char a[])
> >     {
> >       head = new char[strlen(a)];
> 
>        head = new char[strlen(a) + 1];
> 
> >       strcpy(head, a);
> >     }

Indeed, thanks for the catch!

Neal
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads