PDA

Visualizza la versione completa : [c++] stringhe illimitate


metropolis999
26-12-2001, 01:45
come gestisco le stringhe in c++ in maniera tale da non dover dichiarare l'array di caratteri? ossia questo

#include <iostream.h>

main()

{

char[20] messaggio;

cin >> messaggio;

cout << messaggio << endl;

return(0);

}

non puo' essere modificato in maniera tale da non dover limitare l'inserimento dei caratteri al numero di 20 ?

metropolis999
27-12-2001, 01:56
up

metropolis999
27-12-2001, 11:52
#include <iostream.h>
#include <string.h>

main()

{

char* name;

name = new char;

cin >> name;

cout << name << endl;

delete (name);

return (0);


}

così non fa, come posso fare?

p.s.: mi dice anche che ho fatto dei danni... è grave medico?

Andrea Simonassi
28-12-2001, 21:01
#include "StringBuffer.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>

StringBuffer::StringBuffer() throw()
{
this->capacity = 32;
this->factor = 50;
this->length = 0;
this->original_capacity = 32;
buffer = (char*)malloc(32);
if (buffer==NULL)throw;
buffer[0]='\0';
}

StringBuffer::StringBuffer(int capacity, unsigned int factor) throw()
{
this->capacity = capacity;
this->factor = factor;
this->length = 0;
this->original_capacity = capacity;
buffer = (char*)malloc(capacity+1);
if (buffer==NULL)throw;
buffer[0]='\0';
}

//these Append method must be protected against multithread collisions
//if necessary

void StringBuffer::Append(int n) throw()
{
char num[80];
itoa( n, num, 10);
try{
Append(num);
}
catch(void)
{
throw;
}
}

void StringBuffer::Append(int n, int radix) throw()
{
char num[80];
itoa( n, num, radix);
try{
this->Append(num);
}
catch(void)
{
throw;
}
}
void StringBuffer::Append(char c) throw()
{

try{
EnsureCapacity(length + 2);
}
catch(void)
{
throw;
}
buffer[length++]=c;
buffer[length]='\0';
}
void StringBuffer::Append(double n) throw()
{
char dbl[256];
sprintf(dbl, "%f", n);
try{
Append(dbl);
}
catch(void)
{
throw;
}
}

//Assume that c is terminated by zero
void StringBuffer::Append(char* c) throw()
{
try{
EnsureCapacity(length + strlen(c) + 1);}
catch(void){
throw;}

strcat(buffer, c);
length += strlen(c);
}

//return the actual capacity of the buffer
int StringBuffer::Capacity()
{
return capacity;
}

//return the size of the actually used buffer (excluded the terminator)
//that is equal to the length of the contained string
int StringBuffer::Length()
{
return length;
}
//if n is greater than Capacity() then the capacity is increased by
//a factor while internal capacity is not greater than n
void StringBuffer::EnsureCapacity(unsigned int n) throw()
{
unsigned int oldcapacity = capacity;

while (capacity < n)
{
capacity += capacity * factor / 100;
if(capacity <= oldcapacity)capacity=oldcapacity+1;
}

if(oldcapacity != capacity)
{
char * newbuffer;
newbuffer =(char*) realloc(buffer, capacity);
if(newbuffer == NULL) throw;
buffer = newbuffer;
}
}

//frees the unused portion of the buffer
void StringBuffer::TrimBuffer()
{
char * newbuffer;
newbuffer = (char*)realloc(buffer, length + 1);
buffer = newbuffer;
}

//return a pointer to the buffer. The buffer is returned as string
//of chars terminated by zero
char * StringBuffer::GetBuffer()
{
return buffer;
}

//Allocates new memory and copies the content of buffer into the new location
//the original buffer remains unaltered. Note that the dimension
//of the newly allocated memory is trimmed to the length (not capacity) of
//the original buffer
char * StringBuffer::CopyBuffer() throw()
{
char * p;
p = (char*) malloc(length + 1);
if (p==NULL) throw;
strcpy(p, buffer); //buffer is certainly terminated by zero
return p;
}

//creates a new buffer with 32 byte of capacity
//mantaining original increment
//the original buffer is cleanly destroyed
void StringBuffer::ReInit() throw()
{
Free();
capacity = original_capacity;

buffer =(char*) malloc(capacity);
if (buffer==NULL)throw;
}

//the original buffer is destroyed and capacity is set to 0
void StringBuffer::Free()
{
if(buffer)
free(buffer);
length=0;
capacity=0;
}

void StringBuffer::Empty()
{
length=0;
buffer[0]='\0';
}

int StringBuffer::GetCharAt (unsigned int pos)
{
if (pos > length) return -1;
return buffer[pos];

}

Andrea Simonassi
28-12-2001, 21:02
// by Andrea Simonassi 2001
// sorry for my bad english.

//A string buffer implements a mutable sequence of characters.

//Programmers should take care to protect this class against
//multithreaded functions; while multithreading is not portable
//this class don't implements any specific method of protection.

//A string buffer work in this way:
//while there is enough space to store new charachters simply append
//these to the buffer. When the space isn't enough the capacity of
//the buffer is increased by a factor%.
//If the increment done applying the factor
//doesn't exceed the old capacity then capacity will be increased by 1.

//================================================== ===================
//Particular care must be taken using the GetBuffer() method:
//the programmer must not free or modify this buffer while the
//object is alive.

//Before to destroy this object, the programmer must take the
//pointer to the buffer using the methog GetBuffer. In this case
//the programmer have the responsibility of the disallocation of
//the buffer. However if the programmer don't need this pointer
//can use the method Free of the object to release the heap space
//before to destroy the object. Mind that the destructor don't do
//this.

//example of what a programmer that readed this document never do

