clc selected threads (30-jan-2005 to 31-jan-2005) #1

S

sathyashrayan

Following are the selected thread from the date:30-jan-2005 to
31-jan-2005. I did not use any name because of the subject is important.
You can get the original thread by typing the subject "string" in google
comp.lang.c archives.Hope this helps.Hope I am not bothering any one. am I?

=================================Start===========================
subject: Return to Start of Line?

Question:
I'd like printf, the next printf, to return to the start of the
line just printed. In other words, I want to keep print over the same
portion of the screen again and again. 01, 02, 03, ... Is there some /X
that does that?

Answers:
Depends on your output device. Usually \r. Don't forget to use
fflush(f) when you haven't terminated a line with \n.

#include <stdio.h>

int main(int argc, char* argv[]) {
for (size_t j = 0; j < 4; ++j)
fprintf(stdout, "Hello world!\r");
fprintf(stdout, "Hello world!\n");
return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
Hello world!



==============================End======================


Subject: function to count number of set bits

Question:
Hi, I'm wondering if anyone knows if the following function will
function properly as a set-bit counter on non 2s complement machines
(as K&R2 implies).

| int bitcount(unsigned x)
| {
| int count;
|
| for(count = 0; x != 0; count++, x &= (x-1))
| ;
|
| return count;
| }

I can't think of a reason why this would fail on a 1s complement or
sign-mag machine (and can't find a non 2s compliment machine to try it
on). Is it portable as far as C is concerned?

And also, if I declare a signed int in the main program and want to set
the msb to 1, can I do this (32bit ints)?:

int b = 0x8000000;
/* is the 0x80000000 taken as an unsigned long constant or a signed
int? */

int count = bitcount(b);
/* is this undefined- trying to send a negative int to bitcount
function? */

Answers:

Answers:1)

G Patel wrote:


Hi, I'm wondering if anyone knows if the following function will
function properly as a set-bit counter on non 2s complement machines
(as K&R2 implies).

| int bitcount(unsigned x)
| {
| int count;
|
| for(count = 0; x != 0; count++, x &= (x-1))
| ;
|
| return count;
| }
>I can't think of a reason why this would fail on a 1s complement or
>sign-mag machine (and can't find a non 2s compliment machine to try it
>on). Is it portable as far as C is concerned?

It makes no difference what representation the machine
uses for negative integers, because `x' cannot be negative!
I see no portability or conformance problems in the code.

>And also, if I declare a signed int in the main program and want to set
>the msb to 1, can I do this (32bit ints)?:
>int b = 0x8000000;

You're missing a zero here, I believe.

>/* is the 0x80000000 taken as an unsigned long constant or a signed
>int? */

Neither: Given the assumption of 32 bits, the constant
(with all seven zeroes) will be an `unsigned int'. Since the
value of this constant is too large for plain `int', trying to
convert it to `int' either produces an implementation-defined
result or raises an implementation-defined signal. On most 32-bit
implementations, `b' will be initialized to INT_MIN, -2147483648 --
but the Standard doesn't actually guarantee this.

>int count = bitcount(b);
>/* is this undefined- trying to send a negative int to bitcount
>function? */

No: conversion the other way, from signed to unsigned,
is well-defined. However, the conversion might change the
number of one-bits in the representation. For example, the
representation of -1 on a signed magnitude machine has two
one-bits. Converting this to `unsigned' produces the value
UINT_MAX, which has at least sixteen one-bits. Avoiding such
surprises is one of the reasons to stick to `unsigned' types
for bit-fiddling.

Answers:2)



>
> It makes no difference what representation the machine
> uses for negative integers, because `x' cannot be negative!
> I see no portability or conformance problems in the code.
>
>
> You're missing a zero here, I believe.
>
>
> Neither: Given the assumption of 32 bits, the constant
> (with all seven zeroes) will be an `unsigned int'. Since the
> value of this constant is too large for plain `int', trying to
> convert it to `int' either produces an implementation-defined
> result or raises an implementation-defined signal. On most 32-bit
> implementations, `b' will be initialized to INT_MIN, -2147483648 --
> but the Standard doesn't actually guarantee this.

Thank you. Now I get it, I went and checked the C89 draft and found:

The type of an integer constant is the first of the corresponding list
in which its value can be represented. Unsuffixed decimal: int, long
int, unsigned long int; unsuffixed octal or hexadecimal: int, unsigned
int, long int, unsigned long int; suffixed by the letter u or U:
unsigned int, unsigned long int; suffixed by the letter l or L: long
int, unsigned long int; suffixed by both the letters u or U and l or L:
unsigned long int .

But I'm wondering how the "-" plays into any of this (for negative
constants). Is the "-" part of the constant or is it just the constant
with the - unary operator imparted on it.

How would one explain these constants:

-0xF , -077, -56


No mention of "-" that go in front of constants in the standard. How
does the "-" affect the constant (I imagine it just takes all the
signed types in each list out of the picture).


[I wonder what the authors of my C textbook was thinking when he named
it: Teach yourself C in 24 hours ... they couldn't be more wrong]


Answers:3)

