Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλημερα, θελω ενα unsigned int (πχ 125) να μπορω να προσπελασω καθε ψηφιο του και να ξερω και το μεγεθος του(κατι σαν strlen()),εχετε καμια ιδέα.Ευχαριστω .

Δημοσ.

Ε κάνε αυτό που σου είπε ο migf1 μέσα σε ένα βρόχο, ώστε να παίρνεις το κάθε ψηφίο σε κάθε ανακύκλωση. Εφόσον μιλάς για δεκαδικό σύστημα, κάθε φορά που βρίσκεις το υπόλοιπο με το 10 παίρνεις το δεξιότερο ψηφίο.

Δημοσ.

Ή:

sprintf(num_str, "%u", num);   // efoson thes unsigned orizeis analoga
                               // to megethos tou num_str
digits_n = strlen(num_str);
for (i = 0; i < digits_n; i++)
    digits_v[i] = num_str[i] - 48;  // ASCII value of '0'

Πάντως είναι προτιμότερο αυτό που είπε ο migf1.

  • Like 2
Δημοσ.

Ή:

Πάντως είναι προτιμότερο αυτό που είπε ο migf1.

Ωραίος. Μια και καλείς sprintf μπορείς να διώξεις και την strlen και να το κάνεις:

 

 

digits_n = sprintf(num_str, "%u", num);   // efoson thes unsigned orizeis analoga
                               // to megethos tou num_str
for (i = 0; i < digits_n; i++)
    digits_v[i] = num_str[i] - '0';
  • Like 1
Δημοσ.

Ή ... :P

 

Code:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/****************************************************//**
 * Convert a positive integer to a cstring of the base-10
 * representation of the integer. The inputed integer may
 * be entered in decimal, octal or hexadecimal form, but
 * the resulting cstring always reflects the decimal form.
 *
 * Return a pointer to the created cstring, or NULL on error.
 * The caller is responsible for freeing up the returned cstring.
 *
 * The digcount argument, if non-NULL, passes to the caller
 * the count of the base-10 digits successfully converted.
 ********************************************************
 */
char *ulong_to_string( unsigned long int num, int *digcount )
{
	size_t sz = 8;        /* alloc-ahead size */
	size_t i=0, j=0;
	char   *ret  = NULL;
	char   *temp = NULL;

	ret = calloc(sz, 1);
	if ( NULL == ret ) {
		fputs( "*** calloc() failed!\n", stderr );
		goto ret_failure;
	}

	/* special case */
	if ( 0 == num ) {
		if ( NULL != digcount ) {
			*digcount = 1;
		}
		return memcpy( ret, "0", sizeof("0") );
	}

	/* general case */
	for (i=0; num > 0; i++) {
		if ( i == sz-1 ) {
			sz += sz;
			temp = realloc( ret, sz );
			if ( NULL == temp ) {
				free( ret );
				goto ret_failure;
			}
			ret = temp;
		}
		ret[i] = (char)(num % 10 + '0');
		num /= 10;
	}
	ret[i] = '\0';

	/* store the count of base-10 digits */
	if ( NULL != digcount ) {
		*digcount = i;
	}

	/* reverse the resulting cstring */
	for (j=0,--i; i > j; j++,i--) {
		char c = ret[i];
		ret[i] = ret[j];
		ret[j] = c;
	}

	return ret;

ret_failure:
	if ( NULL != digcount ) {
		*digcount = 0;
	}
	return NULL;
}

/****************************************************//**
 *
 ********************************************************
 */
int main( void )
{
	int n = 0;
	char *s = ulong_to_string( 1254879786, &n );

	printf( "%s (%d digits)\n", s, n );
	free( s );

	return 0;
}

 

 

Αν θέλεις και overflow-check, γίνεται πιο σύνθετο.

  • Like 1
Δημοσ.

Μια αλλη λυση για πληθος ψηφιων και για ατομικη επεξεργασια:

 

Για το πληθος οπως προτεινε και ο lion2486:

#include <math.h>

unsigned int getNDigits(const unsigned int n)
{
	return (int)(log10(n) + 1);
}

Και για ατομικη επεξεργασια:

unsigned int getDthDigit(unsigned int n, const unsigned int d)
{
	for(unsigned int i=0; i<d; i++) n /= 10;
	return n%10;
}

  • Like 1
Δημοσ.

Μια αλλη λυση για πληθος ψηφιων και για ατομικη επεξεργασια:

 

