473,382 Members | 1,563 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Please comment on my program

I'm a newbie and have attempted to create a program to convert a string
containing the representation of a number in a specified base to a
decimal integer. Here's the code:

#include <stdio.h>

unsigned todecimal( char *s, int base)
{
unsigned num = 0, mul;
int len=0;
while (*++s != '\0')
++len;
--s;
for (mul=1; len>=0; --len, mul*=base, --s)
{
if (*s >= '0' && *s <= '9')
num+= (*s-'0')*mul;
else if (*s>='A'&& *s<='Z')
num+= (*s-'A'+10)*mul;
else if (*s>='a' && *s<='z')
num+=(*s-'a'+10)*mul;
}
return num;
}

int main()
{
char s[33];
int base;
printf("Enter the number and its base: ");
scanf("%s%d",s, &base);
printf("Decimal value = %u\n", todecimal(s, base) );
return 0;
}

Sep 25 '06 #1
5 1620
Registered User wrote:
>
I'm a newbie and have attempted to create a program to convert a
string containing the representation of a number in a specified
base to a decimal integer. Here's the code:

#include <stdio.h>

unsigned todecimal( char *s, int base)
{
unsigned num = 0, mul;
int len=0;
while (*++s != '\0')
++len;
--s;
for (mul=1; len>=0; --len, mul*=base, --s)
{
if (*s >= '0' && *s <= '9')
num+= (*s-'0')*mul;
else if (*s>='A'&& *s<='Z')
num+= (*s-'A'+10)*mul;
else if (*s>='a' && *s<='z')
num+=(*s-'a'+10)*mul;
}
return num;
}

int main()
{
char s[33];
int base;
printf("Enter the number and its base: ");
scanf("%s%d",s, &base);
printf("Decimal value = %u\n", todecimal(s, base) );
return 0;
}
Shows promise, but here are some things to consider:

There is no guarantee that the letters 'A'..'Z' are contiguous.
Same for 'a'..'z'. See EBCDIC encoding for one example.

Nothing stops your conversion if an input 'digit' is beyond the
size allowed by base.

Nothing detects overflow.

--
Some informative links:
<news:news.announce.newusers
<http://www.geocities.com/nnqweb/>
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/>

Sep 25 '06 #2
Registered User schrieb:
I'm a newbie and have attempted to create a program to convert a string
containing the representation of a number in a specified base to a
decimal integer. Here's the code:

#include <stdio.h>

unsigned todecimal( char *s, int base)
"to" followed by a lower case letter belongs as an identifier
to the implementation; i.e. this name might at some time clash
with something the standard library provides.

You do not modify the passed string, so you may as well pass a
const char *.