> But I'm wondering how the "-" plays into any of this (for negative
> constants). Is the "-" part of the constant or is it just the constant
> with the - unary operator imparted on it.

The latter.

Answers:4)

>
> The latter.

Ok, so the - isn't part of the actual constant, only acts as a - unary
operator. But what about constants that "fall" into a unsigned type.
Wouldn't the whole expression be a sort of negative unsigned constant?

Answers:5)
>
> Ok, so the - isn't part of the actual constant, only acts as a - unary
> operator. But what about constants that "fall" into a unsigned type.
> Wouldn't the whole expression be a sort of negative unsigned constant?

Arithmetic in unsigned types "wraps around". A negative value in
an unsigned type is changed into a positive one by adding the
type's maximum value plus one until it is in range. Thus, -1u is
equal to UINT_MAX.

Answers:6)



I don't think that is true. I think the "-" sign in front of an
otherwise unadorned arithmetic constant is inherently part of the
constant. If we considered the "-" to be an "add on" that works just
as a unary - operator, then we would have to perform UAC/Promotion on
assignments (where otherwise, an assignment has no promotion/UAC, just
straight conversion to the type of the left operands).
Where in the standard did you read this?

Answers:7)




You're mistaken; see below.



Do you have an example where this matters? (Note that there are no
integer constants for types shorter than signed or unsigned int.)



C99 6.4.4.1 defines the syntax of an integer constant; it doesn't
allow for a leading sign.

Answers:8)

..... snip ...


Look at the way INT_MIN is usually defined in limits.h. For a 16
bit 2's complement int machine, it would normally be (-INT_MAX -
1). If it were written as -32768 it would create an overflow on
input.

Answers:9)


Not an overflow, exactly, but a result with the wrong
type and the wrong value. Since the constant is too large
for `int' but within range for an `unsigned int' it would
have the latter type; in effect it would be 32768u. The
"negation" would, under the rules of unsigned arithmetic,
reduce modulo 65536u to yield the value 32768u again. Thus
you'd have the, er, "anomalous" condition INT_MIN > INT_MAX!

Note that `(int)-32768' wouldn't work, since the value
must be a constant expression and constant expressions can't
contain cast operators.

Answers:10)


Casts are allowed in constant expressions although there are some
restrictions which don't apply here. The problem with (int)-32768 where
INT_MAX is 32767 and UINT_MAX is 65535 is that it is equivalent to
(int)(32768U) i.e. you are trying to convert to a signed integer type a
value that is not representable in that type. That's undefined in C90 and
in C99 you get an implementation-defined value or signal.

Answers:11)


And if the implementation-defined value happens to be -32768, the
implementation is free to use it as the definition of INT_MIN. (There
are good reasons not to do so. Keeping <limits.h> in sync with the
compiler might be non-trivial, and you might as well have a portable
definition of INT_MIN if you can.)

Answers:12)




There is another good reason not to use a cast here. Suppose
INT_MIN is in fact -32768 (numerically), and the implementation
uses a cast in the "#define" for INT_MIN. Then consider:

#if INT_MIN < (-2147483647 - 1)
/* int is at least 32 bits */
...
#endif

When the compiler sees this during the preprocessing phase in which
keywords have no meaning (because there are only pp-tokens, not
yet any tokens), we get:

#if ((some_pp_token)-32768) < (-2147483647 - 1)

which is syntactically invalid and requires a diagnostic. My C99
draft says, in part:

[#1] The values given below shall be replaced by constant
expressions suitable for use in #if preprocessing
directives.

(C89 has similar if not identical wording.)

Answers:13)
>>> Look at the way INT_MIN is usually defined [...]
>>
>>
>> Note that `(int)-32768' wouldn't work, since the value
>> must be a constant expression and constant expressions can't
>> contain cast operators.
>
>
> Casts are allowed in constant expressions although there are some
> restrictions which don't apply here. The problem with (int)-32768 where
> INT_MAX is 32767 and UINT_MAX is 65535 is that it is equivalent to
> (int)(32768U) i.e. you are trying to convert to a signed integer type a
> value that is not representable in that type. That's undefined in C90 and
> in C99 you get an implementation-defined value or signal.


Sorry; sloppy language on my part. Casts are indeed
permitted in "constant expressions" (6.6), but they are
forbidden in the special form of "constant expression" the
preprocessor can evaluate (6.10.1). INT_MIN and friends
must be evaluable by the preprocessor (5.2.4.2.1), and so
cannot be defined with casts.

Answers:14)





Where did you find anything in the standard that talks about
negative constants? The grammar shows `-' as a unary operator,
not as part of a primary expression.

I have no idea why you think this has anything to do with
assignment.


Answers:15)
>
>
>
>
> Where did you find anything in the standard that talks about
> negative constants? The grammar shows `-' as a unary operator,
> not as part of a primary expression.
>
#define EOF (-1)

Is '-' part of a primary expression?

#define LONG_MIN (-2147483647L-1L)