Για το πληθος οπως προτεινε και ο lion2486:

#include <math.h>

unsigned int getNDigits(const unsigned int n)
{
	return (int)(log10(n) + 1);
}
Και για ατομικη επεξεργασια:

unsigned int getDthDigit(unsigned int n, const unsigned int d)
{
	for(unsigned int i=0; i<d; i++) n /= 10;
	return n%10;
}

Ναι, αυτός είναι ο καθαρά μαθηματικός τρόπος. Δεν είμαι όμως σίγουρος ότι δεν έχει προβλήματα στην γενική περίπτωση, λόγω floating precision errors. Μπορεί να μην έχει, αλλά καλό είναι να το έχει υπόψη του όποιος το χρησιμοποιήσει, και να το ψάξει πρωτα.

Δημοσ.

Ωραίος. Μια και καλείς sprintf μπορείς να διώξεις και την strlen και να το κάνεις:

digits_n = sprintf(num_str, "%u", num);   // efoson thes unsigned orizeis analoga
                               // to megethos tou num_str
for (i = 0; i < digits_n; i++)
    digits_v[i] = num_str[i] - '0';

 

Λοιπόν,ο παρακάτω κώδικας απευθύνεται κυρίως στο φίλο gon1332 που ξέρω πως τα γουστάρει κάτι τέτοια, αλλά φυσικά και σε όποιον άλλον διαβάσει το νήμα και το βρει ενδιαφέρον:

 

Κώδικας:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/* Print specified msg (a-la printf) along with debugging information.
 */
#define DBGF( format, ... )                                       \
do {                                                              \
	int c_;                                                   \
	puts("*** RUNTIME ERROR CAUGHT ****");                    \
	fprintf(stderr, "*** File: %s | Line: %d | Func: %s()\n", \
		__FILE__, __LINE__, __func__);                    \
	fprintf(stderr, "%s", "*** ");                            \
	fprintf(stderr, (const char *)(format), __VA_ARGS__);     \
//	fflush(stderr);                                           \
        putchar( '\n' );                    \
} while(0)

/* --------------------------------------------------------------
 * char *vprintf_to_text():
 *
 * This function is a wrapper to ISO C99's vsnprintf(). It creates
 * dynamically the buffer needed to hold the printed output, and if
 * it succeeds it returns a pointer to it. On error, it returns NULL.
 *
 * NOTES:
 *   1. vargs MUST have been already initialized in the caller
 *      (by the va_start macro, and possibly subsequent va_arg
 *      calls).
 *   2. The returned buffer, if non-NULL, MUST be freed in the
 *      calling environment.
 *   3. The function is used in the function: printf_to_text()
 * --------------------------------------------------------------
 */
char *vprintf_to_text( const char *fmt, va_list vargs )
{
	int   nchars = 0;
	char  *buf = NULL;
	size_t bufsz = BUFSIZ;

	/* make buf to hold the text and pass it to vsnprintf */
	if ( NULL == (buf = calloc(1, bufsz)) ) {
		DBGF( "%s", "calloc failed!" );
		goto ret_failure;
	}
	nchars = vsnprintf( buf, bufsz, fmt, vargs );
	if ( nchars < 0 ) {
		DBGF( "%s", "vsnprintf failed!" );
		goto ret_failure;
	}

	/* Was buf too small to hold the text?
	 * Reallocate 1+nchars bytes and re-apply.
	 */
	if ( nchars >= (int)bufsz ) {
		char *try = NULL;
		bufsz = 1 + nchars;   /* for the NUL byte */
		try = realloc( buf, bufsz );
		if ( NULL == try ) {
			DBGF( "%s", "realloc failed!" );
			goto ret_failure;
		}
		buf = try;

		nchars = vsnprintf( buf, bufsz, fmt, vargs );
		if ( nchars < 0 ) {
			DBGF( "%s", "vsnprintf failed!" );
			goto ret_failure;
		}
	}

	return buf;

ret_failure:
	if ( buf ) {
		free( buf );
	}
	return NULL;
}

/* --------------------------------------------------------------
 * char *printf_to_text():
 *
 * This function is similar to ISO C99's snprintf() but it creates
 * dynamically the string needed to hold the print-out. It returns
 * the string, or NULL on error.
 * --------------------------------------------------------------
 */
