char* to int, has to be an easier way

Programming, for all ages and all languages.
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

char* to int, has to be an easier way

Post by BASICFreak »

Ok, what I have works but it is the worst looking function I have:

Code: Select all

int						charTOint(char* in)
{
	int			out = 0;
	int i;
	int z = 0;
	for (i=strlen(in)-2 ; i>=0;i--,z++)
	{
		switch (in[i])
		{
			case '1':
				out += 1*exponent(10, z);
				break;
			case '2':
				out += 2*exponent(10, z);
				break;
			case '3':
				out += 3*exponent(10, z);
				break;
			case '4':
				out += 4*exponent(10, z);
				break;
			case '5':
				out += 5*exponent(10, z);
				break;
			case '6':
				out += 6*exponent(10, z);
				break;
			case '7':
				out += 7*exponent(10, z);
				break;
			case '8':
				out += 8*exponent(10, z);
				break;
			case '9':
				out += 9*exponent(10, z);
				break;
		}
	}
	return		out;
}
Is there an easier way of going about this?

Hopefully it is obviously easier than I think and I'm just tired, it is late...
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
User avatar
bwat
Member
Member
Posts: 359
Joined: Fri Jul 03, 2009 6:21 am

Re: char* to int, has to be an easier way

Post by bwat »

You're processing the string in the wrong direction.

Hint 1: 123*10+4 is 1234, and 1234*10+5 is 12345
Hint 2: '3'-'0' is 3
Every universe of discourse has its logical structure --- S. K. Langer.
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: char* to int, has to be an easier way

Post by iansjack »

Is there an easier way of going about this?
I find it difficult to think of a more convoluted way. The entire switch statement can be replaced with a single expression and you can eliminate the variables "i" and "z". I'm not going to insult your intelligence by spoonfeeding you with a solution.
User avatar
bwat
Member
Member
Posts: 359
Joined: Fri Jul 03, 2009 6:21 am

Re: char* to int, has to be an easier way

Post by bwat »

iansjack wrote:
Is there an easier way of going about this?
I find it difficult to think of a more convoluted way. The entire switch statement can be replaced with a single expression and you can eliminate the variables "i" and "z". I'm not going to insult your intelligence by spoonfeeding you with a solution.
What he's done is completely in line with how positional number systems are taught. The only thing he was missing was the application of Horner's rule:

Code: Select all

 str[n]*x^n+str[n-1]*x^(n-1)+...+str[0]=((str[n]*x+str[n-1])*x+...)*x+str[0]. 
His code isn't convoluted, in fact it's quite understandable but inefficient on a binary machine (exponent(10,X) would be more efficient on a decimal machine). The use of Horner's rule and knowledge about the lexicographical ordering of the ASCII alphabet makes the experienced programmer's solution difficult to understand but efficient to execute.
Every universe of discourse has its logical structure --- S. K. Langer.
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: char* to int, has to be an easier way

Post by BASICFreak »

Thanks for all the replies, here is what I have now and I will continue to modify it as time goes on but it's much simpler now.

Code: Select all

int						charTOint(char* in)
{
	int			out = 0;
	int i;
	int z = 0;
	for (i=strlen(in)-2 ; i>=0;i--,z++) out += (in[i] - '0') * exponent(10, z);
	return		out;
}
Must have been late I posted and don't even remember getting to bed ;)
And how can I forget ASCII '7' - ASCII '0' = # 7

For now I'll leave int z & i and exponent() - I have more important segments to worry about.
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: char* to int, has to be an easier way

Post by sortie »

You really are trying to be more clever than you need to be, it can be done extremely elegantly:

Code: Select all