Something to document early: You check neither s!=NULL nor
2<=base<=36. If the user does not find this, you may get
invalid input and the ensuing crash or returned garbage is
somehow _your_ fault...
{
unsigned num = 0, mul;
Note: I'd rather use unsigned long which is the widest unsigned
integer type in C89 (or unsigned long long for C99).
int len=0;
while (*++s != '\0')
If s is "", then you run off wildly through storage that does
not necessarily belong to you. In addition, you modify a
parameter -- it may be a better idea to create a copy and modify
that.
Either stick with strlen() or amend this to
const char *tmp;
for (tmp = s; *tmp != '\0'; ++tmp) {
++len;
}
++len;
--s;
for (mul=1; len>=0; --len, mul*=base, --s)
{
if (*s >= '0' && *s <= '9')
num+= (*s-'0')*mul;
else if (*s>='A'&& *s<='Z')
num+= (*s-'A'+10)*mul;
else if (*s>='a' && *s<='z')
num+=(*s-'a'+10)*mul;
This breaks if 'Z'-'A' != 25...
A better method is using a digits array:
char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
and set the allowed range:
digits[base] = '\0';
and then find the digit using strchr()
char *occurred = strchr(digits, tolower(*s));
if (occurred && *occurred) {
int digit = occurred - s;
....
The other thing is that you do not make sure that you have
no overflow: For num of type unsigned int, this means:
unsigned int add;

if (UINT_MAX / digit < mul) {
/* mul will become too large in the next step and is
* already too large for digit*mul to be representable */
/* Your error handling here */
}
add = digit * mul;
if (UINT_MAX - add < num) {
/* mul will become too large in the next step and is
* already too large for num+digit*mul to be representable */
/* Your error handling here */
}

}
return num;
}
You omitted error handling; there are several types of errors, so
you should decide how you want to flag "everything okay" vs. "something
bad happened".
Bad things that could happen:
s == NULL
base < 2
base strlen(digits)
one of the characters not in digits (where digits[base] == 0)
overflow
Should everything be flagged differently?
How do you want to flag this?
As you have unsigned int values, the obvious candidate for an error
return is UINT_MAX. Alternatively, you can have a look at the
strtoul() function and how it flags "bad" values.
int main()
int main (void)
-- we have that much time.
{
char s[33];
int base;
printf("Enter the number and its base: ");
scanf("%s%d",s, &base);
Always make sure that you did get what you expected when using
*scanf():
if (2 != scanf("%s%d", s, &base)) {
/* Your error handling here */
}
printf("Decimal value = %u\n", todecimal(s, base) );
return 0;
}
Note: As you have an excellent alternate version (strtoul()), you
can test your function in comparison with strtoul(). Maybe you have
to wrap strtoul() to get the same outward behaviour.
When testing, do not forget corner cases such as:
s = NULL, s = ""
base = -1, base = 0, base = 1, base = 2, base = 36, base = 37
s = "/", s = "-1", s = "3" for base = 2, s = "0",
s = string holding UINT_MAX, s = string holding UINT_MAX + 1, ....
Cheers

--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Sep 25 '06 #3
Registered User posted:
#include <stdio.h>

unsigned todecimal( char *s, int base)

Take that argument as a pointer to const. I would also suggest making the
actual arguments themselves const.

{
unsigned num = 0, mul;
int len=0;

I would advocate the use of an unsigned integer type for "len".

>
while (*++s != '\0')
++len;
--s;

Highly inefficient on most systems; you'd probably be better off with
something like:

size_t len = strlen(s);

s += len-1;

for (mul=1; len>=0; --len, mul*=base, --s)

If using an unsigned type, change the conditional to: len != -1

{
if (*s >= '0' && *s <= '9')
num+= (*s-'0')*mul;
else if (*s>='A'&& *s<='Z')
num+= (*s-'A'+10)*mul;
else if (*s>='a' && *s<='z')
num+=(*s-'a'+10)*mul;

As mentioned elsethread, the codes for the letters of the alphabet aren't
necessarily in order one after the other.

--

Frederick Gotham
Sep 25 '06 #4
On Mon, 25 Sep 2006 10:42:47 -0400, CBFalconer <cb********@yahoo.com>
wrote:
>Registered User wrote:
>>
I'm a newbie and have attempted to create a program to convert a
string containing the representation of a number in a specified
base to a decimal integer. Here's the code:

#include <stdio.h>

unsigned todecimal( char *s, int base)
{
unsigned num = 0, mul;
int len=0;
while (*++s != '\0')
++len;
--s;
for (mul=1; len>=0; --len, mul*=base, --s)
{
if (*s >= '0' && *s <= '9')
num+= (*s-'0')*mul;
else if (*s>='A'&& *s<='Z')
num+= (*s-'A'+10)*mul;
else if (*s>='a' && *s<='z')
num+=(*s-'a'+10)*mul;
}
return num;
}

int main()
{
char s[33];
int base;
printf("Enter the number and its base: ");
scanf("%s%d",s, &base);
printf("Decimal value = %u\n", todecimal(s, base) );
return 0;
}

Shows promise, but here are some things to consider:

There is no guarantee that the letters 'A'..'Z' are contiguous.
Same for 'a'..'z'. See EBCDIC encoding for one example.
While it's important to understand that the C Standard does not
guarantee that the character set used to encode 'A'..'Z' or 'a'..'z'
is not contiguous, it's also important to realize that source code
distributed with a particular character encoding is inherently
non-portable. ZIP files containing source code encoded with the ASCII
character encoding are inherently non-portable. True pedantics would
note such a caveat.

Best regards
--
jay
Sep 26 '06 #5
[snip]
See snippet functions bascnvrt.c and ltostr.c:
http://c.snippets.org/browser.php

Sep 26 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: rked | last post by:
I get nameSPAN1 is undefined when I place cursor in comments box.. <%@ LANGUAGE="VBScript" %> <% DIM ipAddress ipAddress=Request.Servervariables("REMOTE_HOST") %> <html> <head> <meta...
13
by: walter | last post by:
I wrote a program, and found one line of source code not compiled out. I rewrote it for simplicity as below. The comment in the program is big5 code text. --- my program --- main(){ int i, a;...
3
by: hellfire | last post by:
Below is a pretty usless progam but being a begginer and working form a book i need some one to comment on it IE: is it set out right easy to follow i tried to use every thing i know to data your...
2
by: Sathyaish | last post by:
I am writing a program that will take a string that has a C source file and it would format all the multi-line comments like these: //Jingle bells, jingle bells, jingles all the way //O what...
8
by: G Patel | last post by:
I wrote the following program to remove C89 type comments from stdin and send it to stdout (as per exercise in K&R2) and it works but I was hoping more experienced programmer would critique the...
6
by: Clunixchit | last post by:
I would appreciate if you can criticise my code as well as if possible give advice on how to improve it. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h>...
11
by: garyusenet | last post by:
For this first time today I used the System.Diagnositcs namespace to launch a program from my c# code. The program launches OK but I have something which has completely stumped me. The...
1
by: Nethra | last post by:
Hi... I am trying a program which convert the multiline comment type in a program to single line comment type ie. /*have a nice day */ to //have a //nice day
10
by: len | last post by:
I have created the following program to read a text file which happens to be a cobol filed definition. The program then outputs to a file what is essentially a file which is a list definition...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.