char *printf_to_text( const char *fmt, ... )
{
	char  *txtout = NULL;

	if ( NULL == fmt ) {
		DBGF( "%s", "NULL pointer argument (fmt)" );
		return NULL;
	}

	va_list vargs;

	va_start( vargs, fmt );
	txtout = vprintf_to_text( fmt, vargs );
	va_end( vargs );

	return txtout;
}

/****************************************************//**
 *
 ********************************************************
 */
char *ullong_to_string( unsigned long long int num, size_t *digcount )
{
	char *ret = printf_to_text( "%llu", num );
	if ( NULL == ret ) {
		DBGF( "%s", "printf_to_text() failed" );
		if ( NULL != digcount ) {
			*digcount = 0;
		}
		return NULL;
	}

	if ( NULL != digcount ) {
		*digcount = strlen( ret );
	}
	return ret;
}

/****************************************************//**
 *
 ********************************************************
 */
int main( void )
{
	size_t n = 0;
	char *s = ullong_to_string( 1254879786879834, &n );

	printf( "%s (%d digits)\n", s, n );
	free( s );

	return 0;
}

 

Όλα τα λεφτά είναι η συνάρτηση: vprintf_to_text() και αμέσως μετά η printf_to_text() που την χρησιμοποιεί.

Ο κώδικας είναι C99, και ουσιαστικά είναι copy & paste από τον κώδικα του 2048cc για όποιον το θυμάται (και πιο συγκεκριμένα από το πηγαίο: common.c).

  • Like 1
Δημοσ.

Κώδικας:

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/* Print specified msg (a-la printf) along with debugging information.
 */
#define DBGF( format, ... )                                       \
do {                                                              \
	int c_;                                                   \
	puts("*** RUNTIME ERROR CAUGHT ****");                    \
	fprintf(stderr, "*** File: %s | Line: %d | Func: %s()\n", \
		__FILE__, __LINE__, __func__);                    \
	fprintf(stderr, "%s", "*** ");                            \
	fprintf(stderr, (const char *)(format), __VA_ARGS__);     \
//	fflush(stderr);                                           \
        putchar( '\n' );                    \
} while(0)

/* --------------------------------------------------------------
 * char *vprintf_to_text():
 *
 * This function is a wrapper to ISO C99's vsnprintf(). It creates
 * dynamically the buffer needed to hold the printed output, and if
 * it succeeds it returns a pointer to it. On error, it returns NULL.
 *
 * NOTES:
 *   1. vargs MUST have been already initialized in the caller
 *      (by the va_start macro, and possibly subsequent va_arg
 *      calls).
 *   2. The returned buffer, if non-NULL, MUST be freed in the
 *      calling environment.
 *   3. The function is used in the function: printf_to_text()
 * --------------------------------------------------------------
 */
char *vprintf_to_text( const char *fmt, va_list vargs )
{
	int   nchars = 0;
	char  *buf = NULL;
	size_t bufsz = BUFSIZ;

	/* make buf to hold the text and pass it to vsnprintf */
	if ( NULL == (buf = calloc(1, bufsz)) ) {
		DBGF( "%s", "calloc failed!" );
		goto ret_failure;
	}
	nchars = vsnprintf( buf, bufsz, fmt, vargs );
	if ( nchars < 0 ) {
		DBGF( "%s", "vsnprintf failed!" );
		goto ret_failure;
	}

	/* Was buf too small to hold the text?
	 * Reallocate 1+nchars bytes and re-apply.
	 */
	if ( nchars >= (int)bufsz ) {
		char *try = NULL;
		bufsz = 1 + nchars;   /* for the NUL byte */
		try = realloc( buf, bufsz );
		if ( NULL == try ) {
			DBGF( "%s", "realloc failed!" );
			goto ret_failure;
		}
		buf = try;

		nchars = vsnprintf( buf, bufsz, fmt, vargs );
		if ( nchars < 0 ) {
			DBGF( "%s", "vsnprintf failed!" );
			goto ret_failure;
		}
	}

	return buf;

ret_failure:
	if ( buf ) {
		free( buf );
	}
	return NULL;
}

/* --------------------------------------------------------------
 * char *printf_to_text():
 *
 * This function is similar to ISO C99's snprintf() but it creates
 * dynamically the string needed to hold the print-out. It returns
 * the string, or NULL on error.
 * --------------------------------------------------------------
 */
