# K&R2 section 2.7 type conversions (exercise)

A

#### arnuld

this is exercise 2-3 from the mentioned section. i have created a
solution for it but i see errors and i tried to correct them but still
they are there and mostly are out of my head:

------------------------------- PROGRAMME --------------------------
/* Section 2.7 type conversions

we are asked to write a function "htoi(an array)" that accomplishes
this:

STATEMENT: this programme converts a string of hexadecimal digits inot
integers. a string may or may not contain "0X" or "0x" and
allowable digits are 0-9, a-f and A-F.

it runs in 4 steps:

1.) it take sinout from user using "for" loop in "main"
2.) "htoi" calls "heca without lead".
4.) it then calls "hexa_to_int" on "hexa_without_lead" to convert this

5.) "hexa_into_int" uses 2 helper functions: "arr_size" and
"base_conv"
to complete its job of convertint the hexadecimal number into an
integer.

*/

#include <stdio.h>
#include <ctype.h>

unsigned long int htoi(char input_array);
unsigned long int hexa_to_int(char s[]);
int arr_size(char arr[]);

int main(void) {

int i, c;
unsigned long uli;
const int MAXELEMENTS = 1000;
char input_array[MAXELEMENTS];

for(i=0; i < MAXELEMENTS && ((c = getchar()) != EOF || c != '\n'); +
+i)
{
if( isdigit(c) || c == 'a' || c == 'A' || c == 'b' || c == 'B'
|| c == 'c' || c == 'C'
c == 'd' || c == 'D' || c == 'e' || c == 'E' || c == 'f' c == 'F' )
{
input_array = c;
}

else
printf("\nYou are an IDIOT, i asked you to ENTER a hexadecimal number
\n");
}

if( c == '\n')
input_array = '\0';

uli = htoi(input_array);

printf("\n\t the number entered is: %ld", uli);

return 0;
}

unsigned long int htoi(char input_array)
{
unsigned long uli;
char modified_hexa[];

uli = hexa_to_int(modified_hexa);

return uli;
}

{
char s[];
int i;

for(i = 0; arr != '\0'; ++i)
{
if(i == 0 && arr == '0' && ( arr[i+1] == 'x' || arr[i+1] ==
'X'))
i = i+2;

s = arr;
}

s = '\0';
return s;
}

unsigned long hexa_to_int(char s[])
{
unsigned long uli = 0;
int i, len;

enum { hexa_a = 10; hexa_b, hexa_c, hexa_d, hexa_e, hexa_f }; /*
this will give hexa_b = 11, hexa_c = 12...... */

len = array_size(s) - 1;

for(i=0; s != '\0' && len >= 0; ++i)
{
if(isdigit(s))
uli = uli + (s * base_conv(len));

else if(s == 'a' || 'A')
uli = uli + (hexa_a * base_conv(len));

else if(s == 'b' || 'B')
uli = uli + ( hexa_b * base_conv(len) );

else if(s == 'c' || 'C')
uli = uli + ( hexa_c * base_conv(len) );

else if(s == 'd' || 'D')
uli = uli + ( hexa_d * base_conv(len) );

else if(s == 'e' || 'E')
uli = uli + ( hexa_e * base_conv(len) );

else
uli = uli + ( hexa_f * base_conv(len) );

--len;
}

return uli;
}

unsigned long base_conv(int n)
{
int base_unit = 16;

while(n >= 0)
{
if(n == 0)
base_unit = base_unit * 1;

else
base_unit = base_unit * base_unit;

--n;
}

return base_unit;
}

int arr_size(char arr[])
{
int i;

for(i=0; arr != EOF; ++i)
;

return i;
}

-------------------------------- OUTPUT
---------------------------------------
[arch@voodo kr2]\$ gcc -std=c99 -Wall -Wextra 27_ex-2-3.c
27_ex-2-3.c: In function 'main':
27_ex-2-3.c:44: error: expected ')' before 'c'
27_ex-2-3.c:57: warning: passing argument 1 of 'htoi' makes integer
from pointer without a cast
27_ex-2-3.c: In function 'htoi':
27_ex-2-3.c:69: error: array size missing in 'modified_hexa'
27_ex-2-3.c:72: error: expected expression before ']' token
27_ex-2-3.c:72: warning: passing argument 1 of 'hexa_without_lead'
makes pointer from integer without a cast
27_ex-2-3.c:82: error: array size missing in 's'
27_ex-2-3.c:94: warning: return makes integer from pointer without a
cast
27_ex-2-3.c:94: warning: function returns address of local variable
27_ex-2-3.c: In function 'hexa_to_int':
27_ex-2-3.c:103: error: expected ',' or '}' before ';' token
27_ex-2-3.c:106: warning: implicit declaration of function
'array_size'
27_ex-2-3.c:111: warning: implicit declaration of function 'base_conv'
27_ex-2-3.c:117: error: 'hexa_b' undeclared (first use in this
function)
27_ex-2-3.c:117: error: (Each undeclared identifier is reported only
once
27_ex-2-3.c:117: error: for each function it appears in.)
27_ex-2-3.c:120: error: 'hexa_c' undeclared (first use in this
function)
27_ex-2-3.c:123: error: 'hexa_d' undeclared (first use in this
function)
27_ex-2-3.c:126: error: 'hexa_e' undeclared (first use in this
function)
27_ex-2-3.c:129: error: 'hexa_f' undeclared (first use in this
function)
27_ex-2-3.c: At top level:
27_ex-2-3.c:139: error: conflicting types for 'base_conv'
27_ex-2-3.c:111: error: previous implicit declaration of 'base_conv'
was here
[arch@voodo kr2]\$

S

#### santosh

arnuld said:
this is exercise 2-3 from the mentioned section. i have created a
solution for it but i see errors and i tried to correct them but still
they are there and mostly are out of my head:

<snip>

Well, fix the errors and warnings gcc is reporting. You're making
several fundamental mistakes. You've not yet understood how to pass
arrays to functions, how to match prototype with function definition,
declaring objects before trying to use them and scope of various types
of objects.

I suspect that you're skipping ahead in K&R without fully
understanding the previous material. This group cannot repeatedly
correct the same errors you make. You'll have to demonstrate that
you're able to learn and desist from previous mistakes.

To start with correct, or try to correct, all the errors, (not
warnings), that gcc is complaining about. Start from the errors
mentioned first and after each correction, recompile and note the new
diagnostic messages. Do this till all the errors are removed. Then we
can progress to constructs that generate a warning.

Always use the -pedantic option with -std=XX, otherwise gcc may accept
implementation specific extensions.

A

#### arnuld

I suspect that you're skipping ahead in K&R without fully
understanding the previous material.

NO. actually authors have not started to talk about pointers in
chapter 1 or 2, just a little about arrays.
This group cannot repeatedly
correct the same errors you make. You'll have to demonstrate that
you're able to learn and desist from previous mistakes.

i want help building a copyleft project written in C (i want to add
VOICE-CHAT features to GAIM, which are not present and i *had* to use
Skype (propreitary) to talk to my freinds)

i am willing to learn but C looks "completely-alien" to me. i am not
even an experienced programmer. i have never built/helped any software
but i want to. i am learning C becuase i want to master procedural
approach before attacking OOD. 2nd, understanding C will always help
me in understanding what is happening behind the scenes in other
languages like C++, Haskell, Mercury etc. 3rd, i read "Perils of Java
Schools" by Joel Spolsky.

To start with correct, or try to correct, all the errors, (not
warnings), that gcc is complaining about. Start from the errors
mentioned first and after each correction, recompile and note the new
diagnostic messages. Do this till all the errors are removed. Then we
can progress to constructs that generate a warning.

Thanks

after 30 minutes of work i have removed all the errors. only Warnings
have remained.
Always use the -pedantic option with -std=XX, otherwise gcc may accept
implementation specific extensions.

ok. BTW, this is the only programme i wrote in whole day, it ate my
morning -> night

:-(

i don't know what it shows, may be i don't carry that "amount" of
talent that is required to become a programmer. i am not sure of
anything.

--------- Corrected Programme with Warnings only --------
/* Section 2.7 type conversions

we are asked to write a function "htoi(an array)" that accomplishes
this:

STATEMENT: this programme converts a string of hexadecimal digits inot
integers. a string may or may not contain "0X" or "0x" and
allowable digits are 0-9, a-f and A-F.

it runs in 4 steps:

1.) it take sinout from user using "for" loop in "main"
2.) "htoi" calls "heca without lead".
4.) it then calls "hexa_to_int" on "hexa_without_lead" to convert this

5.) "hexa_into_int" uses 2 helper functions: "arr_size" and
"base_conv"
to complete its job of convertint the hexadecimal number into an
integer.

*/

#include <stdio.h>
#include <ctype.h>

const int MAXELEMENTS = 1000;
unsigned long htoi(char input_array);
unsigned long base_conv(int s);
unsigned long int hexa_to_int(char s[]);
int arr_size(char arr[]);

int main(void) {

int i, c;
unsigned long uli;
char input_array[MAXELEMENTS];

for(i=0; i < MAXELEMENTS && ((c = getchar()) != EOF || c != '\n'); +
+i)
{
if( isdigit(c) || c == 'a' || c == 'A' || c == 'b' || c == 'B'
|| c == 'c' || c == 'C' ||
c == 'd' || c == 'D' || c == 'e' || c == 'E' || c == 'f' ||
c == 'F' )
{
input_array = c;
}

else
printf("\nYou are an IDIOT, i asked you to ENTER a hexadecimal number
\n");
}

if( c == '\n')
input_array = '\0';

uli = htoi(input_array);

printf("\n\t the number entered is: %ld", uli);

return 0;
}

unsigned long int htoi(char input_array)
{
unsigned long uli;

uli = hexa_to_int(modified_hexa);

return uli;
}

{
char s[MAXELEMENTS];
int i;

for(i = 0; arr != '\0'; ++i)
{
if(i == 0 && arr == '0' && ( arr[i+1] == 'x' || arr[i+1] ==
'X'))
i = i+2;

s = arr;
}

s = '\0';
return s;
}

unsigned long hexa_to_int(char s[])
{
unsigned long uli = 0;
int i, len;

enum { hexa_a = 10, hexa_b, hexa_c, hexa_d, hexa_e, hexa_f }; /*
this will give hexa_b = 11, hexa_c = 12...... */

len = arr_size(s) - 1;

for(i=0; s != '\0' && len >= 0; ++i)
{
if(isdigit(s))
uli = uli + (s * base_conv(len));

else if(s == 'a' || 'A')
uli = uli + (hexa_a * base_conv(len));

else if(s == 'b' || 'B')
uli = uli + ( hexa_b * base_conv(len) );

else if(s == 'c' || 'C')
uli = uli + ( hexa_c * base_conv(len) );

else if(s == 'd' || 'D')
uli = uli + ( hexa_d * base_conv(len) );

else if(s == 'e' || 'E')
uli = uli + ( hexa_e * base_conv(len) );

else
uli = uli + ( hexa_f * base_conv(len) );

--len;
}

return uli;
}

unsigned long base_conv(int n)
{
int base_unit = 16;

while(n >= 0)
{
if(n == 0)
base_unit = base_unit * 1;

else
base_unit = base_unit * base_unit;

--n;
}

return base_unit;
}

int arr_size(char arr[])
{
int i;

for(i=0; arr != EOF; ++i)
;

return i;
}

-------------- WARNINGS----------
[arch@voodo kr2]\$ gcc -std=c99 -pedantic -Wall -Wextra 27_ex-2-3.c
27_ex-2-3.c: In function 'main':
27_ex-2-3.c:58: warning: passing argument 1 of 'htoi' makes integer
from pointer without a cast
27_ex-2-3.c: In function 'htoi':
27_ex-2-3.c:71: warning: passing argument 1 of 'hexa_without_lead'
makes pointer from integer without a cast
27_ex-2-3.c:72: warning: passing argument 1 of 'hexa_to_int' makes
pointer from integer without a cast
27_ex-2-3.c:93: warning: return makes integer from pointer without a
cast
27_ex-2-3.c:93: warning: function returns address of local variable
[arch@voodo kr2]\$

S

#### santosh

arnuld said:
NO. actually authors have not started to talk about pointers in
chapter 1 or 2, just a little about arrays.

You can use arrays without understanding pointers, at least in the
initial stages.
i want help building a copyleft project written in C (i want to add
VOICE-CHAT features to GAIM, which are not present and i *had* to use
Skype (propreitary) to talk to my freinds)

Patience is required to become a good programmer. The state of current
programming is complex enough that you cannot hope to hack on non-
trivial applications without at least a few months of dedicated study
and practise. Learn the fundamentals of C and practise with all sorts
of small programs. Yes, they may seem boring and pointless, and
there's the inevitable urge to jump into the deep end immediately, but
resist it. If you try too much too soon, you'll only end up
disappointed. Take my word on this. Gaim will always be available. It
can wait a few more months. Until then use an alternative, or if none
is acceptable, do without voice-chat.
i am willing to learn but C looks "completely-alien" to me.

It's not considered as the best first language to learn, since there's
a lot you'll have to manually implement. Other languages provide far
more "infrastructure" and pre-built code to do a lot of tasks. One
*can* do them in C too, often more superiorly, but it takes time and
effort and more skill than a newbie is expected to posses.
i am not even an experienced programmer. i have never built/helped
any software but i want to.

Then put aside a few months of time and learn one or more languages.
Also learn general tools and utilities like ed, vi, awk, sh etc. Often
a combination of languages/tools can more effectively solve a problem
than a single language/tool.
i am learning C becuase i want to master procedural approach before attacking OOD.

Some will say this is unnecessary. Certainly C++ or Java can be
learned without knowing C. If you're ultimately interested in
programming in them, then learn them now. You can always come back to
C later.
2nd, understanding C will always help
me in understanding what is happening behind the scenes in other
languages like C++, Haskell, Mercury etc. 3rd, i read "Perils of Java
Schools" by Joel Spolsky.

Not necessarily. Also, such knowledge is not always needed. You'd be
better off learning a single suitable language which you happen to
like, (not necessarily C), and algorithms. Good algorithms and data
structures can be implemented in a comparable manner in most non-
trivial languages.

To understand computer at a low-level, knowledge of assembler may be
required.

<snip>

S

#### santosh

arnuld said:
Thanks

after 30 minutes of work i have removed all the errors. only Warnings
have remained.

ok. BTW, this is the only programme i wrote in whole day, it ate my
morning -> night

:-(

i don't know what it shows, may be i don't carry that "amount" of
talent that is required to become a programmer. i am not sure of
anything.

--------- Corrected Programme with Warnings only --------
/* Section 2.7 type conversions

we are asked to write a function "htoi(an array)" that accomplishes
this:

STATEMENT: this programme converts a string of hexadecimal digits inot
integers. a string may or may not contain "0X" or "0x" and
allowable digits are 0-9, a-f and A-F.

it runs in 4 steps:

1.) it take sinout from user using "for" loop in "main"
2.) "htoi" calls "heca without lead".
4.) it then calls "hexa_to_int" on "hexa_without_lead" to convert this

5.) "hexa_into_int" uses 2 helper functions: "arr_size" and
"base_conv"
to complete its job of convertint the hexadecimal number into an
integer.

*/

Needlessly complicated algorithm.

You say you've corrected the program sufficiently so that the
compilation only emits warnings, but when I try to compile the code
you've given below with gcc -Wall -Wextra -std=c99 -pedantic, I get
the following errors:

0100.c: In function 'main':
0100.c:46: warning: statement with no effect
0100.c:57: error: missing terminating " character
0100.c:58: error: stray '\' in program
0100.c:58: error: missing terminating " character
0100.c:59: error: 'n' undeclared (first use in this function)
0100.c:59: error: (Each undeclared identifier is reported only once
0100.c:59: error: for each function it appears in.)
0100.c:59: error: syntax error before '}' token
#include <stdio.h>
#include <ctype.h>

const int MAXELEMENTS = 1000;

In C90 the size of arrays must be known at compile time. The above
definition exists only at runtime. C99 has however allowed this. But
be warned.
unsigned long htoi(char input_array);

This function is meant to accept a pointer to the first element of an
array of char. However you've declared it above as taking a single
value of type char. Change the declaration to one of:

unsigned long htoi(char input_array[]);

or

unsigned long htoi(char *input_array);
unsigned long base_conv(int s);
unsigned long int hexa_to_int(char s[]);
int arr_size(char arr[]);

int main(void) {

int i, c;
unsigned long uli;
char input_array[MAXELEMENTS];

for(i=0; i < MAXELEMENTS && ((c = getchar()) != EOF || c != '\n'); ++i)

This should be:

for(i = 0; i < MAXELEMENTS && ((c = getchar()) != EOF) && c != '\n';
++i)
{
if( isdigit(c) || c == 'a' || c == 'A' || c == 'b' || c == 'B'
|| c == 'c' || c == 'C' ||
c == 'd' || c == 'D' || c == 'e' || c == 'E' || c == 'f' ||
c == 'F' )

Since you're using C99 anyway just use isxdigit instead of the above.
{
input_array = c;
}
else
printf("\nYou are an IDIOT, i asked you to ENTER a hexadecimal number\n");

This message will be repeated for every non-hexadecimal character in
input.
}

if( c == '\n')
input_array = '\0';

Why do you terminate the string only if a newline character is
received. A C string *must* have a terminating '\0', under all
conditions.
uli = htoi(input_array);

printf("\n\t the number entered is: %ld", uli);

Use the %lu format specifier. %ld is for long int.
return 0;
}

unsigned long int htoi(char input_array)

This should be:

unsigned long int htoi(char input_array[])
{
unsigned long uli;

You're storing the return value of hexa_without_lead into a single
char object.

However hexa_without_lead attempts to return an array of char, (what
it actually returns is a wild pointer, pointing to non-existent
memory).

Modify hexa_without_lead to operate on input_array directly.
uli = hexa_to_int(modified_hexa);

Here you're passing a single char object when the function expects an
array of char objects.
return uli;
}

{
char s[MAXELEMENTS];

Again C90 does not allow runtime sized arrays.
int i;

for(i = 0; arr != '\0'; ++i)
{
if(i == 0 && arr == '0' && ( arr[i+1] == 'x' || arr[i+1] == 'X'))
i = i+2;

s = arr;
}

s = '\0';
return s;

The array s is local to this function. It'll no longer exist when
execution goes out of this function. So you're returning a pointer to
an object that'll not exist by the time the calling function receives
it.

Either operate on the array passed in or allocate a dynamic array by
malloc or make s a global array. The last option is the least
recommended one. I suggest the first option.

You don't need this function since you filter out non-hexadecimal
characters in the for loop in main.

<snip rest>

I've not checked the rest because it's too convoluted and unreadable.
I'll try to check it if I have time later.

In summary, you're not understanding arrays, how to pass them to
functions and the scope of local objects.

K&R may present too steep a learning curve for you. Try something
simpler initially before coming to K&R like Steve Summit's tutorial:

<http://www.eskimo.com/~scs/cclass/>

Try the introductory one, not the one supplementing K&R.

D

#### Default User

santosh said:
arnuld wrote:

Some will say this is unnecessary. Certainly C++ or Java can be
learned without knowing C. If you're ultimately interested in
programming in them, then learn them now. You can always come back to
C later.

"Arnuld" has supposedly been learning C++ for nearly a year now. At
least according to his posts on comp.lang.c++.

Brian

B

#### Barry Schwarz

this is exercise 2-3 from the mentioned section. i have created a
solution for it but i see errors and i tried to correct them but still
they are there and mostly are out of my head:

------------------------------- PROGRAMME --------------------------
/* Section 2.7 type conversions

we are asked to write a function "htoi(an array)" that accomplishes
this:

STATEMENT: this programme converts a string of hexadecimal digits inot
integers. a string may or may not contain "0X" or "0x" and
allowable digits are 0-9, a-f and A-F.

it runs in 4 steps:

1.) it take sinout from user using "for" loop in "main"
2.) "htoi" calls "heca without lead".
4.) it then calls "hexa_to_int" on "hexa_without_lead" to convert this

5.) "hexa_into_int" uses 2 helper functions: "arr_size" and
"base_conv"
to complete its job of convertint the hexadecimal number into an
integer.

*/

#include <stdio.h>
#include <ctype.h>

unsigned long int htoi(char input_array);

This tells the compiler (incorrectly) that the function htoi has a
character as its parameter. You call htoi with an array as its
argument. The next two prototypes indicate you know
how to declare a function which accepts an array so why is this one
different.
unsigned long int hexa_to_int(char s[]);
int arr_size(char arr[]);

int main(void) {

int i, c;
unsigned long uli;
const int MAXELEMENTS = 1000;
char input_array[MAXELEMENTS];

for(i=0; i < MAXELEMENTS && ((c = getchar()) != EOF || c != '\n'); +
+i)

The expression ((c = ... '\n') is always true. If c is not EOF, then
the first part of the or is true. If c is EOF, then it is not '\n'
and the second part is true. In either case, the whole or is
therefore true. Did you perhaps want && instead of &&.
{
if( isdigit(c) || c == 'a' || c == 'A' || c == 'b' || c == 'B'
|| c == 'c' || c == 'C'
c == 'd' || c == 'D' || c == 'e' || c == 'E' || c == 'f' c == 'F' )

You might want to look up the isxdigit function in your reference.
{
input_array = c;
}

else
printf("\nYou are an IDIOT, i asked you to ENTER a hexadecimal number
\n");

Idiocy notwithstanding, this will generate an incorrect error message
if the user enters 0x or 0X, which is supposed to be allowed.
}

if( c == '\n')
input_array = '\0';

What happens when c is EOF. Don't you need to terminate the string
then also?
uli = htoi(input_array);

printf("\n\t the number entered is: %ld", uli);

%ld is for signed long. uli is unsigned. You need a different
conversion specification.

The absence of a \n at the end of your output will allow it to remain
in a buffer without being visible to the user.
return 0;
}

unsigned long int htoi(char input_array)
{
unsigned long uli;
char modified_hexa[];

If you define an array, you must specify its dimensions.

Wrong in so many ways. What is your real intent here?
uli = hexa_to_int(modified_hexa);

Excessive vertical white space serves no purpose other than making
return uli;
}

Which single character do you intend this function to return?
{
char s[];
int i;

for(i = 0; arr != '\0'; ++i)
{
if(i == 0 && arr == '0' && ( arr[i+1] == 'x' || arr[i+1] ==
'X'))
i = i+2;

s = arr;
}

s = '\0';
return s;
}

unsigned long hexa_to_int(char s[])
{
unsigned long uli = 0;
int i, len;

enum { hexa_a = 10; hexa_b, hexa_c, hexa_d, hexa_e, hexa_f }; /*
this will give hexa_b = 11, hexa_c = 12...... */

len = array_size(s) - 1;

for(i=0; s != '\0' && len >= 0; ++i)
{
if(isdigit(s))
uli = uli + (s * base_conv(len));

s is the character value of the digit, not its numeric value. ('1'
is 49 in ASCII). You need to use s-'0'.

There is no prototype or definition in scope for base_conv. You could
save all the unnecessary code in base_conv by using
uli = uli * 16 + s-'0';

else if(s == 'a' || 'A')

You demonstrated in main that you knew how to check for a character
being equal to one of several values. What is this syntactically
correct but meaningless garbage?
uli = uli + (hexa_a * base_conv(len));

else if(s == 'b' || 'B')
uli = uli + ( hexa_b * base_conv(len) );

else if(s == 'c' || 'C')
uli = uli + ( hexa_c * base_conv(len) );

else if(s == 'd' || 'D')
uli = uli + ( hexa_d * base_conv(len) );

else if(s == 'e' || 'E')
uli = uli + ( hexa_e * base_conv(len) );

else
uli = uli + ( hexa_f * base_conv(len) );

--len;
}

return uli;
}

unsigned long base_conv(int n)
{
int base_unit = 16;

while(n >= 0)
{
if(n == 0)
base_unit = base_unit * 1;

Is there some mystical significance to this waste of CPU cycles?
else
base_unit = base_unit * base_unit;

--n;
}

return base_unit;
}

int arr_size(char arr[])
{
int i;

for(i=0; arr != EOF; ++i)

arr will never equal EOF in this code. What is the only way to
terminate a string?
;

return i;
}

snip ~40 lines of error messages

You really need to work on simpler programs until you get the basics
down pat.

Remove del for email

A

#### arnuld

arnuld wrote:
Needlessly complicated algorithm.

it is *not* an algorithms. it is a method i derived, when i had
nothing in my hands, to solve this *specific* problem.

i have studied any algorithms yet becuase i believe you need a
programming language to implement them.
You say you've corrected the program sufficiently so that the
compilation only emits warnings, but when I try to compile the code
you've given below with gcc -Wall -Wextra -std=c99 -pedantic, I get
the following errors:

0100.c: In function 'main':
0100.c:46: warning: statement with no effect
0100.c:57: error: missing terminating " character
0100.c:58: error: stray '\' in program
0100.c:58: error: missing terminating " character
0100.c:59: error: 'n' undeclared (first use in this function)
0100.c:59: error: (Each undeclared identifier is reported only once
0100.c:59: error: for each function it appears in.)
0100.c:59: error: syntax error before '}' token

don't know how you got those errors. may be i am using a different
version of GCC than you, 4.1.2

I've not checked the rest because it's too convoluted and unreadable.
I'll try to check it if I have time later.

NO, don't waste your unnecessary time. i will put more time myself
1st, then i will ask here.
In summary, you're not understanding arrays, how to pass them to
functions and the scope of local objects.
:-(

K&R may present too steep a learning curve for you. Try something
simpler initially before coming to K&R like Steve Summit's tutorial:

<http://www.eskimo.com/~scs/cclass/>

Try the introductory one, not the one supplementing K&R.

i tried, it feels TOO simple, way-way easy. i already know most of the

i forgot to mention that i have done some Common Lisp:

http://www.gigamonkeys.com/book/

only 1st 22 chapters.

A

#### arnuld

"Arnuld" has supposedly been learning C++ for nearly a year now. At
least according to his posts on comp.lang.c++.

NO, not a year. just just from Nov 20th 2006. before that i was
learning Common Lisp. i started with this book, as an introduction to
programming:

http://www.cs.cmu.edu/~dst/LispBook/index.html

then i went on to this one:

http://www.gigamonkeys.com/book/

before trying these i wasted too much of time on a 3rd class language,
known as Scheme. BUT that is my biased view point only. it is an

A

#### arnuld

This tells the compiler (incorrectly) that the function htoi has a
character as its parameter. You call htoi with an array as its
argument. The next two prototypes indicate you know
how to declare a function which accepts an array so why is this one
different.

The expression ((c = ... '\n') is always true. If c is not EOF, then
the first part of the or is true. If c is EOF, then it is not '\n'
and the second part is true. In either case, the whole or is
therefore true.
:-(

Did you perhaps want && instead of &&.

what does that mean ?

You might want to look up the isxdigit function in your reference.

"isdigit(c)" tells whether (c >= '0' && c <= '9') , page-43 K&R2

Which single character do you intend this function to return?

i wanted to return an array.

else if(s == 'a' || 'A')

You demonstrated in main that you knew how to check for a character
being equal to one of several values. What is this syntactically
correct but meaningless garbage?

what does that mean ?

Is there some mystical significance to this waste of CPU cycles?

other wise how will i compute /2 * (16 raised to the power 3)/

?

arr will never equal EOF in this code. What is the only way to
terminate a string?

aarrrgh...... now i have started to hate myself.

You really need to work on simpler programs until you get the basics
down pat.

i can't. these are the *only* exercises K&R2 has provided.

S

#### santosh

arnuld said:
what does that mean ?

He meant to write:

Did you perhaps want && instead of ||.

I corrected it in my earlier post. The logic is simple. You want to
break the loop when getchar returns an EOF _and_ when it returns a
newline character. Therefore you need to use the && operator which
returns true only when *both* it's conditions are true. The logical OR
operator, i.e., an ||, returns true when either one of it's operands
evaluates to true.
"isdigit(c)" tells whether (c >= '0' && c <= '9') , page-43 K&R2

C99 also has a isxdigit function which returns true if the argument is
in the ranges 0... 9, a... f or A... F. It'll do the job of your
complicated if condition above.

Which single character do you intend this function to return?

i wanted to return an array.

Automatic arrays will go out of scope when execution leaves the parent
function, and thus it'll be destroyed. Consider:

char *ret_spurious_array(char arr[]) {
char local_arr[10];
/* ... */
return local_arr;
}

The array local_arr has block scope. It's block, in this case, is the
entirety of the function ret_spurious_array. It'll be created anew
each time this function is called and destroyed each time this
function returns. Therefore when this function returns the pointer
value local_arr in it's return statement, it's returning a pointer to
an array that'll no longer exist by the time the function's caller
receives the return value, i.e. a wild pointer or a pointer with an
indeterminate value.

There are several ways to fix this. The easiest for you, at this stage
of your learning in C is:

void process_array(char arr[]) {
/* do something with arr */
arr[x] = SOMETHING;
/* ... */
return;
}

Here the process_array function is meant to operate on an array. In C,
you can never pass an array directly to a function. Instead whenever
you pass an array name to a function like this:

process_array(array);

what happens is that the array name 'array' "decays" to a pointer
value to the first element of array. The function process_array
receives this pointer value and, through it, operates *directly* on
the array 'array' in the parent function. Therefore no array needs to
be passed in to the function, (indeed you cannot do so), *and*, no
arrays local to the function are needed. It need not also return a
pointer to a local object which will not exist. This is why the header
for the above function can also be written as:

void process_array(char *arr) { /* ... */ return; }

Since what's passed into the function is actually a pointer value, of
the appropriate type, this form of writing the header is more or less
equivalent to the previous form, except that this form assumes the
student knows about pointers and their representation. The previous
form, i.e., using char arr[] and operating on arr by indexing, like
arr[4] = /* ... */, only assumes knowledge of arrays and indexing
them. It needs no explicit knowledge of pointers, when you're starting
to use them, but the pointer and it's manipulation nevertheless goes
on *behind the scenes*.

On more method to solve your problem is like this:

char *fx(char arr[]) {
char *heap_arr;
/* ... */
heap_arr = malloc(SOME_SIZE);
/* verify allocation has succeeded */
/* do something with the array pointed to by heap_arr */
return heap_arr;
}

Here you're using the malloc function to allocate an array of char *on
the heap*. The heap is best defined as that portion of system memory
from which the functions malloc, calloc and realloc get their memory
from. Most importantly memory allocated on the heap *persists*
throughout the lifetime of the program, or until you explicitly
deallocate it by calling free on it. This means that when the above
function returns the pointer value stored in heap_arr, the array
pointed to will still exist when the calling function receives it.
Also, as long as the pointer value is safely stored in some pointer
object, you can continue to access the memory block as long as the
program runs and from *anywhere* in the program, provided a copy of
the pointer is given to it. When you're done using the memory block,
you can return it to the system using free(the_pointer_value).

One more *highly non-recommended* method of solving you problem is to
declare a _global_ array and pass it between all the functions that
need to operate on it. A global object, (actually the precise term is
file scope), is created by placing it's declaration *outside* of any
function. Like:

char global_arr[SOME_SIZE];

fx1(global_arr);
/* ... */
fx2(global_arr);
/* etc. */

This type of programming tightly couples data with functions and
allows arbitrary changes to data that may become very hard to track
and maintain. Therefore using global objects, without a *very good
reason* is not good programming practise.

There's one more method to do what you want, but it's too complicated
for you at this stage.
else if(s == 'a' || 'A')

You demonstrated in main that you knew how to check for a character
being equal to one of several values. What is this syntactically
correct but meaningless garbage?

what does that mean ?

Well, the equality operator has higher precedence than the logical
operator. So the above construct is actually:

else if ( (s == 'a') || 'A' ) /* ... */

In C a printable character always has positive value. Also any value
other than zero is interpreted as true in test conditions. So in the
above statement, 'a' is tested for equality against the i'th element
of array s. Lets say it contains the character 'b'. Then the
expression yields zero, which is defined as false. However because
you've misunderstood precedence, you've coupled this test with the
value of a character literal 'A', binding them both with a logical OR
which returns true if either of it's operands is true. So even if the
test for equality returns false, the *other* side of the OR will
*always* yield true, since in C, the value of printable characters in
positive, and any non-zero value is taken as being true in logical
contexts.

What you should do is:

else if (s == 'a' || s == 'A') /* ... */

i can't. these are the *only* exercises K&R2 has provided.

Have you worked through *all* the exercises in K&R up to this point?
Have you successfully done *all* of them?

C

#### Coos Haak

Op 13 Mar 2007 22:02:11 -0700 schreef arnuld:
don't know how you got those errors. may be i am using a different
version of GCC than you, 4.1.2
Did you really try
gcc -Wall -Wextra -std=c99 -pedantic
like santosh said? That is the reason why he got these messages.
Which ones did you get? Tell us!

A

#### arnuld

Well, fix the errors and warnings gcc is reporting. You're making
several fundamental mistakes. You've not yet understood how to pass
arrays to functions, how to match prototype with function definition,
declaring objects before trying to use them and scope of various types
of objects.

I suspect that you're skipping ahead in K&R without fully
understanding the previous material.

YES, that was not intentional. today found that i *overlooked* arrays
in chapter 1, my mistake. i have corrected this mistake and started
the K&R2 again from chapter 1.

This group cannot repeatedly
correct the same errors you make. You'll have to demonstrate that
you're able to learn and desist from previous mistakes.

yes, i am willing to do that.

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

### Members online

No members online now.