How about here?

I must be missing something. Help me here. Buy me a beer in Menlo Park.

Answers:16)


Both of these are primary expressions because they're parenthesized.

Without the parentheses, neither -1 nor -2147483647L-1L is a primary
expression.

Answers:17)



1 primary-expression:
identifier
constant
string-literal
( expression )

You're trying to make some kind of pedantic point by saying that
you parenthesized it, therefore it's a primary expression. But
you know what my point is: there is no alternative listed as
`- constant', nor is the negative sign part of `constant'
itself (except perhaps as part of an exponent, etc.). There is
no such thing as a negative constant, only a constant to which
you apply a negating unary operator.

Answers:18)


>> [...] There is
>> no such thing as a negative constant, only a constant to which
>> you apply a negating unary operator.


Three pettifogging counter-examples (two implementation-
specific):

enum { NEGATIVE = -42, POSITIVE = 42 };
/* Henceforth, `NEGATIVE' is a negative constant. */

'\x99'
/* A constant whose value may be negative on some
* implementations, depending on the value of CHAR_BIT
* and the signedness of `char'.
*/

'ß'
/* A constant whose value may be negative on some
* implementations (and which might be utterly rejected
* by some others, since the character is not in the set
* mandated by the Standard).
*/



Answers:19)




>
>>>> [...] There is
>>>> no such thing as a negative constant, only a constant to which
>>>> you apply a negating unary operator.
>
>>
>> Three pettifogging counter-examples (two implementation-
>> specific):

[snip..]

Okay, let me try again. There is no such thing as a negative
integer-constant or floating-constant, but you may apply a
negating unary operator to obtain a negative value.

Anybody want to dispute *that*?

Answers:20)
negative

>



Actually it is treated as a unary - operator. In terms of C, the
constant is just the arithmetic term without a sign. But of course,
with the - in front of it, the negation is calculated at compile time,
and the post-negated constant sits in memory along with corresponding
assembly opcode(s) (calculation is not done at run time, there will be
no evidence of the original positive constant within the instructions).
But run-time instructions at assembly level are not a C issue.

Answers:21)


Not necessarily. Nothing in the Standard forbids implementations from
computing the negation at run-time. Of course, nobody does so because
it's simple to do at compile-time and potentially a great win, but this
is not required.

Answers:22)




Yes it will work.

Heres two counters for 32 bit integers:

int Count (unsigned int w)
{
w = (0x55555555 & w) + (0x55555555 & (w>> 1));
w = (0x33333333 & w) + (0x33333333 & (w>> 2));
w = (0x0f0f0f0f & w) + (0x0f0f0f0f & (w>> 4));
w = (0x00ff00ff & w) + (0x00ff00ff & (w>> 8));
w = (0x0000ffff & w) + (0x0000ffff & (w>>16));
return w;
}

/* slightly faster */
int Count (unsigned int w)
{
const unsigned int all1 = ~0;
const unsigned int mask1h = all1 / 3 << 1;
const unsigned int mask2l = all1 / 5;
const unsigned int mask4l = all1 / 17;
w -= (mask1h & w) >> 1;
w = (w & mask2l) + ((w>>2) & mask2l);
w = w + (w >> 4) & mask4l;
w += w >> 8;
w += w >> 16;
return w & 0xff;
}

Answers:23)



If the intention is to call the function from either signed or unsigned
int, then the code will not work on non-2s complement machiens for
signed ints.

Say for example you have -0 on a sign-mag or 1s comp. machine in an int
variable y:

Even though the y is not devoid of set bits on those machines, once the
call is made to the function and the variable is converted from signed
-> unsigned, C's rules will whipe out all the set bits (via -0 +
UINT_MAX + 1). Your function will return 0 as the # of set bits
because of the conversion that took place on the argument before
function entry. This is an example of C's bias towards 2's complement
machines (which is understandable because 2's complement is the "best"
way to represent negative integers!).

So the authors of K&R were probably warning you about calling the
function with signed ints (not portable).


Answers:24)

[Given a bit-counting function that takes an unsigned int or unsigned
long parameter...]



Well, that depends on what one *wants*.


Indeed it will. And yet, on such a machine, if -0 is produced by
ordinary arithmetic (as opposed to being used to detect uninitialized
variables, for instance), C requires that x==y be true even if x
is -0 and y is +0. That is:

x = <expression 1>;
y = <expression 2>;
if (x == y && bitcount(x) != bitcount(y))
puts("how peculiar!");

should never print the message, even if x is -0 and y is +0. So
you might *want* bitcount() to return 0 in both cases.

On the other hand, if you want to inspect the representation,
rather than the value, of a variable, you can still write that:

int representational_bit_count(unsigned char *p, int size);
#define RBC(var) \
representational_bit_count((unsigned char *)&(var), sizeof(var))
...
if (x == y && RBC(x) != RBC(y))
puts("while x==y, their representations differ");

Note, however, that two identical and nonnegative values can still
have differing representations, if some of the bits in the
representations are padding bits.