//StringBuffer * sb;
//sb = new StringBuffer();
//*sb += "Hello"
//*sb += " world"
//delete sb

//in this example we have lost 32 byte of precious heap space
//(or n*32 if we have a loop or m*n*32 if we have a nested loop)

//StringBuffer * sb;
//char * str;
//sb = new StringBuffer();
//*sb += "Hello"
//*sb += " world\n"
//str = sb->GetBuffer();
//printf(str);
//free(str);
//*sb += "It's a really nice day" //acc..
//str = sb->GetBuffer();
//printf(str);
//free(str);
//delete sb

//in this example we made the OS very irascible or damaged the program.


//Ideally one must use a StringBuffer many times.
//In this case we must use the CopyBuffer()
//method to save the actual buffer and then call the ReInit() method
//that empty the used buffer before reuse it or the Empty() method
//that voids the buffer without releasing the heap

//One can use the TrimBuffer() method before calling GetBuffer() to
//save memory, especially in that case of capacity is greatly bigger
//than length. Note that the method CopyBuffer() allocate a new
//buffer that have capacity = length + 1 so can contain buffer + '\0'.

//The append method, the constructor, the ReInit method, the EnsureCapacity
//method and the CopyBuffer method throw an exception if there is no memory.
//Normally a programmer in this case don't take an action but
//one must be conscious that the run time will stop the execution
//of the program immediatly, so:
//if the programmers know that he will handle a huge quantity of memory
//then he should use the try catch statements, else the possibility
//is so remote that is better to ignore this fact.


#ifndef _StringBuffer_h
#define _StringBuffer_h

class StringBuffer
{
private:
unsigned int original_capacity;
unsigned int capacity;
unsigned int length;
unsigned int factor;
char * buffer;
public:
//create a new empty string buffer with a capacity of 32 chars
//and an increment of 50%
StringBuffer() throw();
//create a empty string with a capacity of 'capacity' byte
//and an increment of factor%
//valid values for factor are between 0.05 and 50.
//reasonable values are between 0.5 and 1
//if the factor argument is not valid in debug situation
//an assertion will block the program, in release situation
//constructor throw.
StringBuffer(int capacity, unsigned int factor) throw();

//appends the string rappresentation of the input element to the buffer
void Append(int n) throw();
void Append(int n, int radix) throw();
void Append(char c) throw();
void Append(double n) throw();
void Append(char* c) throw();

//return the actual capacity of the buffer
int Capacity();
//return the size of the actually used buffer
int Length();
//if n is greater than Capacity() then the capacity is increased by
//a factor while internal capacity is not greater than n
void EnsureCapacity(unsigned int n) throw();

//frees the unused portion of the buffer
void TrimBuffer();

//return a pointer to the buffer. The buffer is returned as string
//of chars terminated by zero
char * GetBuffer();

//Allocates new memory and copies the content of buffer into the new location
//the original buffer remains unaltered. Note that the dimension
//of the newly allocated memory is trimmed to the length (not capacity) of
//the original buffer
char * CopyBuffer() throw();

//creates a new buffer with the same original capacity
//mantaining original increment
//the original buffer is cleanly destroyed
void ReInit() throw();

//the original buffer is destroyed
void Free();

//empty the buffer
void Empty();

//gets the character at the specified position(base 0), returns -1 if pos >= length
int GetCharAt(unsigned int pos);

};
#endif

metropolis999
28-12-2001, 23:28
ommadonnasantissima! :eek: :eek: :eek:

grazie mille (come sempre accorri in mio aiuto) ma... non c'è davvero un metodo più semplice?

dai un'occhiata qui:

http://forum.html.it/forum/showthread.php?threadid=165776

abbiamo provato ad arrampicarci su per gli specchi e qualcosa siamo riusciti a combinare ma... senza risultati, purtroppo, da parte mia :(

metropolis999
28-12-2001, 23:42
questo addirittura me lo compila e mi dice che ho fatto un danno!

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

main()

{

char *name;

name = new char;

cin >> name;

cout << name << endl;

delete (name);


return(0);

}

Andrea Simonassi
29-12-2001, 00:25
ovvio che non va bene dovevi fare new char[100] per esempio, ma non risolve il tuo problema.

Comunque devo aggiungere alcune cose al codice di cui sopra (i due file postati).

Prima di tutto esso è parte di HBPA un software open source del cui team di sviluppo faccio parte e che tra l'altro cerca volontari.

L'uso è facile, chi conosce java ha già di default un oggetto simile.

Ammetti di dover leggere una linea dall'input e di volerla ristampare in echo.




#include "stringbuffer.h"
#include <stdlib.h>
#include <iostream.h>

int main()
{
StringBuffer * sb;
int c;
char * stringa;
try{
sb = new StringBuffer(100,100);
//nuovo string buffer con capacità 100 e che si incrementa
//automaticamente del 100% quando raggiunge il limite della sua
//capacità
}
catch(void)
{
cerr << "Memoria insufficiente";
return 1;
}


while (cin.eof() == 0)
{
c = cin.get();

try
{
if(c != '\n')
sb->Append((char)c);
else break;
}
catch(void)
{
cerr << "memoria insufficiente";
return 1;
}
}
//libera memoria non usata
sb->TrimBuffer();
//si becca il buffer
stringa = sb->GetBuffer();
//elimina l'oggetto (notare che il buffer resta valido)
delete sb;
cout << stringa;
//libera il buffer
free(stringa);
return 0;
}

metropolis999
29-12-2001, 00:44
ma hai letto tutto il 3d? come mai a figaro funziona ad a me no?

Andrea Simonassi
29-12-2001, 01:08
perchè lavori nel namespace sbagliato

Loading