char *printf_to_text( const char *fmt, ... )
{
	char  *txtout = NULL;

	if ( NULL == fmt ) {
		DBGF( "%s", "NULL pointer argument (fmt)" );
		return NULL;
	}

	va_list vargs;

	va_start( vargs, fmt );
	txtout = vprintf_to_text( fmt, vargs );
	va_end( vargs );

	return txtout;
}

/****************************************************//**
 *
 ********************************************************
 */
char *ullong_to_string( unsigned long long int num, size_t *digcount )
{
	char *ret = printf_to_text( "%llu", num );
	if ( NULL == ret ) {
		DBGF( "%s", "printf_to_text() failed" );
		if ( NULL != digcount ) {
			*digcount = 0;
		}
		return NULL;
	}

	if ( NULL != digcount ) {
		*digcount = strlen( ret );
	}
	return ret;
}

/****************************************************//**
 *
 ********************************************************
 */
int main( void )
{
	size_t n = 0;
	char *s = ullong_to_string( 1254879786879834, &n );

	printf( "%s (%d digits)\n", s, n );
	free( s );

	return 0;
}

 

Όλα τα λεφτά είναι η συνάρτηση: vprintf_to_text() και αμέσως μετά η printf_to_text() που την χρησιμοποιεί.

Ο κώδικας είναι C99, και ουσιαστικά είναι copy & paste από τον κώδικα του 2048cc για όποιον το θυμάται (και πιο συγκεκριμένα από το πηγαίο: common.c).

 

[offtopic]

Όσο και να λατρεύω την C, δεν μπορώ να μη θυμηθώ μια παλιά διαφήμιση που έλεγε "Βάλε nova" και να την αλλάξω σε "Βάλε python" :)

 

% python
Python 2.7.9 (default, Mar 22 2015, 20:11:40) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print len(str(153))
3
>>> print len(str(3053))
4
>>> exit()
[/offtopic]
Δημοσ.

[offtopic]

Όσο και να λατρεύω την C, δεν μπορώ να μη θυμηθώ μια παλιά διαφήμιση που έλεγε "Βάλε nova" και να την αλλάξω σε "Βάλε python" :)

 

% python
Python 2.7.9 (default, Mar 22 2015, 20:11:40) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print len(str(153))
3
>>> print len(str(3053))
4
>>> exit()
[/offtopic]

 

Ε ναι ρε συ, δεν υπάρχει σύγκριση μιας και μιλάμε για τελείως διαφορετικής φιλοσοφίας γλώσσες.

Αν και πλέον, μετά από το ποστ αυτό, μπορείς κάλλιστα και στη C να κάνεις:

#include <common.h>
int main( void )
{
	size_t n = 0;
	char *s = ullong_to_string( 1254879786879834, &n );

	printf( "%s (%d digits)\n", s, n );
	free( s );

	return 0;
}
:P

 

Παρεμπιπτόντως (υποθέτω μεταξύ και πολλών & διαφόρων άλλων βιβλιοθηκών) η glib δίνει έτοιμη τέτοια συνάρτηση, την g_strdup_printf(). Μαζί με διάφορες άλλες χρήσιμες συναρτήσεις για strings, στο ίδιο link.

Δημοσ.

Ναι, αυτός είναι ο καθαρά μαθηματικός τρόπος. Δεν είμαι όμως σίγουρος ότι δεν έχει προβλήματα στην γενική περίπτωση, λόγω floating precision errors. Μπορεί να μην έχει, αλλά καλό είναι να το έχει υπόψη του όποιος το χρησιμοποιήσει, και να το ψάξει πρωτα.

 

 

Απ' οσο γνωριζω το πληθος των ψηφιων με τον λογαριθμικο τροπο δεν εχει απροβλεπτα αποτελεσματα για αριθμους μικροτερους 

του 2^50. Αν η παραμετρος δεν ειναι long ή long long ή καποιο Link.png Site: gcc extension η συναρτηση δεν πρεπει να παραγει απροβλεπτα αποτελεσματα

 

Επισης κατι που ξεχασα ειναι οτι καλο θα ηταν να υπαρχει ελεγχος σε περιπτωση που η παραμετρος στη συναρτηση για το πληθος ψηφιων ειναι μηδεν, διοτι στην συγκεκριμενη περιπτωση το αποτελεσμα θα ειναι 2147483648. Συνεπως η σωστη συναρτηση θα ηταν:

unsigned int GetNumberOfDigits (const unsigned int i)
{
    return i > 0 ? (int)(log10(i) + 1) : 1;
}

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...