While *I* am biased towards 2'sC I am not so sure C really is.
C gives you the ability to inspect representations (via pointers
and "unsigned char *"); it is up to you, the programmer, not to
abuse it.


Answers:25)


>> [Given a bit-counting function that takes an unsigned int or unsigned
>> long parameter...]
>>
>>> >If the intention is to call the function from either signed or
>>>unsigned
>>> >int, then the code will not work on non-2s complement machiens for
>>> >signed ints.
>
>>
>> Well, that depends on what one *wants*.
>> >
>
>>
>> Indeed it will. And yet, on such a machine, if -0 is produced by
>> ordinary arithmetic (as opposed to being used to detect uninitialized
>> variables, for instance), C requires that x==y be true even if x
>> is -0 and y is +0. That is:
>>
>> x = <expression 1>;
>> y = <expression 2>;
>> if (x == y && bitcount(x) != bitcount(y))
>> puts("how peculiar!");
>>
>> should never print the message, even if x is -0 and y is +0. So
>> you might *want* bitcount() to return 0 in both cases.
>>
>> On the other hand, if you want to inspect the representation,
>> rather than the value, of a variable, you can still write that:
>>
>> int representational_bit_count(unsigned char *p, int size);
>> #define RBC(var) \
>> representational_bit_count((unsigned char *)&(var),
>>sizeof(var))
>>

So what is truly the universal way of counting the respresentational
bits on any platform? I see that you (Chris) use a char pointer
somehow to cycle through the bytes, but will this catch all the extra
bits used for handling overflow detection etc?


Anyone know a truly universal function for counting all the setbits in
a signed or unsigned number? I presume the receiving function would
have to accept the parameter into a large signed integer (signed long
long ?).


Answers:26)




K&R2 was implying that the expression x &= (x-1) does not remove the
rightmost set bit on all implementations - negative 'even' integers in
sign-mag form will be left unchanged by x &= (x-1)



The function itself is portable, because unsigned numbers have no
issues.


================================END============================

Subject: Is my memory is not enough?

Question:

Dear members:

I am programming in C. I declare as follows but when running program,
there is a fatal error appear:


double a[255][255];
double b[255][255];


When I change it to

double a[255][255];
double b[255][100];


then it works.

I think the problem caused by the running out of memory.

But I am wondering why I use malloc function, there is no error:
------------------------
double **a;
double **b;

a=malloc(255*255*sizeof(double));
if(a==NULL)
printf("there is an error");
b= malloc(255*255*sizeof(double));
if(a==NULL)
printf("there is an error");
-------------------------


I think I am using the same volume of memory for both version. Why in
the first case, the memory is insufficient of memory and in the other,
it is big enough.

One more thing, I need to use 2D array. I try the following but there
is always error when I try to access to an element of the 2D array:


double **a;
double **b;

a=malloc(255*255*sizeof(double));
if(a==NULL)
printf("there is an error");
b= malloc(255*255*sizeof(double));
if(a==NULL)
printf("there is an error");

a[1][1]=1;<----- the error occurs


Pleas take a look and point out the error for me. or can you please
suggest me other more effective methods to use 2D array?

Thank you very much and look forward to your answer.
SIncerly yours




Answers:1)

>> Dear members:
>>
>> I am programming in C. I declare as follows but when running program,
>> there is a fatal error appear:
>>
>>
>> double a[255][255];
>> double b[255][255];
>>
>>
>> When I change it to
>>
>> double a[255][255];
>> double b[255][100];
>>
>>
>> then it works.
>>
>> I think the problem caused by the running out of memory.
>>
>> But I am wondering why I use malloc function, there is no error:
>> ------------------------
>> double **a;
>> double **b;
>>
>> a=malloc(255*255*sizeof(double));
>> if(a==NULL)
>> printf("there is an error");
>> b= malloc(255*255*sizeof(double));
>> if(a==NULL)
>> printf("there is an error");
>> -------------------------
>>
>>
>> I think I am using the same volume of memory for both version. Why in
>> the first case, the memory is insufficient of memory and in the
other,
>> it is big enough.
>>
>> One more thing, I need to use 2D array. I try the following but there
>> is always error when I try to access to an element of the 2D array:
>>
>>
>> double **a;
>> double **b;
>>
>> a=malloc(255*255*sizeof(double));
>> if(a==NULL)
>> printf("there is an error");
>> b= malloc(255*255*sizeof(double));
>> if(a==NULL)
>> printf("there is an error");
>>
>> a[1][1]=1;<----- the error occurs
>>


declare a and b like this

double *a[255];
double *b[255];


You have to declare a & b as pointers to an array of 255 doubles,
otherwise, how would the compiler know how much to "step over" when you
double dereference. I'm giving you a very simplistic answer (I think
you're a newbie). Reading the c.l.c FAQ will help you better
understand the concepts. For now, you can start making use of your
program by just changing the declarations to match what I have above.

See: http://www.eskimo.com/~scs/C-faq/s6.html for more details


As for your conventionally allocated arrays, I am not sure what
happened. Remember, malloc gives you access to a different type/area
of memory than those conventionally allocated arrays would be place in.