unsigned int unsigned_int_of_string(const char* string)
{
	unsigned int result = 0;
	for ( size_t i = 0; string[i]; i++ )
		result = result * 10 + string[i] - '0';
	return result;
}
(without support for negative integers or error handling - that's trivial to add if desired)

There really isn't any need to mess with exponents (is that floats?) or taking the string length, when you can inductively solve the problem by reducing it to adding one more digit to a partial solution.
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: char* to int, has to be an easier way

Post by iansjack »

Better but I would replace the "for" loop with a "while" and do away with the unnecessary variable "i".
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: char* to int, has to be an easier way

Post by sortie »

iansjack wrote:Better but I would replace the "for" loop with a "while" and do away with the unnecessary variable "i".
Now you are just needlessly micro-optimizing and bike-shedding. When I make your change my local gcc outputs exactly the same assembly (instructions in slightly different order) when compiling -Os (optimize for size). It doesn't really matter as the code is equivalent, the only difference is readability and the ease with which it can be statically verified as correct. To that end, I consider it superior using strings as arrays rather than pointers that are rewritten and dereferenced. Besides, if you wanted it pure, you'd do it recursively functional style.
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: char* to int, has to be an easier way

Post by BASICFreak »

sortie wrote:You really are trying to be more clever than you need to be, it can be done extremely elegantly:

Code: Select all

unsigned int unsigned_int_of_string(const char* string)
{
	unsigned int result = 0;
	for ( size_t i = 0; string[i]; i++ )
		result = result * 10 + string[i] - '0';
	return result;
}
(without support for negative integers or error handling - that's trivial to add if desired)

There really isn't any need to mess with exponents (is that floats?) or taking the string length, when you can inductively solve the problem by reducing it to adding one more digit to a partial solution.
FYI 'size_t i' should be declared before the for loop, only in C99 mode can it be declared inside the loop.

so here is the code I remade:

Code: Select all

unsigned int			charTOint(char* in)
{
	unsigned int ret = 0;
	while (*in != 0)
	{
		if (*in < '0' || *in > '9') return -1;
		ret = ret * 10 + *in - '0';
		*in++;
	}
	return ret;
}
Tested and works fine, and returns -1 on error

I could not think of how to process in order thanks for that, makes more sense than what I was doing.
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: char* to int, has to be an easier way

Post by Combuster »

BASICFreak wrote:FYI 'size_t i' should be declared before the for loop, only in C99 mode can it be declared inside the loop.
And you're deliberately lagging behind 25 years :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bwat
Member
Member
Posts: 359
Joined: Fri Jul 03, 2009 6:21 am

Re: char* to int, has to be an easier way

Post by bwat »

BASICFreak wrote:

Code: Select all

unsigned int			charTOint(char* in)
{
	unsigned int ret = 0;
	while (*in != 0)
	{
		if (*in < '0' || *in > '9') return -1;
		ret = ret * 10 + *in - '0';
		*in++;
	}
	return ret;
}
Tested and works fine, and returns -1 on error

I could not think of how to process in order thanks for that, makes more sense than what I was doing.
You've written a function with return type unsigned int that returns -1 on error. Interesting....... :)
Every universe of discourse has its logical structure --- S. K. Langer.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: char* to int, has to be an easier way

Post by sortie »

BASICFreak wrote:FYI 'size_t i' should be declared before the for loop, only in C99 mode can it be declared inside the loop.
Please simply cease to use C89 and upgrade to C11, or at least C99. It's entirely silly to use obsolete versions of the C standard that has been replaced. I realized the C89 portability issue when I wrote the code and I deliberately did it anyway. :-)
BASICFreak wrote:*in++;
Why are you referencing the pointer prior to advancing it, rather than just advancing it? :-)
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: char* to int, has to be an easier way

Post by iansjack »

sortie wrote:
iansjack wrote:Better but I would replace the "for" loop with a "while" and do away with the unnecessary variable "i".
Now you are just needlessly micro-optimizing and bike-shedding. When I make your change my local gcc outputs exactly the same assembly (instructions in slightly different order) when compiling -Os (optimize for size). It doesn't really matter as the code is equivalent, the only difference is readability and the ease with which it can be statically verified as correct. To that end, I consider it superior using strings as arrays rather than pointers that are rewritten and dereferenced. Besides, if you wanted it pure, you'd do it recursively functional style.
No. I'm lazy and cutting down on the typing. Why use two words when one does the job? ;)
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: char* to int, has to be an easier way

Post by BASICFreak »

bwat wrote:
BASICFreak wrote:

Code: Select all

unsigned int			charTOint(char* in)
{
	unsigned int ret = 0;
	while (*in != 0)
	{
		if (*in < '0' || *in > '9') return -1;
		ret = ret * 10 + *in - '0';
		*in++;
	}
	return ret;
}
Tested and works fine, and returns -1 on error

I could not think of how to process in order thanks for that, makes more sense than what I was doing.
You've written a function with return type unsigned int that returns -1 on error. Interesting....... :)
Yea, I realized that after posting and switched to 0 on error (only issue is if 0 is the right output I'm screwed...)

bochs out (snip-it):
Testing char to int of '2048': 2048, '44578': 44578, '64728': 64728, '4d58': 0
sortie wrote:Why are you referencing the pointer prior to advancing it, rather than just advancing it? :-)
Because that is the way I know...

C is not my native language, learning so much within 1500 lines. I'm starting to miss the OO languages though - or at the very least standard libraries.

And I'll continue to make my code C89 standard so I don't have to worry about anyone (mostly me) missing a -C99 gcc tag.
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: char* to int, has to be an easier way

Post by Antti »

iansjack wrote:Why use two words when one does the job?
Readability is extremely important. Pointer arithmetic adds one low-level detail that can be avoided. The example sortie gave us is more elegant because it is more "portable" to more restricted languages (read: safe languages).
Post Reply