Errore a imprecisione di 1 , a volte anche 2

di il
7 risposte

Errore a imprecisione di 1 , a volte anche 2

Salve,ho sviluppato questo codice per rendere giustificato il testo scritto in una riga di 65 caratteri, MA a volte funziona e a volte no, sballando la riga di 1 o 2 caratteri in + o in -.
Quando modifico i valori "i += 65" in "i += 66" succede che la stringa che andava male dopo va bene e viceversa, comunque quelle che va meglio con un pò tutte le stringhe è 65.
Che cosa può essere???????

ecco a voi il codice
#include <stdio.h>
#include <string.h>

void stringtok(char *, char *);

int main() {

	char *string, empty[1000] = "\0";

	gets(string);
	stringtok(string,empty);
	printf("\n%s\n", empty);

	return 0;
} //fine main

void stringtok(char *string, char *empty) {

	void insertspace(char *, char *, int);
	int i = 64, x;
	size_t len;

	len = strlen(string);

	while (i <= len) {
		x = 1;
		if(string[i + 1] == ' ' && string[i] != ' ') {
			string[++i] = '\n';
			insertspace(string,empty, 0);
		}
		else if(string[i] == ' ') {
			string[i] = '\n';
			insertspace(string,empty ,1);
		}
		else if(string[i] != ' ') {
			while (--i) {
				++x;
				if (string[i] == ' ') {
					string[i] = '\n';
					insertspace(string,empty, x);
					break;
				}
			}
		}
		i += 65;
	}
	insertspace(string,empty, 0);
} // fine stringtok

void insertspace(char *Ptr, char *Ptr2, int X) {  //X = spazi da inserire

	int i, space = 0;
	static int x = 0, y = 0;
	if(X)
		for (i = x; Ptr[i] != '\n'; i += 1) //conta spazi disponibili
			if(Ptr[i] == ' ')
			 ++space;

	strcat(Ptr2, "          ");
	y += 10;

	for (; Ptr[x] != '\n'; y++, x++) {
		Ptr2[y] = Ptr[x];
		if (X && Ptr[x] == ' ') {
			if(space < X) {
				Ptr2[++y] = '*';
				Ptr2[++y] = '*';
				X--;
			}
			else {
				Ptr2[++y] = '*';
				--X;
			}
		}
	}
	Ptr2[y] = Ptr[x];
	Ptr[x] = ' ';
	++x;
	++y;
} //fine insertspace

/*If you happened to receive some new computer hardware this Christmas or are weighing a possible upgrade with Skylake PCs becoming more common and AMD Zen coming out next year, you might as well benchmark your system against our vast collection of other systems to see how the performance stacks up.*/

/*Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura, ché la diritta via era smarrita. Ahi quanto a dir qual era è cosa dura esta selva selvaggia e aspra e forte che nel pensier rinova la paura!*/
in fondo al codice ci sono 2 esempi nei commenti, dove uno funziona correttamente e l'altro no.