Answers:2)


>>declare a and b like this
>>
>>double *a[255];
>>double *b[255];
>>
>>
>>You have to declare a & b as pointers to an array of 255 doubles,


You have declared a and b as arrays of pointers, not as pointers to
arrays. If you want a pointer to an array, you need
double (*b)[255];

Answers:3)


Most likely the memory is allocated on the stack in one case, and on
the heap in the other. Your operating system probably has a limit on
the stack size. How you change that limit will depend on the
operating system; on unix systems the "limit" or "ulimit" command is
what you want.

Answers:4)


Or you can just allocate the memory on the heap and not have to
increase your stack limit every time you run the program.

=================================END=====================

Subject: What does this code mean???

Question:

I am reading the code of a program from the examples, but really don't
understand this one........

int i,j;

......................................................

while (scanf("%d",&i),j)
{
.........................................
}

So I think the question should become,
how does the compiler evaluate the expression, (int i,int j)??
(am I right?? 'cause scanf function returns an integer as I know)


Answers:

1)




Break it down like this:

scanf("%d", &i), j

The value returned by scanf is discarded and the whole expression
evaluates to the value of j. A sequence point occurs
at the comma. (See Annex C of the C Standard).

The loop is reading in values and will continue executing
while j is not 0.

As an example, see what this does:

/* comma.c */
#include <stdio.h>

int
main (void)
{
int a, b = 6;
int ret;

ret = (a = 5, b);

printf ("a: %d; ret: %d\n", a, ret);

return 0;
}

Answers:2)


True, but I must say that this is an inadvisable way of using the comma
operator. The scanf() call has nothing to do with whether or not the
loop continues at all. This use of the comma is mere obfuscation.


Answers:3)




That's your opinion of course. I like this style because the return value of
scanf is often ignored anyway and you dont need to put in 2 calls to scanf
as in:

scanf();
while(j)
{
scanf();
}



Answers:4)


Unfortunately true. Consider however there are very few situations where
ignoring the return value of scanf() isn't a bug.


Answers:5)



..... snip ...


I rarely use scanf so am not sure, but are there any situations in
which it isn't a bug?

Answers:6)


Only situations where you didn't care if the read operation failed or
encountered end-of-file, and the scanf() just readss characters without
writing values. scanf(fp, " ") to skip white-space perhaps in some odd
circumstances. Not very likely but it is difficult to say that there
is NO situation where this isn't a bug. Well actually easy to say, maybe I
should and just wait for others to come up with the counterexamples.




Answers:7)


I'm not aware of any for scanf, but sscanf can certainly be legitimately
used without checking the return value, because it leaves its arguments
alone if it has no data so they default to the latest value. Silly
example:

#include <stdio.h>
int main(void)
{
char buff[256];
int x = 0;
int y = 0;
while (fgets(buff, 256, stdin))
{
sscanf(buff, "%d%d", &x, &y);
printf("%d + %d = %d\n", x, y, x+y);
}
return 0;
}

I suppose one could use something similar with scanf() and check feof()
after each call.

Answers:8)
> >
>>
>>
>> That's your opinion of course. I like this style because the return value of
>> scanf is often ignored anyway [...]


What else do you ignore? NULL values from malloc() and
fopen()? Warning messages from compilers? STOP signs? Fire
alarms?

No wonder software sucks.


Answers:9)




No, that's not why. For example, the expressions separated by a string
of && operators are _also_ evaluated from left to right, but the value
of the whole expression is either 0 or 1, depending on any number of the
expressions, no matter whether the relevant ones are 1, 3.14159265,
&main, or any other non-zero value.

Your conclusion is correct in so far that the Standard says of the ,
operator that
- its operands are evaluated in the order left first, then right;
- because of the way its syntax it specified, it is left-to-right
associative (which, in conjunction with the above, also means that a
string of expressions separated by commas is evaluated left to right);
- the value and type of the whole expression are those of the right
argument.
However, the third requirement does not follow by necessity from the
first two at all.

=================================END==========================

subject: array performance

Question:

Hi,

I have on large threedimensional array
int largeArray[1024][64][4];
In a particular function I only need a part of this array
So I'm using a new variable and assign it the follwoing way:

int (*smallArray)[64][4];
smallArray = &largeArray[42];

Is the following code correct if I want to get the value of an element ?
int x = smallArray[0][0];


Is there a performance difference between retriveing many elements of the
small and the large array in my function ?

Answers:

1)


>> I have on large threedimensional array
>> int largeArray[1024][64][4];
>> In a particular function I only need a part of this array
>> So I'm using a new variable and assign it the follwoing way:
>>
>> int (*smallArray)[64][4];
>> smallArray = &largeArray[42];
>>
>> Is the following code correct if I want to get the value of an element ?
>> int x = smallArray[0][0];
>>

I don't think so. smallArray is a pointer to a list of int [64][4] s. So
smallArray[0] would be the first 2d array (&largeArray[42]), smallArray[1]
would be the next (&largeArray[43]) and so on. So smallArray[0][0] actually
returns a list of 4 integers, and you need (*smallArray)[0][0];

