|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Treviso
Messaggi: 1386
|
[c] stringhe di lunghezza indefinita
C'è un modo per allocare una stringa senza sapere a priori la sua lunghezza e senza spreco di spazio?
cioè se io devo memorizzare una stringa immessa da un utente, devo inizializzarla o con dimensione n che stabilisco io o con n caratteri(+1 per lo /0) che mi passa l'utente. Ma senza che l'utente mi dica la dimensione, senza usare un'altra stringa aux e senza dare io un n grande, c'è un altro modo? |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
realloc, ma e' lenta.
In alternativa una struttura del tipo typedef struct { char stringa[100]; struct nodo* next; } nodo; se sfori allochi e aggiungi un altro nodo Forse c'e' un modo migliore, ma non mi viene in mente |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Nov 2001
Città: genova
Messaggi: 241
|
se il poroblema è occupare meno memoria possibile penso che la lista linkata sia l'ideale (per quello che ne so). io ne ho scritta una per dei numeri, ma modificarla per i caratteri non costa nulla. fatemi sapere se è una soluzione valida, sto studiando c++ in uni e la cosa mi interessa. altrimenti puoi allocare dinamicamente un array in memoria (ma devi passargli la grandezza). il prob della lista linkata è che la svuoti dall'alto (l'ultima cosa entrata è quella che esce per prima). per risolvere potresti usare la lista linkata circolare, dove immetti in coda e peschi in testa (per stampare stringhe va benissimo)
array..... Codice:
int n; char *v; v = new char[n] lista linkata... Codice:
#include <iostream.h>
#ifndef STACK_H
#define STACK_H
#include "ListNode.h"
class Stack {
public:
Stack() {
top = NULL;
}
bool isEmpty() const {
return top == NULL;
}
void set(int x) {
ListNode *temp;
temp = new ListNode(x);
temp->ptrNext = top;
top = temp;
}
int get() {
int v = top->value;
ListNode *temp = top;
top = top->ptrNext;
delete temp;
return v;
}
private:
ListNode *top;
};
#endif
Codice:
#include <iostream.h>
#ifndef LISTNODE_H
#define LISTNODE_H
class ListNode {
friend class Stack;
public:
ListNode(int n)
{
ptrNext = NULL;
value = n;
}
private:
int value;
ListNode *ptrNext;
};
#endif
Ultima modifica di michele.t : 11-12-2003 alle 18:34. |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
Codice:
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Stack
{
public:
// Constructor with dimension
Stack(int dim) { vet = new T[checkDim(dim)]; };
// Constructor without dimension
Stack() { vet = new T[5]; };
// Check and verify the chosed dimensione
int checkDim(int dim) { return(dim <= 0)?5:dim; };
// The destructor
~Stack(){};
// add a element
void push(T * value) { vet[sp++] = value; };
// return a element (and no delete)
T pop() { return vet[sp--]; };
private:
T * vet;
int sp;
};
__________________
Gnu/Linux User
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Raga...qui si parla di C...non di C++
Concordo con lista linkata di lovaz, ma l'input a questo punto andrà gestito carattere per carattere (oppure sfruttando la fgets sullo stdin)... |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Treviso
Messaggi: 1386
|
Si a me serve in c liscio
Non abbiamo ancora fatto tutto all'unive, infatti non sapevo si potesse dare il comando struct nodo* next; dentro la definizione di nodo... devo studiarci sopra... grazie intanto. |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Utilizza una malloc
char * pippo = (char*)malloc(numero_caratteri + 1); memset(pippo, 0, numero_caratteri + 1); alla fine quando non ti serve + usa free(pippo); se in corso d'opera devi modificarne la lunghezza usa la realloc. Il + 1 è per il tappo finale (0 binario).
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Nov 2001
Città: genova
Messaggi: 241
|
era c! oooppsss
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Quote:
Chiaramente dall'input può arrivare una qualsiasi lunghezza e se non puoi limitarla devi dettare delle regole di lunghezza massima. Ma questo è l'unico modo di gestione dinamico che c'è in C. In C++ in particolare in MFC puoi trovarelasse CString (se nn ricordo male anche in Borland C++ Builder) che gestisce lunghezze dinamiche.
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Provate questo (non l'ho debuggato, l'ho scritto così al volo): Codice:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define VARSTR_LEN 10
struct svarstr {
char str[VARSTR_LEN];
struct svarstr *next;
};
typedef struct svarstr* varstr;
void free_varstr(varstr str)
{
varstr tmp;
do {
tmp = str->next;
free(str);
str = tmp;
} while(str);
}
void write(varstr str, FILE *f = stdout)
{
do {
fprintf(f, "%s", str->str);
str = str->next;
} while(str);
}
varstr read(FILE *f = stdin)
{
varstr str, tmp;
int i;
str = (varstr)malloc(sizeof(svarstr));
str->next = NULL;
tmp = str;
while(1)
{
if(fgets(tmp->str, VARSTR_LEN, f) == NULL)
{
fprintf(stderr, "fgets error\n");
free_varstr(str);
return NULL;
}
if(strlen(tmp->str) < (VARSTR_LEN-1) || tmp->str[VARSTR_LEN-2] == '\n')
{
tmp->str[strlen(tmp->str)-1] = '\0';
return str;
}
else
{
tmp->next = (varstr)malloc(sizeof(svarstr));
tmp = tmp->next;
tmp->next = NULL;
}
}
}
int main()
{
varstr str;
str = read();
write(str);
free_varstr(str);
getchar();
}
Ultima modifica di cionci : 13-12-2003 alle 18:46. |
|
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Quote:
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
In realta' ripensandoci la cosa migliore in questo caso e' usare realloc, avendo l'accortezza di non chiamarla a ogni carattere, ma di far crescere la stringa di un tot di byte alla volta.
Per es.: stringa iniziale di 100 byte quando sto per esaurire lo spazio realloc con dimensione 200 byte, poi 300 byte, e cosi' via. |
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Secondo me c'è poco da fare... se non si conosce la lunghezza iniziale di una stringa occorre controllare l'input dell'utente.
Se l'input è dos, si utilizzano gli interrupt (l'interrupt) relativi allinput da tastiera. Altrimenti se è windows si gestiscono i messaggi relativi alla casella di testo (che poi non ce ne sarebbe bisogno lestringhe sono davero davvero dinamiche) Ogni malloc o realloc vuole la size come parametro. Ma se quella fgets legge dallo stdin come gli si può passare una stringa di lunghezza completamente dinamica?
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
fgetc?
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Quote:
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
Si', per sapere la lunghezza della stringa devi "contare" i caratteri.
Oppure usare qualche libreria, tipo la readline, ma non l'ho mai usata. |
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Ah le librerie le risolvono queste cose. Su quello alzo le mani. Ma se nn si vuol utilizzare nessuna libreria occorre solo gestire fisicamente e a basso livello l'input dell'utente. Cosa che probabilmente fanno gia le librerie.
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
Ora io sono un po' arrugginito sul c, ma usando la fgetc o analoga non puoi leggere l'input un char alla volta e agire di conseguenza? Magari riallocando?
|
|
|
|
|
|
#20 | |
|
Senior Member
Iscritto dal: Nov 2003
Città: Napoli
Messaggi: 6193
|
Quote:
Tu la faresti un interfaccia nella quale devi inserire il nome di un libro, ad esempio, e lo devi inserire lettera per lettera (lettera+invio, lettera+invio)?
__________________
Diablo3 PF | MyPC(liquidato) - Case Corsair Obsidian 800D / PSU Enermax Galaxy 1000W / MB GA-EX58A-UD7 / CPU Intel I7 920 [email protected] / MEM Corsair Dom. GT@1680mhz / GPU R9 290X / HD 2xWD 150GB raid 0/ SO - Windows 7 Ult. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:32.


















