|
|
|
![]() |
|
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 17: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 D0@4.1ghz / 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 D0@4.1ghz / 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 17: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 D0@4.1ghz / 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 D0@4.1ghz / 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 D0@4.1ghz / 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 D0@4.1ghz / 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 D0@4.1ghz / 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: 17:46.