However I have been programming in C for years, and had to think about this.
This is the problem with mutli-dimensional arrays. Beyond the very basics,
the syntax is horrible and confusing and even an experienced programmer will
find it difficult to understand your program.

Depends on the platform. Your huge array probably won't fit in a cache, but
if you can arrange matters so that acesses that are continguous in memory
are also close together in order, you might see some speed-up. Declaring a
pointer to a small part of the array is unlikely to have an impact by
itself, but it might help you organise the code efficently.


Answers:2)

>>Hi,
>>
>>I have on large threedimensional array
>> int largeArray[1024][64][4];


largeArray is an array of 1024 arrays of 64 arrays of 4 int.

>>In a particular function I only need a part of this array
>>So I'm using a new variable and assign it the follwoing way:
>>
>>int (*smallArray)[64][4];


smallArray is a pointer to an array of 64 arrays of 4 int.

>>smallArray = &largeArray[42];


largeArray[42] is the n-th element (out of the possible 1024 elements)
of largeArray. this element is an array of 64 arrays of 4 int.
&largeArray[42] is the address of this element with the same type as
smallArray.

>>
>>Is the following code correct if I want to get the value of an element ?
>>int x = smallArray[0][0];


No. smallArray is a pointer to the first of a series of objects, each
of which is an array of 64 arrays of 4 int. smallArray[0] is the n-th
such object pointed to and is therefore an array of 64 arrays of 4
int. smallArray[0][0] is the n-th array (of the possible 64 arrays)
and has type array of 4 int.

As you have set it up, you need to use (*smallArray)[0][0].

Alternatively, you could consider the following:

largeArray[42] is a particularly object (out of the 1024 that
largeArray consists of) with type 64 arrays of 4 int.

In most contexts, the expression largeArray[42] evaluates to the
address of the first element, that is the address of the first array
of 4 int (out of the possible 64) with type pointer to array of 4 int.
One exception to this rule (there are others) is when the expression
is the operand of the & operators, as it is in your original code.

If you code
int (*smallArray)[4];
you can assign to it with
smallArray = largeArray[42];
and then refer to individual integers with smallArray[j] which I
find to be a much easier notation to read and to type.


A quality of implementation issue which is not part of the language we
discuss here. You can ask in a newsgroup where your compiler is
discussed.

=====================================END=======================



Subject: help broke prog up into functions now not working

Question:

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

#define FALSE 0
#define TRUE 1
#define LINESIZE 255

int setupoutfile(char filename[], FILE *outfile)
{
strcat(filename, ".js");
outfile=fopen(filename, "w+");
if(!outfile)
{
sleep(TRUE);
outfile=fopen(filename, "w+");
if(!outfile) return -1;
}
return 0;
}

int setupinfile(char filename[], FILE *infile)
{
infile=fopen(filename, "r+");
if(!infile)
{
sleep(TRUE);
infile=fopen(filename, "r+");
if(!infile) return -1;
}
return 0;
}

int mymenu(FILE *infile, FILE *outfile)
{
char line[LINESIZE]="\0";
int i=0;

while(fgets(line, LINESIZE, infile)!=NULL)
if(strstr(line, ".gif")!=NULL || strstr(line, ".jpg")!=NULL)
{
line[strlen(line)-1] = '\0';
fprintf(outfile, "myImages[%d]=\"%s\"\n", i++, line);
}
return 0;
}

int main(int argc, char *argv[])
{
FILE *infile, *outfile;

if(argc>2) setupoutfile(argv[2], outfile);
if(argc>1) setupinfile(argv[1], infile);
else
{
printf("mymenu infname basefolder -> basefolder.js\n");
return -1;
}
mymenu(infile, outfile);
return 0;
}

Answers:

1)


