Forum - C/C++
- Problemi di aritmetica dei puntatori
spode (Normal User)
Pro
Messaggi: 151
Iscritto: 03/09/2010
Ciao!
Potreste aiutarmi con questo codice:
Codice sorgente - presumibilmente C++
char * strBetweenPointersReverse( const char * yourstring, const char * pos1, const char * pos2, char whereToPut[ ] ) {
#if DEBUG
puts ( "\n stringBetweenReverse()" ) ;
printf ( "\n yourstring %s" , yourstring) ;
#endif
strcpy ( whereToPut, yourstring) ;
strdelete( whereToPut, whereToPut, pos1) ; //non mi dà problemi
strdelete( whereToPut, pos2, whereToPut+ strlen ( whereToPut) ) ; //qui ho problemi
return whereToPut;
}
dove yourstring = ""-13+2*41\0", pos1 = "-13+2*41" (posizione 0 di yourstring) e pos2="2*41" (posizione 6 di yourstring).
Codice sorgente - presumibilmente C#
char * strdelete( char * where, char * from_inc, char * to_inc) {
if ( to_inc == NULL || from_inc == NULL || where == NULL ) return where;
char temp[ strlen( where) - ( to_inc- from_inc) + 1] ; //in particolare noto che la differenza tra i puntatori non dà il risultato atteso =(
int pos= 0 ;
for ( ; ( from_inc- ( where+ pos) ) != 0 ; pos++ )
* ( temp+ pos) = * ( where+ pos) ;
for ( int posTo_inc= 1 ; * ( to_inc+ posTo_inc) != '\0 ' ; posTo_inc++ ,pos++ )
* ( temp+ pos) = * ( to_inc+ posTo_inc) ;
* ( temp+ pos) = '\0 ' ;
strcpy( where,temp) ;
return where;
}
Ho rilevato che il risultato non è quello atteso per via di to_inc-from_inc: eppure puntano entrambi a youstring... ci sono casi in cui lavora bene e altri in cui non va, tipo quello menzionato sopra.
pierotofy (Admin )
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
Che compilatore stai usando?
spode (Normal User)
Pro
Messaggi: 151
Iscritto: 03/09/2010
Ciao! GCC con Eclipse Luna per il debug, sotto OpenSuse 13.1 e hardware...beh il processore è un vecchio Intel Dual core.
Ultima modifica effettuata da spode il 06/08/2014 alle 13:42
pierotofy (Admin )
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
Dovresti postarci il codice completo... in particolare come viene chiamata strBetweenPointersReverse.
spode (Normal User)
Pro
Messaggi: 151
Iscritto: 03/09/2010
Codice sorgente - presumibilmente C++
/*
Ottiene "(132-2*51)"
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define DEBUG 0
#define NUMERO 19 //numero max caratteri per a,b e k in k=ax+by e MCD(a,b)
long int powi( int num, int exp ) { //10^0
long int ris= 1 ;
while ( exp-- )
ris= ris* num;
return ris;
}
int intlen( int num) {
int i= 1 ;
while ( num/ powi( 10,i) ! = 0)
i++ ;
return i;
}
/*
* Delete characters from where starting from from_included position to to_included position.
* Positions included in the process of deleting.
*
* Example:
* where = +1*51-1*132+1*51\0
* from_included = 0, to_included=4
* OutPut: where = -1*132+1*51\0
* */
void strdeleteAt( char where[ ] , const int from_included, const int to_included) {
char temp[ strlen ( where) - ( to_included- from_included) + 1] ;
int i;
for ( i= 0 ; i< from_included; i++ )
temp[ i] = where[ i] ;
strcpy ( temp+ i, where+ to_included+ 1) ;
strcpy ( where, temp) ;
}
/*
* Deletes characters in where starting from from_inc position to to_inc position.
* Positions included in the process of deleting.
*
* Warning: passing a NULL pointer causes where to be returned.
*
* Example:
* where = +1*51-1*132+1*51\0
* from_inc = strstr(where, "+");
* to_inc=strstr(where, "*");
* OutPut: where = 51-1*132+1*51\0
*/
char * strdelete( char where[ ] , char * from_inc, char * to_inc) {
if ( to_inc == NULL || from_inc == NULL || where == NULL ) return where;
printf ( "\n where: %s %d\n to_inc: %s %d\n from_inc: %s %d" , where, strlen ( where) , to_inc, strlen ( to_inc) , from_inc, strlen ( from_inc) ) ;
short len = strlen ( where) - ( to_inc- from_inc) + 1 ; //from inc è pos 1 => errore
int pos= 0 ;
if ( len <= 0) return where;
char temp[ len] ;
for ( ; from_inc- ( where+ pos) ! = 0 ; pos++ )
* ( temp+ pos) = * ( where+ pos) ;
for ( int posTo_inc= 1 ; * ( to_inc+ posTo_inc) ! = '\0 ' ; posTo_inc++ ,pos++ )
* ( temp+ pos) = * ( to_inc+ posTo_inc) ;
* ( temp+ pos) = '\0 ' ;
strcpy ( where,temp) ;
return where;
}
char * int2string( const int toBeParsed, char * whereToPut) { //-1
char digits[ ] = "0123456789" ;
int pos = 0, len= intlen( toBeParsed) ;
if ( toBeParsed<= 0 ) {
* whereToPut = '-' ;
pos++ ;
}
/* Determine the integer and putting it into whereToPut.
* for 38:
* whereToPut[0] = digits[38/10 -10*(38/100)] = '3'
* whereToPut[1] = digits[38/1 - 10*(38/10)] = '8'
* whereToPut => "38\0"
*/
while ( len-- > 0)
* ( whereToPut + pos++ ) = digits[ abs ( toBeParsed) / powi( 10,len) - 10* ( abs ( toBeParsed) / powi( 10,len+ 1) ) ] ;
* ( whereToPut+ pos) = '\0 ' ;
#if DEBUG
printf ( "\n \t int2string. toBeParsed=%d; whereToPut=%s\n " ,toBeParsed, whereToPut) ;
#endif
return whereToPut;
}
char * substringAt( char where[ ] , int from_included, int to_included, char whereToPut[ ] ) {
int pos = 0 ;
for ( ; to_included >= from_included; from_included++ , pos++ )
* ( whereToPut+ pos) = * ( where+ from_included) ;
* ( whereToPut+ pos) = '\0 ' ;
return whereToPut;
}
char * substringAtstrstr( const char where[ ] , char * from_included, const char * to_included, char whereToPut[ ] ) {
if ( to_included == NULL )
return strcpy ( whereToPut, from_included) ;
int pos = 0 ;
for ( ; to_included >= from_included; from_included++ , pos++ )
* ( whereToPut+ pos) = * ( from_included) ;
* ( whereToPut+ pos) = '\0 ' ;
return whereToPut;
}
int countChars( const char where[ ] , const char character) {
int cont = 0 ;
for ( ; * where; where++ )
if ( * where == character) cont++ ;
return cont;
}
_Bool strcontain( const char where[ ] , const char character) {
return countChars( where, character) ;
}
_Bool strcontainArray( const char where[ ] , const char characters[ ] , const short charactersLen)
{
_Bool r= 1 ;
for ( int i= 0 ; i< charactersLen && r; i++ )
r = r && countChars( where, characters[ i] ) ;
return r;
}
char * strstrArray( const char where[ ] , const char chars[ ] , const short charsLeng) {
//restituire l'occorrenza più vicina a where di una delle stringhe in chars. Per esempio per 132-2*51 e 132+2*51
char * occ = NULL ;
for ( int i= 0 ; i < charsLeng; i++ )
for ( int pos = 0 ; * ( where+ pos) ; pos++ )
if ( * ( where+ pos) == chars[ i] )
if ( occ == NULL )
{
occ = where+ pos;
pos = strlen ( where) - 1 ;
}
else
if ( occ ! = NULL && where+ pos < occ)
{
occ = where+ pos;
pos = strlen ( where) - 1 ;
}
return occ;
}
void emptystring( char string[ ] ) {
while ( * string++ = '\0 ' ) ;
}
char * strBetweenPointersReverse( const char * yourstring, char * pos1, char * pos2, char whereToPut[ ] ) {
#if DEBUG
puts ( "\n stringBetweenReverse()" ) ;
printf ( "\n yourstring %s" , yourstring) ;
#endif
strcpy ( whereToPut, yourstring) ;
strdelete( whereToPut, whereToPut, pos1) ;
strdelete( whereToPut, pos2, whereToPut+ strlen ( whereToPut) ) ;
return whereToPut;
#if DEBUG
printf ( "\n whereToPut = %s" , whereToPut) ;
#endif
}
/*
* This function find the first addend's components of an expression.
*
* @Params:
* exp is the expression where you want to find the first addend;
* mul2 is the memory location where the multiplier will be put. Must be "" when passed;
* num is the memory location where the number will be put. Must be "" when passed.
*
* @returns:
* true if the first addend was found. false otherwise.
*
* Example:
* exp = "è?(["; mul2 = ""; num = ""
* Output: mul2 = ""; ncum = ""
*
* Example :
* exp = "2*132-51"; mul2 = ""; num = ""
* Output: mul2 = "2", num = "132
* */
_Bool findAddendCmpts( const register char exp [ ] , char mul2[ ] , char num[ ] ) {
char signs[ ] = { '+' ,'-' } , * endnum = strstrArray( exp + 1, signs, 2) ;
if ( endnum ! = NULL )
endnum-- ;
if ( * ( exp ) == '-' ) //132-2*51; -132-2*51; 2*132-2*51; -2*132-2*51; 132; -132; -2*132; 2*132
if ( strcontain( exp , '*' ) && strstrArray( exp , signs,2) < strstr ( exp , "*" ) )
{ //-132-2*51; -2*132-2*51; -2*132
char r[ 9+ 1] ;
strcpy ( r,strBetweenPointersReverse( exp , strstr ( exp , "-" ) , strstr ( exp , "*" ) - 1, mul2) ) ;
if ( strcontainArray( r, signs, 2 ) ) //is there, next to + or -, a number?
{ //-132-2*51
strcpy ( mul2, "-1" ) ; //sure that exp contains *
substringAtstrstr( exp , exp + 1, endnum, num) ;
}
else
{ //-2*132-2*51; -2*132
substringAtstrstr( exp , mul2+ 2, strstrArray( mul2+ 2, signs, 2) , num) ;
}
}
else //-132
{
strcpy ( mul2, "-1" ) ;
substringAtstrstr( exp , exp + 1, endnum, num) ;
}
else //132-2*51; 2*132-2*51; 132; 2*132
if ( strcontain( exp + 1 , '-' ) || strcontain( exp + 1 , '+' ) )
{ //132-2*51; 2*132-2*51
if ( strcontain( exp , '*' ) && strstr ( exp , "*" ) < strstrArray( exp , signs, 2 ) ) //2*132-2*51
{
substringAtstrstr( exp ,exp , strstr ( exp , "*" ) - 1, mul2) ;
substringAtstrstr( exp , strstr ( exp ,"*" ) + 1, endnum, num) ;
}
else //132-2*51
{
strcpy ( mul2, "1" ) ;
substringAtstrstr( exp , exp , endnum, num) ;
}
}
else
if ( strcontain( exp , '*' ) )
{ //2*132
substringAtstrstr( exp , exp , strstr ( exp , "*" ) - 1, mul2) ;
substringAtstrstr( exp , strstr ( exp , "*" ) + 1, endnum, num) ; //all right with NULL ;) (see substringAtstrstr
}
else
{ //132 that must be multiplied per n
strcpy ( mul2, "1" ) ;
if ( * exp == '+' )
exp ++ ;
strcpy ( num, exp ) ;
}
if ( strcmp ( num, "" ) == 0 || strcmp ( mul2, "" ) == 0)
return 0 ;
else
return 1 ;
}
char * distribute( const char sign, char mul1[ ] , char exp [ ] , char result[ ] ) {
char mul2[ 5 + 1 ] , num[ 5 + 1 ] , signs[ ] = { '+' , '-' } , * occ= NULL ;;
short lung = 0, pos = 0 ;
while ( findAddendCmpts( exp + pos, mul2, num) )
{
if ( ( occ= strstrArray( exp + pos+ 1, signs, 2) ) ! = NULL )
pos+ = occ - ( exp + pos) ;
else pos+ = strlen ( exp + pos) ;
int mulDone = atoi ( mul2) * atoi ( mul1) ;
if ( mulDone > 0) {
strcat ( result, "+" ) ;
lung++ ;
}
char wtp[ intlen( mulDone) + 1] ;
strcat ( result, int2string( mulDone, wtp) ) ;
lung+ = intlen( mulDone) ;
strcat ( result, "*" ) ;
lung++ ;
strcat ( result, num) ;
lung+ = strlen ( num) ;
* ( result+ lung+ 2 ) = '\0 ' ;
* num = '\0 ' ;
* mul2 = '\0 ' ;
}
return result;
}
int main( void ) {
char wtp[ 10 ] = "" ;
char exp [ ] = "-13+2*41" ;
printf ( "\n distribuzione: 2* (%s) =\n %s" ,exp ,distribute( '+' , "2" , exp , wtp) ) ;
//dovrei ottenere "-2*13+4*41"
return 0 ;
}
Ultima modifica effettuata da spode il 06/08/2014 alle 20:16
spode (Normal User)
Pro
Messaggi: 151
Iscritto: 03/09/2010
Codice sorgente - presumibilmente C++
/*
Ottiene "(132-2*51)"
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define DEBUG 0
#define NUMERO 19 //numero max caratteri per a,b e k in k=ax+by e MCD(a,b)
long int powi( int num, int exp ) { //10^0
long int ris= 1 ;
while ( exp-- )
ris= ris* num;
return ris;
}
int intlen( int num) {
int i= 1 ;
while ( num/ powi( 10,i) ! = 0)
i++ ;
return i;
}
/*
* Delete characters from where starting from from_included position to to_included position.
* Positions included in the process of deleting.
*
* Example:
* where = +1*51-1*132+1*51\0
* from_included = 0, to_included=4
* OutPut: where = -1*132+1*51\0
* */
void strdeleteAt( char where[ ] , const int from_included, const int to_included) {
char temp[ strlen ( where) - ( to_included- from_included) + 1] ;
int i;
for ( i= 0 ; i< from_included; i++ )
temp[ i] = where[ i] ;
strcpy ( temp+ i, where+ to_included+ 1) ;
strcpy ( where, temp) ;
}
/*
* Deletes characters in where starting from from_inc position to to_inc position.
* Positions included in the process of deleting.
*
* Warning: passing a NULL pointer causes where to be returned.
*
* Example:
* where = +1*51-1*132+1*51\0
* from_inc = strstr(where, "+");
* to_inc=strstr(where, "*");
* OutPut: where = 51-1*132+1*51\0
*/
char * strdelete( char where[ ] , char * from_inc, char * to_inc) {
if ( to_inc == NULL || from_inc == NULL || where == NULL ) return where;
short len = strlen ( where) - ( strlen ( from_inc) - strlen ( to_inc) ) + 1 ; //from inc è pos 1 => errore
if ( len <= 0) return where;
register int pos= 0 ;
char temp[ len] ;
for ( ; strlen ( where+ pos) - strlen ( from_inc) + 1 ! = 0 ; pos++ )
* ( temp+ pos) = * ( where+ pos) ;
for ( register int posTo_inc= 1 ; * ( to_inc+ posTo_inc) ! = '\0 ' ; posTo_inc++ ,pos++ )
* ( temp+ pos) = * ( to_inc+ posTo_inc) ;
* ( temp+ pos) = '\0 ' ;
strcpy ( where,temp) ;
return where;
}
char * int2string( const int toBeParsed, char * whereToPut) { //-1
char digits[ ] = "0123456789" ;
int pos = 0, len= intlen( toBeParsed) ;
if ( toBeParsed<= 0 ) {
* whereToPut = '-' ;
pos++ ;
}
/* Determine the integer and putting it into whereToPut.
* for 38:
* whereToPut[0] = digits[38/10 -10*(38/100)] = '3'
* whereToPut[1] = digits[38/1 - 10*(38/10)] = '8'
* whereToPut => "38\0"
*/
while ( len-- > 0)
* ( whereToPut + pos++ ) = digits[ abs ( toBeParsed) / powi( 10,len) - 10* ( abs ( toBeParsed) / powi( 10,len+ 1) ) ] ;
* ( whereToPut+ pos) = '\0 ' ;
#if DEBUG
printf ( "\n \t int2string. toBeParsed=%d; whereToPut=%s\n " ,toBeParsed, whereToPut) ;
#endif
return whereToPut;
}
char * substringAt( char where[ ] , int from_included, int to_included, char whereToPut[ ] ) {
int pos = 0 ;
for ( ; to_included >= from_included; from_included++ , pos++ )
* ( whereToPut+ pos) = * ( where+ from_included) ;
* ( whereToPut+ pos) = '\0 ' ;
return whereToPut;
}
char * substringAtstrstr( const char where[ ] , char * from_included, const char * to_included, char whereToPut[ ] ) {
if ( to_included == NULL )
return strcpy ( whereToPut, from_included) ;
int pos = 0 ;
for ( ; to_included >= from_included; from_included++ , pos++ )
* ( whereToPut+ pos) = * ( from_included) ;
* ( whereToPut+ pos) = '\0 ' ;
return whereToPut;
}
int countChars( const char where[ ] , const char character) {
int cont = 0 ;
for ( ; * where; where++ )
if ( * where == character) cont++ ;
return cont;
}
_Bool strcontain( const char where[ ] , const char character) {
return countChars( where, character) ;
}
_Bool strcontainArray( const char where[ ] , const char characters[ ] , const short charactersLen)
{
_Bool r= 1 ;
for ( int i= 0 ; i< charactersLen && r; i++ )
r = r && countChars( where, characters[ i] ) ;
return r;
}
char * strstrArray( const char where[ ] , const char chars[ ] , const short charsLeng) {
//restituire l'occorrenza più vicina a where di una delle stringhe in chars. Per esempio per 132-2*51 e 132+2*51
char * occ = NULL ;
for ( int i= 0 ; i < charsLeng; i++ )
for ( int pos = 0 ; * ( where+ pos) ; pos++ )
if ( * ( where+ pos) == chars[ i] )
if ( occ == NULL )
{
occ = where+ pos;
pos = strlen ( where) - 1 ;
}
else
if ( occ ! = NULL && where+ pos < occ)
{
occ = where+ pos;
pos = strlen ( where) - 1 ;
}
return occ;
}
void emptystring( char string[ ] ) {
while ( * string++ = '\0 ' ) ;
}
char * strBetweenPointersReverse( const char * yourstring, char * pos1, char * pos2, char whereToPut[ ] ) {
#if DEBUG
puts ( "\n stringBetweenReverse()" ) ;
printf ( "\n yourstring %s" , yourstring) ;
#endif
strcpy ( whereToPut, yourstring) ;
strdelete( whereToPut, whereToPut, pos1) ;
strdelete( whereToPut, pos2, whereToPut+ strlen ( whereToPut) - 1) ;
return whereToPut;
#if DEBUG
printf ( "\n whereToPut = %s" , whereToPut) ;
#endif
}
/*
* This function find the first addend's components of an expression.
*
* @Params:
* exp is the expression where you want to find the first addend;
* mul2 is the memory location where the multiplier will be put. Must be "" when passed;
* num is the memory location where the number will be put. Must be "" when passed.
*
* @returns:
* true if the first addend was found. false otherwise.
*
* Example:
* exp = "è?(["; mul2 = ""; num = ""
* Output: mul2 = ""; ncum = ""
*
* Example :
* exp = "2*132-51"; mul2 = ""; num = ""
* Output: mul2 = "2", num = "132
* */
_Bool findAddendCmpts( const register char exp [ ] , char mul2[ ] , char num[ ] ) {
char signs[ ] = { '+' ,'-' } , * endnum = strstrArray( exp + 1, signs, 2) ;
if ( endnum ! = NULL )
endnum-- ;
if ( * ( exp ) == '-' ) //132-2*51; -132-2*51; 2*132-2*51; -2*132-2*51; 132; -132; -2*132; 2*132
if ( strcontain( exp , '*' ) && strstrArray( exp , signs,2) < strchr ( exp , '*' ) )
{ //-132-2*51; -2*132-2*51; -2*132
if ( strcontainArray( strBetweenPointersReverse( exp , strchr ( exp , '-' ) , strchr ( exp , '*' ) - 1 , mul2) , signs, 2 ) ) //is there, next to + or -, a number?
{ //-132-2*51
strcpy ( mul2, "-1" ) ; //sure that exp contains *
substringAtstrstr( exp , exp + 1, endnum, num) ;
}
else
{ //-2*132-2*51; -2*132
substringAtstrstr( exp , mul2+ 2, strstrArray( mul2+ 2, signs, 2) , num) ;
}
}
else //-132
{
strcpy ( mul2, "-1" ) ;
substringAtstrstr( exp , exp + 1, endnum, num) ;
}
else //132-2*51; 2*132-2*51; 132; 2*132
if ( strcontain( exp + 1 , '-' ) || strcontain( exp + 1 , '+' ) )
{ //132-2*51; 2*132-2*51
if ( strcontain( exp , '*' ) && strstr ( exp , "*" ) < strstrArray( exp , signs, 2 ) ) //2*132-2*51
{
substringAtstrstr( exp ,exp , strstr ( exp , "*" ) - 1, mul2) ;
substringAtstrstr( exp , strstr ( exp ,"*" ) + 1, endnum, num) ;
}
else //132-2*51
{
strcpy ( mul2, "1" ) ;
substringAtstrstr( exp , exp , endnum, num) ;
}
}
else
if ( strcontain( exp , '*' ) )
{ //2*132
substringAtstrstr( exp , exp , strstr ( exp , "*" ) - 1, mul2) ;
substringAtstrstr( exp , strstr ( exp , "*" ) + 1, endnum, num) ; //all right with NULL ;) (see substringAtstrstr
}
else
{ //132 that must be multiplied per n
strcpy ( mul2, "1" ) ;
if ( * exp == '+' )
exp ++ ;
strcpy ( num, exp ) ;
}
if ( strcmp ( num, "" ) == 0 || strcmp ( mul2, "" ) == 0)
return 0 ;
else
return 1 ;
}
char * distribute( const char sign, char mul1[ ] , char exp [ ] , char result[ ] ) {
char mul2[ 5 + 1 ] , num[ 5 + 1 ] , signs[ ] = { '+' , '-' } , * occ= NULL ;;
short lung = 0, pos = 0 ;
while ( findAddendCmpts( exp + pos, mul2, num) )
{
if ( ( occ= strstrArray( exp + pos+ 1, signs, 2) ) ! = NULL )
pos+ = occ - ( exp + pos) ;
else pos+ = strlen ( exp + pos) ;
int mulDone = atoi ( mul2) * atoi ( mul1) ;
if ( mulDone > 0) {
strcat ( result, "+" ) ;
lung++ ;
}
char wtp[ intlen( mulDone) + 1] ;
strcat ( result, int2string( mulDone, wtp) ) ;
lung+ = intlen( mulDone) ;
strcat ( result, "*" ) ;
lung++ ;
strcat ( result, num) ;
lung+ = strlen ( num) ;
* ( result+ lung+ 2 ) = '\0 ' ;
* num = '\0 ' ;
* mul2 = '\0 ' ;
}
return result;
}
int main( void ) {
char wtp[ 10 ] = "" ;
char exp [ ] = "-13+2*41" ;
printf ( "\n distribuzione: 2* (%s) =\n %s" ,exp ,distribute( '+' , "2" , exp , wtp) ) ;
return 0 ;
}
Ora va bene. Ho praticamente usato strchr anzichè strstr e poi ho usato strlen su ciò che viene restituito da strchr nella funzione strdelete. Ma perchè ora va bene e prima no?
P.S.: il doppio post era d'obbligo secondo me. Inoltre ho un problema per l'amministratore: nella versione per cellulare (ottima
), in WP 8.0 Lumia 520, ho rilevato che ogni post viene sdoppiato.
Ultima modifica effettuata da spode il 07/08/2014 alle 13:40