7 Risposte

  • Re: Errore a imprecisione di 1 , a volte anche 2

    Ad una prima superficiale occhiata, direi che la logica dell'algoritmo è gravemente errata.

    Assumiamo l'ipotesi di lavoro, altamente semplificata per partire, che ogni singolo spazio nella frase da formattare sia rigorosamente circondato da caratteri (alfanumerici + segni di interpunzione) e/o dai limiti della stringa, in particolare preceduto da un carattere nell'insieme suddetto e seguito in via mutuamente esclusiva o da un siffatto carattere o dal terminatore di stringa (l'eventuale spazio in testa è una singolarità insignificante e banalissima da eliminare, qualora presente).

    Partendo da un offset inizialmente nullo, ci si posiziona al carattere k-esimo della stringa da giustificare, dove k è ovviamente la colonna del margine destro. A questo punto, sono possibili solamente due stati, più un corner case:

    1) Il carattere alla locazione offset + k è un spazio.

    2) Caso opposto, dunque siamo entro una parola.

    Il terzo caso (terminatore di stringa) è banalmente liquidato entro un apposito ramo if() e non inficia il resto del lavoro.
    Il caso 1) è tanto banale quanto raro.

    Nel caso 2), si deve scorrere all'indietro la stringa fino a riportarsi nella condizione 1), ossia fino a trovare alla locazione che chiameremo posizione_attuale un singolo spazio al termine di una parola (considerata estensivamente come comprensiva di eventuale segno di interpunzione a seguire). Qui occorre procedere con la formattazione della porzione di stringa compresa tra le locazioni offset e offset + posizione_attuale, per poi stabilire il nuovo offset in corrispondenza di posizione_attuale.

    Si riapplica poi iterativamente quanto esposto in precedenza, partendo dal nuovo offset.
    Spero che l'esposizione in linguaggio naturale sia sufficientemente chiara (purtroppo non ho tempo né modo di produrre esempi di codice anche minimali in questo frangente).
  • Re: Errore a imprecisione di 1 , a volte anche 2

    M.A.W. 1968 ha scritto:


    Ad una prima superficiale occhiata, direi che la logica dell'algoritmo è gravemente errata.
    OMG! mi stai facendo preoccupare

    Ciao ,grazie per la risposta,comunque il mio algoritmo sembra, ripeto sembra, che faccia quello che tu hai descritto, sviluppato con semplicità e naturalezza e descritto come segue:in primo luogo ho suddiviso l'algoritmo in 2 funzioni, la 1A stringtok verifica solamente l'opportuno k-esimo elemento del vettore valutando 3 casi, il 1° if(string[i + 1] == ' ' && string != ' ') calcola se il k-esimo elemento è già nella locazione giusta, in questo caso non ce bisogno di formattazione ma di una semplice copia, il 2° else if(string == ' ') si trova su uno spazio ed in questo caso ha bisogno di un solo spazio per allinearsi a 65 caratteri, e il 3° else if(string != ' ') come descritto da te in precedenza va a ritroso nella stringa fino a ritrovare uno spazio per poi piazzargli un '\n per identificazione per poi passargli alla 2A funzione insertspace il numero di spazi da aggiungere, cosa che fanno anche gli altri 2 stati precedenti.
    In tutto ciò sono ancora confuso e non riesco a risolvere, non so dove ho sbagliato, in esercizi precedenti ho sempre fatto errori di imprecisione di 1 ma con piccole modifiche ad operatori come da >= a > o la modifica del valore di un operando risolvevo.
  • Re: Errore a imprecisione di 1 , a volte anche 2

    Tanto per cominciare questa

    gets(string);

    è sbagliata perché operi su un puntatore non allocato ... e questo pregiudica tutto il funzionamento successivo.
  • Re: Errore a imprecisione di 1 , a volte anche 2

    oregon ha scritto:


    Tanto per cominciare questa

    gets(string);

    è sbagliata perché operi su un puntatore non allocato ... e questo pregiudica tutto il funzionamento successivo.
    si lo so che la gets e deprecata e non dovrebbe essere usata, comunque sia con scanf sia con fgets fa lo stesso problema.
  • Re: Errore a imprecisione di 1 , a volte anche 2

    No ... non hai capito ... il problema non è la gets .... è il puntatore che utilizzi SENZA avere allocato la memoria !
  • Re: Errore a imprecisione di 1 , a volte anche 2

    oregon ha scritto:


    No ... non hai capito ... il problema non è la gets .... è il puntatore che utilizzi SENZA avere allocato la memoria !
    si anche creando un vettore comunque da sempre errore, sta di fatto che gets chiude la stringa inserendo un carattere di terminazione, poi il problema che ha l'algoritmo non centra niente con la dichiarazione di un puntatore a stringa.
  • Re: Errore a imprecisione di 1 , a volte anche 2

    In casi del genere, è opportuno procedere con una riscrittura progressiva del codice.
    Inizia ad implementare il caso più semplice, poi quello di scansione a ritroso. Per facilitare il lavoro, puoi anche copiare in un buffer transitorio la parte di stringa che occuperà la riga corrente, ossia quella compresa tra offset e posizione_corrente, usando ovviamente la strncpy e senza fare ricorso a delimitatori temporanei.

    Comunque gli off-by-one sono uno degli errori più comuni in C, e possono avere un gran numero di cause anche remote.
Devi accedere o registrarti per scrivere nel forum
7 risposte