> #include <stdio.h>
> #include <string.h>
>
> #define FALSE 0
> #define TRUE 1
> #define LINESIZE 255
>
> int setupoutfile(char filename[], FILE *outfile)
> {
> strcat(filename, ".js");

You are passing argv[2] as filename; there is no space left
for ".js". You need an array of char or allocated storage
of at least strlen(filename)+strlen(".js")+1 bytes.
> outfile=fopen(filename, "w+");
> if(!outfile)
> {
> sleep(TRUE);

sleep() is not a standard C function.
> outfile=fopen(filename, "w+");

You are assigning the return value to outfile. Unfortunately,
the value written to outfile will be lost to you as soon as
you leave this function.
Pass FILE **outfile to the function and assign to *outfile.
> if(!outfile) return -1;
> }
> return 0;
> }
>
> int setupinfile(char filename[], FILE *infile)
> {
> infile=fopen(filename, "r+");


same as above
> if(!infile)
> {
> sleep(TRUE);
> infile=fopen(filename, "r+");
> if(!infile) return -1;
> }
> return 0;
> }
>
> int mymenu(FILE *infile, FILE *outfile)
> { char line[LINESIZE]="\0";
> int i=0;
>
> while(fgets(line, LINESIZE, infile)!=NULL)
> if(strstr(line, ".gif")!=NULL || strstr(line, ".jpg")!=NULL)
> {
> line[strlen(line)-1] = '\0';


Umh, what exactly do you think you are doing here?
If line[strlen(line)-1] is _not_ '\n', you may very well discard
the 'f' of gif or the 'g' of jpg.
> fprintf(outfile, "myImages[%d]=\"%s\"\n", i++, line);
> }
> return 0;
> }
>
> int main(int argc, char *argv[])
> {
> FILE *infile, *outfile;
>
> if(argc>2) setupoutfile(argv[2], outfile);

Here, with the changes suggested above, you need to pass
a large enough buffer containing a copy of the string in argv[2]
and &outfile.
> if(argc>1) setupinfile(argv[1], infile); else
> {
> printf("mymenu infname basefolder -> basefolder.js\n");
> return -1;
> }


This logic is badly broken.

What do you want? Probably:
if (argc > 2) {
char *buffer = malloc(strlen(argv[2])+4);
if (!buffer) {
fprintf(stderr,"Mem trouble\n");
exit(EXIT_FAILURE);
}
strcpy(buffer, argv[2]);
setupoutfile(buffer, &outfile);
setupinfile(argv[1], &infile);
free(buffer);
}
else {
/* usual stuff */
}

By the way, if you do not want to return 0, rather use
exit(EXIT_FAILURE) (and #include said:
> mymenu(infile, outfile);
> return 0;
> }


Answers:2)



>


In this case you might just as well make it the return value of the
function, with a null pointer return indicating a failure.

Answers:3)


> {
> FILE *infile, *outfile;


How are these pointers initialized ?
> if(argc>2) setupoutfile(argv[2], outfile);
> if(argc>1) setupinfile(argv[1], infile);


Don't you meant

if(argc>2) setupoutfile(argv[2], &outfile);
if(argc>1) setupinfile(argv[1], &infile);

or the like... Of course the prototypes of the functions have to be
redesigned...

int setupoutfile(char filename[], FILE **outfile)


=================================END=====================
Subject: File handling

Question:

Hello everyone...........
I have a problem on retriving a content of a binary file I wrote into.
My program user structures, dynamic allocation of memory and files. I
take the infomation into a dynamicaly allocated structure and then
write it to a binary file using fwrite() with appending mode. I can
retrive the data I wrote while the program is running. But if I stop
the program and re-execute it I can't read the things I wrote to the
file last time(only some vieard characters appear), but the the data I
wrote this time appeard without any problem.
How can I retrive the data I wrote to the file previousy.
Souce code of the program I wrote is as follows,

#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include<string.h>
#include<ctype.h>

typedef struct student{
char *name;
int age;
}stu;

void stu_initializer(stu *p,FILE *fp);
void print_stu(stu *p, FILE *fp);

void main()
{
clrscr();
stu *p;
FILE *fp;

//allocate memory for the structure
p=(stu*)malloc(sizeof(stu));
fp=fopen("stu.dat","a+b");

stu_initializer(p,fp);
fclose(fp);

clrscr();
fp=fopen("stu.dat","rb");
print_stu(p,fp);


fclose(fp);
free(p);
}////end main

/////////////////////////////////////////////////////////////////////
//set the information about the parties
void stu_initializer(stu *p,FILE *fp)
{
int a;
char buffer[81];



do{clrscr();
printf("Enter the student name: ");
gets(buffer); fflush(stdin);
//alocate memory for the stu name inside the structure


p[0].name=(char*)malloc((strlen(buffer)+1)*sizeof(char));
strcpy(p[0].name,buffer);//copy the name to the structure

//age of the student
printf("\nEnter the index of the stu? ");
scanf("%d",&p[0].age);
fflush(stdin);
//write to the file
fwrite(p,sizeof(*p),1,fp);
printf("\n\nAny more students?[Y][N] ");
}while(toupper(getch())=='Y');

clrscr();
fflush(stdin);//clear the input buffer


}//end function

/////////////////////////////////////////////////////////////////////
//print the stu list
void print_stu(stu *p, FILE *fp)
{
printf("%s %s \n","Name","Age");
while((fread(p,sizeof(*p),1,fp))==1)
printf("%s %d\n",p[0].name,p[0].age);
}



Please Help me on this problem.......

Answers:

1)

You are writing out a structure that has 1) a pointer and 2) an int. To
be certain, your pointer might possibly point to a string, but at the
moment you are only writing out the pointer to your string in
memory--and once the application ends everything that was in memory
will go away and your pointer when read back in the next time you run
the application will just point to some random location in memory with
who knows what data in it.

One thing to note, once you do write out your strings, you will
probably also want to write out their lengths into the file as well.
Either that or you're going to have to read a whole bunch of strings in
and then go searching about for the end of lines or \0s that you wrote
out.

Also, if you open your file with notepad (or whatever), you should be
able to see any text that you have written into it. There will be some
junk characters between the text (which will be the integers) but so
long as there _is_ text you are one step ahead.



Answers:2)




Since there are that many errors in this program I mostly restrict
my comments to the first occurence of an error...



Both <conio.h> and <malloc.h> aren't standard C header files. Replace
<malloc.h> with <stdlib.h>. I have no idea what <conio.h> is supposed
to do.



main() is always supposed to return an int. And it has either zero
or two arguments, so make that

int main( void )

(or

int main( int argc, char *argv[ ] )

in case you are interested in the command line arguments).



What's that supposed to do? It's not a standard C function.



Unless you have a C99 compliant C compiler all variable definitions
mus come before the first executable statement.



Please use normal C style comments, i.e. '/*' and '*/', when you
post in newsgroups. The C++ style comments were only introduced
with the new C99 standard and often make it hard to see where a
comment ends when a newsreader wraps long lines.



1) Check the return value of malloc().
2) Drop the cast. It's not needed and will keep the compiler from
complaining when you forgot to include the header file where


Check the return value of fopen().



There's no declaration of this function (the definition only comes
later), so the compiler can't check if you call it with the correct
arguments,



Again no declaration for the function...



Since main() must return an integer you're missing a return statement
here.

>> /////////////////////////////////////////////////////////////////////
>> //set the information about the parties
>> void stu_initializer(stu *p,FILE *fp)
>> {
>> int a;
>> char buffer[81];
>> do{clrscr()
>> printf("Enter the student name: ");


Unless the line ends with a '\n' it usually isn't printed immediately.
You need a 'fflush(stdout);' after this.



Now, that's really horrible. First of all. Never, ever use gets().
There is no way to keep the user from entering more character
than fit into the buffer gets() puts them in. The function is
broken by design. Use fgets() instead.

Second, you can't fflush() stdin, you can only fflush() output
channels.

>> //alocate memory for the stu name inside the structure
>> p[0].name=(char*)malloc((strlen(buffer)+1)*sizeof(char));


sizeof(char) is 1 by definition. And why do you use 'p[0]' here?
Since 'p' isn't an array it would be clearer to use 'p->name'.

>> strcpy(p[0].name,buffer);//copy the name to the structure
>> //age of the student
>> printf("\nEnter the index of the stu? ");
>> scanf("%d",&p[0].age);


Don't use scanf() when reading user input - if what the user enters
isn't an integer you will get rather starnge results. Use fgets() to
get the whole stuff and then use e.g. sscanf() to get the value,
giving you a chance to check if there was an integer at all.



Now you try to write a structure, containing a pointer to a string.
Once you read back in the file what the pointer points to is rather
likely not the string that was at that address before. You have to
write the string itself into the file, not just a pointer to were
that string was sometime in the past. You might get away with that
here by accident since you read back the structures within the same
program (and since you never deallocate the memory for the strings
once they aren't used anymore), but never if you try to read them
back from a file in a newly started program.

Moreover, you only write out as many bytes as a pointer to such a
structure has because of the '*' in front of 'p'. But if you want
to write out the structure you must fwrite() as many bytes as the
structure is long.

>> printf("\n\nAny more students?[Y][N] ");
>> }while(toupper(getch())=='Y');


getch() isn't standard C function, so I can't see if this here is
correct...



No, you clear the input buffer by reading until nothing is in
there anymore.



This won't work for the multiple reasons given above.

>> printf("%s %d\n",p[0].name,p[0].age);
>> }


As a rule writing out structures in binary form is a bad idea. Even
if you get it right it will only work in case you read back the file
on a machine with the same archtitecture and may require to have the
programs for writing and reading where compiled with the same com-
piler.

=======================================END=======================

--
"combination is the heart of chess"

A.Alekhine

Mail to:
sathyashrayan AT gmail DOT com


--
"combination is the heart of chess"

A.Alekhine

Mail to:
sathyashrayan AT gmail DOT com
 
J

Jack Klein

Following are the selected thread from the date:30-jan-2005 to
31-jan-2005. I did not use any name because of the subject is important.
You can get the original thread by typing the subject "string" in google
comp.lang.c archives.Hope this helps.Hope I am not bothering any one. am I?

Exactly why are you wasting bandwidth and storage on servers all over
the world to repost messages that already exist in comp.lang.c and the
Google archive?

I don't know what your reason is, but this is extremely bad manners.
You are liable to get yourself kill filed by a large number of
readers, and perhaps enough complaints to Google to get your posting
account cancelled.

Don't do this again.
 
M

Mark McIntyre

Surely you did not mean to quote the whole thing?!?

I most assuredly did not.... somehow my newsreader hid the rest of the post
from me, and I therefore didn't snip it. Dang. Sorry.
 
M

Mark McIntyre

What made you quote the whole 2500 odd lines of monstrosity? You
are making yourself at least as big a nuisance as he is. Don't do
it again or I will sic Dan Pop on you. :)

I already castigated myself with scorpions.....
 

Ask a Question

Want to reply to this thread or ask your own question?

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.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top