FRIHOST FORUMS SEARCH FAQ TOS BLOGS COMPETITIONS
You are invited to Log in or Register a free Frihost Account!


C/C++





hunnyhiteshseth
I find various C/C++ questions scattered around. So, I thought we should have a thread specifically for C/C++ questions. Anybody having any problem should post here.

So, I request mods to please make this topic sticky.
AftershockVibe
But what if two questions (or more) are asked at the same time by different people. The thread will become a hideous mess!
hunnyhiteshseth
AftershockVibe wrote:
But what if two questions (or more) are asked at the same time by different people. The thread will become a hideous mess!


So, we may have following rules:-

1) Each question will have a different color. So, reply to a particular question should be made in that color only.

2) Each question will have a lifetime of 7 days after which it will be deleted. If anybody still is searching for answer he may repost the question for another week.
AftershockVibe
Well yes that..... or we can just do separate posts which is what forum systems are supposed to be used for.

It's already recommended (unless it was lost in the forum re-jig) that people use tags (like [C++] or [Java]) to say what language they are working in.
hunnyhiteshseth
Yes, but what happens is that between so many posts, any post related to one subject gets lost very easily. If, we are going to have a sticky, so any body only interested in C/C++ will not have to search whole forum, he will just have to go to one sticky.
Nyizsa
hunnyhiteshseth wrote:
Yes, but what happens is that between so many posts, any post related to one subject gets lost very easily. If, we are going to have a sticky, so any body only interested in C/C++ will not have to search whole forum, he will just have to go to one sticky.

The forum is (easily) searchable. A topic is not.
Stubru Freak
Listen.

It's not gonna happen.

If we'd do this for all languages, we'd end up with 5 huge threads per forum. If you want C/C++ to be seperate from other languages, ask the mods to make a seperate forum for it.
snowboardalliance
many short specific threads > one huge barely organized thread
hyhy
There should be programing subforum in scripting section including everything related to C, C++, C#, Pascal, Perl, Python, and the rest!
hunnyhiteshseth
Ok, with so much resistance, may be I am wrong. It was just a suggestion, rest what mods will decide I will accept.
rayx
All reply for this is OFF TOPIC this forum should be talking about C/C++.
Shirish
I have found a really simple solution to ur problem

for every question must be posted directly to the forum


no color required'

now when a person wants to put up the answer he must use Quote on right of the question he's referring


that simple..


I think now we can start out on posting questions


First Question from My side


IS Class based Objects are initialized at compile time or untime when we don't use any "new" operator...
hunnyhiteshseth
I think they are initialized at compile time, if you use new operator then at runtime.
Indi
Shirish wrote:
IS Class based Objects are initialized at compile time or untime when we don't use any "new" operator...

Nothing is initialized at compile time. Everything that happens in C++, except for template metaprograms and any preprocessor "code", happens at runtime.
BruceTheDauber
Indi wrote:
Shirish wrote:
IS Class based Objects are initialized at compile time or untime when we don't use any "new" operator...

Nothing is initialized at compile time. Everything that happens in C++, except for template metaprograms and any preprocessor "code", happens at runtime.


Some things are. If you wrote

static const int i = 45;

That would be initialized at compile time.

If you look at an interesting library called Blitz++, you'll find that it can implement complex algorithms and initialize arbitrarily complicated data structures all at compile time, by making clever use of templates.

It wouldn't really be possible for templates to do things at compile-time if it weren't for the fact that statics and literals are initialized at compile time.
Indi
BruceTheDauber wrote:
Indi wrote:
Shirish wrote:
IS Class based Objects are initialized at compile time or untime when we don't use any "new" operator...

Nothing is initialized at compile time. Everything that happens in C++, except for template metaprograms and any preprocessor "code", happens at runtime.


Some things are. If you wrote

static const int i = 45;

That would be initialized at compile time.

If you look at an interesting library called Blitz++, you'll find that it can implement complex algorithms and initialize arbitrarily complicated data structures all at compile time, by making clever use of templates.

It wouldn't really be possible for templates to do things at compile-time if it weren't for the fact that statics and literals are initialized at compile time.

That is not initialized at compile time. By the same token you could write:

std::string const s("whatever");

Are you going to tell me now that the constructor for string runs at compile time?

The same logic applies for the int. Its "constructor" (such as it is) is not run until runtime. Its constructor may do nothing, or it may load 45 into a special segment of read-only memory. The latter shows that it cannot be run at compile time.

Literals are not initialized at compile time because they are never initialized. They are literals.

And I assume when you said "statics" you meant "consts", in which case, no they're not initialized. However, during the compile phase integral type consts can be treated as an alias for the literal, the same way as a #define macro is. It's not initialization, but it looks like it.

I am not familiar with Blitz++, but I have seen lots of funky template metaprogramming tricks done. I suspect you're misrepresenting what the templates do. The template code probably expands to initialization statements, but those statements are not run until runtime.
BruceTheDauber
Indi wrote:
BruceTheDauber wrote:


static const int i = 45;


That is not initialized at compile time. By the same token you could write:


Yes, it is. Read:

Quote:
Static objects of POD (Plain Old Data) types initialized with constant expressions shall be initialized before any run time initialization is done.


http://www-d0.fnal.gov/KAI/doc/tutorials/static_initialization.html

In practice, that means at compile time.

Indi wrote:

std::string const s("whatever");

Are you going to tell me now that the constructor for string runs at compile time?


No, because objects of type std::string are not POD ("Plain Old Data"). String literals are POD, therefore the following is initialized at compile time:

Code:

static char * str = "This is a string";


and so is this:

Code:
static wchar_t * str = L"This is a wide string";


Indi wrote:
Literals are not initialized at compile time because they are never initialized. They are literals.


What you are saying directly contradicts what the C++ standard says.


Indi wrote:
And I assume when you said "statics" you meant "consts", in which case, no they're not initialized.


Again, what you are saying directly contradicts what the C++ standard says. Also, I do not mean consts. Static values do not have to be declared
Code:
const
in order to be initialized at compile time (and the same goes for globals).


Quote:
However, during the compile phase integral type consts can be treated as an alias for the literal, the same way as a #define macro is. It's not initialization, but it looks like it.


I'm sorry, but you are not talking the language of C++, but another language altogether. When the value represented by a name is set for the first time, that's initialization, as far as C++ is concerned. There isn't something else that "looks like" initialization.

Quote:
I am not familiar with Blitz++, but I have seen lots of funky template metaprogramming tricks done. I suspect you're misrepresenting what the templates do. The template code probably expands to initialization statements, but those statements are not run until runtime.


Wrong again. They are run at compile time. Any documentation describing Blitz++ will tell you this fact -- e.g.:

Quote:
By using templates cleverly, optimizations such as loop fusion, unrolling, tiling, and algorithm specialization can be performed automatically at compile time. Another goal of Blitz++ is to extend the conventional dense array model to incorporate new and useful features. Some examples of such extensions are flexible storage formats, tensor notation and index placeholders.


http://www.univ-orleans.fr/mapmo/membres/filbet/vadorh/node6.html
Indi
BruceTheDauber wrote:
Quote:
Static objects of POD (Plain Old Data) types initialized with constant expressions shall be initialized before any run time initialization is done.


http://www-d0.fnal.gov/KAI/doc/tutorials/static_initialization.html

In practice, that means at compile time.

What it means is that you have misunderstood the implications of the statement. Whoever wrote the documentation for the Kai compiler has apparently chosen to refer to variables whose values cannot be known until run time (as opposed to variables whose values are known as literals or other constant expressions) as run time initialized variables. That term is not part of the standard documentation, and it is misleading.

Read the standard and see. It says nothing about compile-time initialization or run-time initialization. What it says is that "The storage for objects with static storage duration shall be zero-initialized before any other initialization takes place. Objects of POD types with static storage duration initialized with constant expressions shall be initialized before any dynamic initialization takes place." (Note that dynamic initialization means not initialized with a constant.) You see anything in there that says compile time? It just says "before".

And in fact, all POD types cannot be portably initialized at compile time. You are aware that POD types can have constructors, right? And that those constructors can throw? Just read ISO/IEC 14882 3.9.1-3 and see. How can they then be constructed at compile time?

BruceTheDauber wrote:
String literals are POD, therefore the following is initialized at compile time:

You do not seen to be aware of what a literal is.

BruceTheDauber wrote:
Indi wrote:
Literals are not initialized at compile time because they are never initialized. They are literals.


What you are saying directly contradicts what the C++ standard says.

Oh? Quote me the standard clause that states 2 or "text" is initialized. That's what a literal is. In what you wrote:
Code:
static char * str = "This is a string";

str is not a literal. "This is a string" is. Literals are not initialized. They are raw data, not variables. Ltierals can be used to initialize, but they are not initialized.

BruceTheDauber wrote:
Indi wrote:
And I assume when you said "statics" you meant "consts", in which case, no they're not initialized.


Again, what you are saying directly contradicts what the C++ standard says. Also, I do not mean consts. Static values do not have to be declared
Code:
const
in order to be initialized at compile time (and the same goes for globals).

Oh?
Code:
int N1 = 8;

int main()
{
   static int N2 = 6;
   
   int array1[N1];
   int array2[N2];
   
   return 0;
}

Then the code above should compile on a C++ compiler that doesn't support C99 runtime variable length arrays, shouldn't it?

BruceTheDauber wrote:
Quote:
However, during the compile phase integral type consts can be treated as an alias for the literal, the same way as a #define macro is. It's not initialization, but it looks like it.


I'm sorry, but you are not talking the language of C++, but another language altogether. When the value represented by a name is set for the first time, that's initialization, as far as C++ is concerned. There isn't something else that "looks like" initialization.

Oh?
Code:
#define SOME_MACRO "Some data"
So I have just initialized the variable SOME_MACRO? How peculiar, considering that it's not even a variable, it's a preprocessor macro.

And yet at compile-time it behaves in pretty much exactly the same way as:
Code:
char const SOME_MACRO[] = "Some data";


BruceTheDauber wrote:
Quote:
I am not familiar with Blitz++, but I have seen lots of funky template metaprogramming tricks done. I suspect you're misrepresenting what the templates do. The template code probably expands to initialization statements, but those statements are not run until runtime.


Wrong again. They are run at compile time. Any documentation describing Blitz++ will tell you this fact -- e.g.:

Quote:
By using templates cleverly, optimizations such as loop fusion, unrolling, tiling, and algorithm specialization can be performed automatically at compile time. Another goal of Blitz++ is to extend the conventional dense array model to incorporate new and useful features. Some examples of such extensions are flexible storage formats, tensor notation and index placeholders.


http://www.univ-orleans.fr/mapmo/membres/filbet/vadorh/node6.html

Um. Dude. I said explicitly that template metaprograms are run at compile-time. That's all that Blitz++ is doing. No initializations or any non-template metaprogramming code would be done at compile-time.

Let me ask you two simple questions. First, you never addressed my point that even the initialization of consts requires some platform code to be run on some platforms. On some platforms, when you write "int const N = 2", that means a special read-only section of memory is initalized with the literal value 2. How can this be, if initialization happens at compile time?

And secondly, often not only is a program compiled on a different computer, it is compiled on a different operating system - as in the case of cross-compiling. How can any initialization be done (or any code run at all) with a cross-compiler without effectively creating a stripped-down emulator within the compiler? And if that's how you think it's actually done, explain to me the design of gcc. How can any initialization be done at compile time when the front end doesn't even know what the back end will be compiling for? 'a' may be 97 (ASCII) or 129 (EBCDIC) - the gcc front end has no way of knowing.
trimbaard
OOK NEDERLANDERS HIER
tony
trimbaard wrote:
OOK NEDERLANDERS HIER


is this spam?
mukesh.cv19@gmail.com
u can find good c/c++ tutorials here ...

http://www.cprogramming.com/tutorial.html

________________
looseballs
Hey, thanks, i was looking for a tutorial, scrolled down to ask for 1, and BAM, the last post plainly says, heres a tutorial. Thanks, ill check it out.
darth_revan
Well, i'd better inform you about define and const.
(some information: size of one floating number is 4 bytes normally)

when you do that:
const float PI 3.1428
you take a space of four bytes from the RAM, and make it 3.1428. You cannot change that space anymore.

But when you do that:
#define PI 3.1428
the compiler changes PI with 3.1428 when you compile your code. it takes no memory, so it's better to use #define. but don't forget that,

PI3
means
3.14283, since the compiler changes Pi with 3.1428 without thinking.
so when you make a code like that:
#define ABS(x) x>0 ? x : -x
it doesn't work correctly. for example,
ABS(3-5) is normally 2, since -2 <0.
but when you do that code:
ABS(3-5);
you do that:
3-5>0 ? 3-5 : -3-5
so, it is -8.

How to correct it? simple:

#define ABS(x) x>0 ? (x) : (-(x))
this will not fail.
Indi
darth_revan wrote:
Well, i'd better inform you about define and const.
(some information: size of one floating number is 4 bytes normally)

Yeah? Define "normally". ^_^' And... just how big is a byte, "normally".

But anyway....

darth_revan wrote:
when you do that:
const float PI 3.1428
you take a space of four bytes from the RAM, and make it 3.1428. You cannot change that space anymore.

But when you do that:
#define PI 3.1428
the compiler changes PI with 3.1428 when you compile your code. it takes no memory, so it's better to use #define. but don't forget that,

False.

When you do:
Code:
float const PI = 3.1416f; // Incidently, your approximation was incorrect

float pi_times_2 = PI * 2;

The compiler is not required to allocate space for PI - it can perform a text substitution just as if it were a macro define.

(And even if that were not true, and the compiler did choose to allocate space for PI on the first pass, it could optimize that space away on a later pass.)

However, when you do:
Code:
float const PI = 3.1416f;

float const* pointer_to_pi = &PI;

Then yes, the compiler has to allocate space for PI, because you can't take the address of a segment of memory that doesn't exist.

You should not use macro substitutions in modern code. #define is evil.

darth_revan wrote:
PI3
means
3.14283, since the compiler changes Pi with 3.1428 without thinking.

False. Try it and see.

And... not only false... but really, really bad code. >_< Yes, it can be done (although not the way you did it). But don't ever write C or C++ code like that.

darth_revan wrote:
so when you make a code like that:
#define ABS(x) x>0 ? x : -x
it doesn't work correctly. for example,
ABS(3-5) is normally 2, since -2 <0.
but when you do that code:
ABS(3-5);
you do that:
3-5>0 ? 3-5 : -3-5
so, it is -8.

How to correct it? simple:

#define ABS(x) x>0 ? (x) : (-(x))
this will not fail.

This is also bad practice in modern C++. Imagine if you did:
Code:
ABS(very_long_and_expensive_calculation_that_will_slow_down_your_program(x));

The macro expands to:
Code:
(very_long_and_expensive_calculation_that_will_slow_down_your_program(x)) > 0 ? (very_long_and_expensive_calculation_that_will_slow_down_your_program(x)) : -(very_long_and_expensive_calculation_that_will_slow_down_your_program(x));

That means that no matter what happens, that expensive calculation will be called twice.

Much better is this:
Code:
template <typename T>
inline T abs(T const& a)
{
   return a > T(0) ? a : -a;
}

// And another option, just to demonstrate the power of this method:
template <typename T>
inline T abs(T const& a, T const& zero)
{
   return a > zero ? a : -a;
}

abs(1); // Does what you expect
abs(3 - 5); // Does what you expect (and doesn't repeat the calculation)
abs(expensive_function()); // Does what you expect (and calls the function once)

// Bonus:
 // For really big numbers
BigNumber b1("-12546432623754848568945694549");

// If there is a constructor for BigNumber(int):
BigNumber b2 = abs(b1); // does what you expect

// Otherwise, for example:
BigNumber b3 = abs(b1, BigNumber("0"));

These are true functions, and can be called as first class citizens in C++. And they will work as expected, and call the expensive function only once. On top of that they can be specialized by type, and so on and so forth.

The moral of the story: DO NOT USE THE PREPROCESSOR IN C++. Just about the only things the preprocessor is good for in C++ are #includes and include guards... and... that... is... all...!
Stubru Freak
Indi wrote:
This is also bad practice in modern C++. Imagine if you did:
Code:
ABS(very_long_and_expensive_calculation_that_will_slow_down_your_program(x));

The macro expands to:
Code:
(very_long_and_expensive_calculation_that_will_slow_down_your_program(x)) > 0 ? (very_long_and_expensive_calculation_that_will_slow_down_your_program(x)) : -(very_long_and_expensive_calculation_that_will_slow_down_your_program(x));


That's not the worst. Imagine doing (I'm not good at C and I've never done anything database-related with it so this is pseudo-code):
Code:
ABS(database->getrow()->get('number'))

That would return the opposite of another row. Completely useless.
darth_revan
Indi wrote:

Yeah? Define "normally". ^_^' And... just how big is a byte, "normally".

Just like int (taking 2 to 4 bytes depending on your compiler), float may take more than 4 bytes. But gcc takes 4 byte. And, a byte is 8 bits, since an int can be up to 2^15 (first bit is sign bit, if zero, the number is greater than 0, i suppose.)
Indi wrote:

False.
When you do:
Code:
float const PI = 3.1416f; // Incidently, your approximation was incorrect

float pi_times_2 = PI * 2;

The compiler is not required to allocate space for PI - it can perform a text substitution just as if it were a macro define.

(And even if that were not true, and the compiler did choose to allocate space for PI on the first pass, it could optimize that space away on a later pass.)

However, when you do:
Code:
float const PI = 3.1416f;

float const* pointer_to_pi = &PI;

Then yes, the compiler has to allocate space for PI, because you can't take the address of a segment of memory that doesn't exist.

You should not use macro substitutions in modern code. #define is evil.

Nah, when you use that code:
Code:

typename a;

the compiler takes sizeof(typename) bytes from the ram. How can it know that we are going to use a pointer to point its space, or just multiply it?
Indi wrote:

darth_revan wrote:
PI3
means
3.14283, since the compiler changes Pi with 3.1428 without thinking.

False. Try it and see.

And... not only false... but really, really bad code. >_< Yes, it can be done (although not the way you did it). But don't ever write C or C++ code like that.

yup, it was false. but it's just to make people realize that define is not a logical thing, its just changing something into something.
Indi wrote:

darth_revan wrote:
so when you make a code like that:
#define ABS(x) x>0 ? x : -x
it doesn't work correctly. for example,
ABS(3-5) is normally 2, since -2 <0.
but when you do that code:
ABS(3-5);
you do that:
3-5>0 ? 3-5 : -3-5
so, it is -8.

How to correct it? simple:

#define ABS(x) x>0 ? (x) : (-(x))
this will not fail.

This is also bad practice in modern C++. Imagine if you did:
Code:
ABS(very_long_and_expensive_calculation_that_will_slow_down_your_program(x));

The macro expands to:
Code:
(very_long_and_expensive_calculation_that_will_slow_down_your_program(x)) > 0 ? (very_long_and_expensive_calculation_that_will_slow_down_your_program(x)) : -(very_long_and_expensive_calculation_that_will_slow_down_your_program(x));

That means that no matter what happens, that expensive calculation will be called twice.

Much better is this:
Code:
template <typename T>
inline T abs(T const& a)
{
   return a > T(0) ? a : -a;
}

// And another option, just to demonstrate the power of this method:
template <typename T>
inline T abs(T const& a, T const& zero)
{
   return a > zero ? a : -a;
}

abs(1); // Does what you expect
abs(3 - 5); // Does what you expect (and doesn't repeat the calculation)
abs(expensive_function()); // Does what you expect (and calls the function once)

// Bonus:
 // For really big numbers
BigNumber b1("-12546432623754848568945694549");

// If there is a constructor for BigNumber(int):
BigNumber b2 = abs(b1); // does what you expect

// Otherwise, for example:
BigNumber b3 = abs(b1, BigNumber("0"));

These are true functions, and can be called as first class citizens in C++. And they will work as expected, and call the expensive function only once. On top of that they can be specialized by type, and so on and so forth.

The moral of the story: DO NOT USE THE PREPROCESSOR IN C++. Just about the only things the preprocessor is good for in C++ are #includes and include guards... and... that... is... all...!

ABS was just for types like int, float etc. You can use a temp to speed up if you use it for functions.
Define is good, as long as you know how to use it
Indi
darth_revan wrote:
Indi wrote:

Yeah? Define "normally". ^_^' And... just how big is a byte, "normally".

Just like int (taking 2 to 4 bytes depending on your compiler), float may take more than 4 bytes. But gcc takes 4 byte. And, a byte is 8 bits, since an int can be up to 2^15 (first bit is sign bit, if zero, the number is greater than 0, i suppose.)

That is incorrect on all counts.

First, a byte is not necessarily 8 bits (see here). A byte is the smallest addressible unit of memory on a system. I know that it is common usage to use byte to mean 8 bits because almost all desktop computers have 8-bit bytes, but C++ (and also C) is not just a desktop programming language. It is used to program everything from supercomputers to embedded microchips. Because of that, you cannot assume that a byte is 8 bits in a C++ program. At one time I was programming a DSP chip with 16-bit bytes - the TMS3020 (I may have the name wrong because it was a while ago, but it is a Texas Instruments DSP still used in things like MP3 players). I have also seen machines with 9 and 14 bit bytes. (Actually, a byte has a special definition in C/C++ related to the execution character set, but it still leaves you with the fact that a byte is not guaranteed to be 8 bits in C or C++.)

Second, an int is not necessarily 2-4 bytes. An int is the natural word size of the system. That is commonly 32 bits on current desktop systems, but 16 bits used to be common, and 64 bits are the next wave. With an 8 bit byte, that means that int byte sizes of 4 (32 bit ints), 2 (16 bit ints) and 8 (64 bit ints) are common in desktop programming. However, once again, once you leave the realm of the desktop, you can have ints that are 1, 2, 3, 4, 6, 8, 10 or more bytes big.

Of course, when you start talking about floats and other types, they can be pretty much anything.

If you're just going to stay in the realm of programming Windows, Linux or Mac desktop systems, you can usually get away with the generalizations that you made, but be very careful. Tons and tons and tons of otherwise perfectly good programs broke during the transition from 16 to 32 bit systems because people assumed a byte was 8 bits and an int was 2 bytes (or that a short and an int were the same size). You'd think people would learn, but they haven't. There will be another massive wave of broken software in the move from 32 to 64 bit bytes - and even Microsoft's desparate attempt at maintaining compatibility (LLP64) will not save everyone. If you have ever written software that assumes an int is 2-4 bytes, or that a pointer is the same size as an int, or that a long is the same size as an int (all sins that Microsoft itself is guilty of in its Windows API, which is why it went LLP64), you will also be burned by the transition to 64 bits.

The lessons in all this are:
  1. Do not assume a byte is 8 bits. A byte is CHAR_BIT bits long, where CHAR_BIT >= 8.
  2. Do not assume an int is 16 or 32 bits. An int is sizeof(int) * CHAR_BIT bits long, where sizeof(int) * CHAR_BIT >= 16.
  3. Do not assume an int can hold numbers from -32768 to 32767 or from -2147483648 to 2147483647. An int can hold from INT_MIN to INT_MAX (or even better, numeric_limits<int>::min() to numeric_limits<int>::max()). The minimum range you can count on is -32767 to 32767.
  4. Do not assume an int is the same size as a pointer. Shamefully, this is a mistake that even Microsoft is guilty of.


darth_revan wrote:
Nah, when you use that code:
Code:

typename a;

the compiler takes sizeof(typename) bytes from the ram.

Not necessarily. There are dozens of factors that affect whether or not a variable declared like that actually takes up any space at all, let alone space in RAM. In fact, the vast majority of cases do not take up space in RAM - they are simply virtual variables approximated by registers. In fact, in the hypothetical function below:
Code:
int convert_traditional_japanese_year_to_gregorian(int j_year, int j_era)
{
   int year = j_year;
   
   switch (j_era)
   {
   case heisei:
      year += 1989;
      break;
   case shouwa:
      year += 1926;
      break;
   case taishou:
      year += 1912;
      break;
   case meiji:
      year += 1868;
      break;
   }
   
   return year;
}

it is very possible that not a single variable will be in RAM - not even the function parameters or the "stack frame". In fact, it is entirely possible - even likely - that RAM may not be used at all at any point in the entire execution of the function, from pre-calling to post-returning. (With the possible exception of the fact that the program code itself would usually be in RAM.)

In fact, the only way you can be "sure" that a variable is in RAM (and even then, you won't be 100% sure) is:
  • If you put it there explicitly (using OS functions or compiler commands).
  • If you take its address in one way or another (this includes dynamic allocation).
  • If it's really big.


darth_revan wrote:
How can it know that we are going to use a pointer to point its space, or just multiply it?

Simple. It's the compiler. It will compile the variable declaration... as well as the multiplication and/or address taking. It will have all the information it needs to make that decision.

Remember that there are two fundamentally different types of variables in C and C++ - internal and external linkage. Obviously variables with external linkage must be in RAM (usually). But variables with internal linkage do not automatically need to be in RAM. When compiling a translation unit, a compiler has all of the information it needs to have about variables with internal linkage right at hand - including everywhere they're used. Therefore it is a trivial matter to optimize variables with internal linkage.

In the case here, a variable declared const is internal by default (with some exceptions - see the standard). Therefore the compiler can determine whether or not it actually needs to be allocated in RAM right at compile time - all in one translation unit. Of course, that's the compiler's decision - it might still allocate a const variable in RAM (although you'll probably never use a compiler that will, with even a low level of optimization turned on). But then again, it might also allocate RAM for #define by creating a virtual variable. You can't control the compiler completely, so you might as well trust in it. If it's really that important to you that your variable takes up no memory, what you're effectively saying is that you need a compiler that optimizes well. And a compiler that optimizes well will not allocate memory for true constants that it doesn have to. So you're done. Simple. (And if it's really that important that a variable not take up memory, and you can't get a better compiler... still don't use a macro, use an enum. There is no good argument for using #define.)

There are essentially two types of constants in C++, true constants and pseudo-constants. True constants are constants that can be determined at compile-time, pseudo-constants are determined at run-time. For example:
Code:
float const PI = 3.1416f; // Completely determined
float const pi_times_2 = PI * 2; // Can be done by the compiler
float const root_pi = sqrt(PI); // Cannot be done by the compiler

The compiler can do simple math operations, but cannot call functions, and of course, cannot do anything that requires memory addresses. So the first two can potentially be constants, the last cannot.

One of the design goals of the C++ committee was to make the preprocessor obsolete. Because of that, const variables were expanded to allow them to be treated the same way as #defines (when they could be determined at compile-time, so only true const variables). Observe the kinds of things that you can do with (true) const variables:
Code:
int const num = 5; // A true const variable
int const wrong = get_num(); // A pseudo const variable

// You can use true consts to initialize arrays
char buffer1[num];
char buffer2[wrong]; // Doesn't work (but is legal in C99)

// You can use true consts as template parameters
template <typename T, int N>
class array
{
public:
   T element[N];
};

array<char, num> a1;
array<char, wrong> a2; // Doesn't work

// You can use true consts as switch cases
switch (n)
{
case num:
case wrong: // Doesn't work
}

// You can also use true consts in - or from - template metaprogramming
template <int N>
class factorial
{
public:
   static int const value = N * factorial<N - 1>::value;
};

template <>
class factorial<0>
{
public:
    static int const value = 1;
};

int const num_factorial = factorial<num>::value;

// Note that num_factorial is also a true constant, which means you can do:
char buffer[num_factorial];
// Or any of the other true constant tricks

// And there will be no need to do any calculation at run-time,
// or to allocate any memory space in RAM for any of the const variables.

Basically, true consts replace #defines completely.

So they have all the benefits of #defines and no new drawbacks - as they were designed to. But do they have any new benefits?

Yes.

They include type information - #defines do not:
Code:
#define NUM 123456
int const num = 123456;

void foo(int);
void foo(long);

foo(NUM); // Which foo() does this call?
foo(num); // Obviously foo(int)


They are compiler-level entities, not preprocessor-level. That means that your debugger - which gets symbolic information from the compiler, not the preprocessor - can give you more information about const variables than #defines.

They obey the language rules (because they are part of the C++ language, whereas #defines are part of the separate preprocessor language). In particular, scoping:
Code:
// Global variables (or class members)
int one = 1;
int two = 2;

void foo()
{
   // For some reason, this function requires everything to be increased by 1
   #define one 2;
   int const two = 3;
   
   cout << one; // Prints 2
   cout << two; // Prints 3
}

// ... hundreds of lines of code

void bar()
{
   int a = one;
   int b = two;
   
   cout << a; // Prints 2 (!)
   cout << b; // Prints 2
}

See how the subtle bug was introduced?

See the C++ FAQ Lite for more information. The newbie section talks about const versus #define.

darth_revan wrote:
ABS was just for types like int, float etc. You can use a temp to speed up if you use it for functions.

Uh huh? ^_^ You see, you didn't say that before. And that's the problem. Macros do not behave like the rest of the language, which means that you can be surprised. And in programming, surprises == bugs.

You think you've got it covered now? Well, alright. So ABS() is good for built-in types only, and no functions. Ok, gotcha. i'll use it for an integer, and i won't use a function.
Code:
ABS(i++)

Oops.

Once again, the inline template version does the right thing, as you'd expect. And once again, the macro is broken. The inline template function works everywhere the function macro does, and many places that it does not.

The moral is unchanged. Do not use function macros in C++. Use inline (template) functions.

darth_revan wrote:
Define is good, as long as you know how to use it

No.

Do not ever use #defines to create constants in C++. Ever. That usage is unnecessary and buggy. Don't ever do it. Even in C, use enums instead of #defines. Above i gave you an example of a case when using the preprocessor instead of a const value introduced a nasty bug. i can give you dozens more. Do not use #defines to create constants in C++. There is no reason to prefer a #define over a const variable. None.

Here is a short list of tutorials, FAQs, and coding manuals that state that rule:

i challenge you to show me - besides the case of include guards - just one common situation where a macro is better than using one of the C++ mechanisms. Function macros or just pure #define constants, your choice. Show me at least one example where proper modern C++ programming does not work better than the preprocessor methods (or at least as well).
darth_revan
Code:

const int one =1
#define one 2
cout << one;
#ifdef one
#undef one
#endif
cout << one;


this prints 21. And, you shouldn't use define like that.

For example, you are creating a game;
Code:

#define STRENGTH 1
#define DEXTERITY 2
#define INTELLIGENCE 3
#define STATS 3
class character{
//codes..
int stats[STATS]

//in a combat function,
return (damage + stats[STRENGTH]);

no need to undef those, since they are ONLY used about stats. PI is like that too.
#define PI 3.1428 means no harm, since you aren't going to create a variable called PI again.

And, when you are creating a variable inside a function,
Code:

void func(classname cn)
{
classname a;
if(a != cn)
a.variable++;
func(a);
}

This is a recursive function (you can do it easier with a for loop, but its just an example), and every classname member you create, you take a space from the stack memory. It's also taken from ram.

What memory does it use if not RAM?

-- I normally use C, not C++. I've been to Computing Olimpiads, and working only for linux and windows. I use features of C instead of C++, since C++ is much more slower with the features it has. For example, overloading slows my program down. I even use qsort() and take pointers as arrays instead of vectors. And they reccomend me use preprocessors. Being fast is really important for your program in olimpiads, since you always have a time limit like 1 seconds or less, and memory and stack limit. So, they know more than me, i suppose. And it shouldn't be a bad thing to listen to them... --
Indi
darth_revan wrote:
For example, you are creating a game;
Code:

#define STRENGTH 1
#define DEXTERITY 2
#define INTELLIGENCE 3
#define STATS 3
class character{
//codes..
int stats[STATS]

//in a combat function,
return (damage + stats[STRENGTH]);

no need to undef those, since they are ONLY used about stats. PI is like that too.

That is incredibly horrible code >_< Even if you replaced the #defines with other kinds of constants, that's still godawful code. (It's also wrong, by the way, but ignoring that....)

Why on earth would you make an array for that? That makes no sense. Why not:
Code:
class character
{
public:
   class stats_data
   {
   public:
      typedef unsigned int stat_value;
     
      stat_value strength() const { return strength_; }
     
   private:
      stat_value strength_;
   };
   
   stats_data const& stats() const { return stats_; }
   
private:
   stats_data stats_;
};

// Any time you want to do a stats calculation
character player;
// ...
return damage - player.stats().strength();

Not only is that safer and more robust, it's probably going to be faster because it doesn't have the double indirection due to the array access. It also gives the compiler free reign to reorganize the data to increase access speed if necessary. It even allows you, the programmer, to change the order that the stats values appear in the class in order to speed up access, or the types, or whatever, without having to recompile the whole game! >_<

Even in C, if you just used a POD struct, you would still get pretty much all of the benefits, and it would still be faster than the array you did above.

darth_revan wrote:
#define PI 3.1428 means no harm, since you aren't going to create a variable called PI again.

How can you be sure?

i can think up a dozen hypothetical cases where you might. For example, in another header you're defining the weights of points in an algorithm to simulate cloth flapping, or the surface of water. You happily put your point weights in an enum where they won't conflict and name them PA, PB, PC... you can see where this is going.

Then in another header you've made a really kick ass pseudo random number generator that uses an array of probabilites to generate the numbers. You need to store the index of this array that you're going to use to seed the next generation in a constant, so you make it a class constant called PI (probability index).

Now, you write your game and it seems to work fine. Perfectly! Everything's great. Then you decide to add just one more feature....

Adding the feature is no problem, but during adding the feature you decide to do some innocent cleaning up of the file, including improving the comments... and rearranging the order of the header files so they can be precompiled faster.

And... BAM... you have a bug.

Not a compile error! Oh goodness no, that would be too easy. The program compiles fine as always. It runs perfectly as before... except in certain specific situations....

That kind of bug can take weeks to track down in a large program. Or, more realistically, you'll probably ship without catching it.

Now consider if you'd used C++ constants or enums. As soon as you attempted to compile when there was a conflict, the compiler would have errored... and told you specifically what was wrong, too! A ten second fix, and you would be on your way again... and no other bugs would pop up from that in the future.

So, while your team was shipping buggy projects and/or tracking down nasty bugs that seem to show up even when you didn't actually edit any code... the team that does things the proper way finishes quickly and easily, and has no mysterious bugs. Which team would you rather be on?

Or, let's put it another way. Let's consider what has to happen in order for there to be no bugs in your code. In order for a programmer to not accidently duplicate a #defined constant:
  1. Every programmer would have to read the documentation for every header in your project, just to make sure the constant name they are about to use hasn't been used elsewhere. Which also means:
  2. Every programmer would have to document every constant they use immediately - even constants that aren't intended to be used outside of their own code. And on top of this:
  3. All of that would have to be done every time a programmer added or wanted to add a new constant, because someone else might have added a constant since the last time they checked. And if you think that all of that is doable:
  4. All of this would still not guarantee that you won't end up with a conflict or a subtle bug.

Whereas if you had used modern C++ methods (const variables and/or enums), this is what you would have to do:
  1. Nothing. If there is a potential conflict, the compiler will detect it and warn you every time.

Dude, seriously, let go of #defines. It's old technology, from the 60's, that was made obsolete in the 80's. We're now in the 21st century. Let it go.

darth_revan wrote:
And, when you are creating a variable inside a function,
Code:

void func(classname cn)
{
classname a;
if(a != cn)
a.variable++;
func(a);
}

This is a recursive function (you can do it easier with a for loop, but its just an example), and every classname member you create, you take a space from the stack memory. It's also taken from ram.

What memory does it use if not RAM?

Obviously a recursive function has to use RAM. -_- But how many recursive functions do you actually write? Very few i would hope.

Normal functions do not have to use RAM in many cases. In the example function i gave, all parameters and return values can be in registers (this is called the "fastcall" convention), and the temporary can also be a register. The whole function can be run start to finish without a RAM access, allowing it to be parallelized against other functions that do access RAM, VRAM or the hard drive (or anything) while they're waiting.

darth_revan wrote:
-- I normally use C, not C++. I've been to Computing Olimpiads, and working only for linux and windows. I use features of C instead of C++, since C++ is much more slower with the features it has. For example, overloading slows my program down. I even use qsort() and take pointers as arrays instead of vectors. And they reccomend me use preprocessors. Being fast is really important for your program in olimpiads, since you always have a time limit like 1 seconds or less, and memory and stack limit. So, they know more than me, i suppose. And it shouldn't be a bad thing to listen to them... --

First, if you were told that C++ is slower than C, you were lied to. C++ is C (more or less), so if you do the same thing in C++ that you do in C, they will be exactly the same speed. Exactly. If you use additional C++ features that offer more safety and/or ease of programming at the expense of speed, then yes, C++ will be slower. However, if you use other features in C++ that increase the speed, then C++ will be faster. In other words, C++ is not slower or faster than C. But you can write C++ code that is slower or faster than equivalent C code.

Second, even if you're using C only, you should still use enums for constants instead of #defines. (And i believe that C99 has const variables too - borrowed from C++ because they are such a good idea.) Even if you're just using enums instead of #defines, you will still get most of the benefits.

Third, C++ vectors are slower than C arrays... because they have extra features that make them safer, smarter and easier to use. You pay for those extra benefits with just a small speed decrease. But if you actually tried to use C arrays in a way that was as safe, mart and powerful as C++ vectors, your C code would be slower than C++ code that uses vectors.

Four, you shouldn't just listen to people who you think know more than you. Research on your own. Test code to see what's faster. Read up papers and technical journals to see what the real experts are saying. There are a lot of people teaching C and C++ out there - even at some well known terciary educational institutions - that are buffoons. In fact, i have a very low opinion of university and college C and C++ teachers in general. You'll get a better knowledge of C/C++ from the internet, or from Chapters, than you will from most of them.
vm_yap
can i asked this questions? i'm having a hard time with c programming especially with arrays and strings...

[turbo c] [asap sorry]

I was asked to create a program that a user must input his/her full name (first name middle name last name) then output it as (last name, first name middle name)) another problem is if the user has 2 names for last name, first name and middle name..

ex.

input: full name: Wuggy buggy ramos de los santos
output: De los santos, wuggy buggy ramos

any help will do...

oh i'm weak in turbo c so maybe there would be a easy explanation.
Stubru Freak
vm_yap wrote:
can i asked this questions? i'm having a hard time with c programming especially with arrays and strings...

[turbo c] [asap sorry]

I was asked to create a program that a user must input his/her full name (first name middle name last name) then output it as (last name, first name middle name)) another problem is if the user has 2 names for last name, first name and middle name..

ex.

input: full name: Wuggy buggy ramos de los santos
output: De los santos, wuggy buggy ramos

any help will do...

oh i'm weak in turbo c so maybe there would be a easy explanation.


That's very hard or even impossible to do, as you never know what part is the last name and what part is the first name. If you'd get a Chinese name, would you know? Well, English(/Spanish/anything) is like Chinese to C.
vm_yap
i already have a program that i got from another board, but it won't output the middle name... and it does work with output last name, first name (if it is one word name) using for loop and if else statement. but i don't know how to add a middle name and 2 names.. (english name only)

this is partly the program..

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

main()
{

char fullname[50], firstname[30], lastname[30];
int i=0, j=0, flag=0;

clrscr ();
printf("Please type your full name: ");
gets(fullname);

for (i=0,j=0;fullname[i];i++,j++)
{
if(fullname[i]==' ')
{
flag=1;
firstname[j]=NULL;
j=0;
i++;
}

if(flag==0)
firstname[j]=fullname[i];
else
lastname[j]=fullname[i];
}

lastname[j] = NULL;
printf("\nOutput: %s, %s",lastname, firstname);

getch();
}
Indi
vm_yap wrote:
i already have a program that i got from another board, but it won't output the middle name... and it does work with output last name, first name (if it is one word name) using for loop and if else statement. but i don't know how to add a middle name and 2 names.. (english name only)

this is partly the program..

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

main()
{

char fullname[50], firstname[30], lastname[30];
int i=0, j=0, flag=0;

clrscr ();
printf("Please type your full name: ");
gets(fullname);

for (i=0,j=0;fullname[i];i++,j++)
{
if(fullname[i]==' ')
{
flag=1;
firstname[j]=NULL;
j=0;
i++;
}

if(flag==0)
firstname[j]=fullname[i];
else
lastname[j]=fullname[i];
}

lastname[j] = NULL;
printf("\nOutput: %s, %s",lastname, firstname);

getch();
}

This program is atrocious. Sometimes it's better to not try to fix something. Sometimes it's best to shoot it, burn the corpse, bury the remains, walk away, and never speak of it again. Such is the case for this program. It is abhorently awful.

Your best bet is to just ditch that code abortion completely and start from scratch. Don't try to learn from that code. It will only hurt the universe.

First: Must you use C? Or can you use C++?
vm_yap
turbo c only..

i'm not that good inmipulating strings and arrays so I'm having a hard time creating the program..

thanks for any help.
Indi
vm_yap wrote:
turbo c only..

i'm not that good inmipulating strings and arrays so I'm having a hard time creating the program..

thanks for any help.

Is this for school? Or is it for a private tool? Or is it part of an actual project you are going to eventually release?

The reason i ask is because programs for school are mostly for the purpose of showing you understand something - so, for example, if the program is about manipulating strings, then doing things like input properly isn't really important, so you can hack that. Programs written for yourself need to be generally ok, but don't need to be bulletproof. But programs written for the rest of the world need to be pretty tight and error-proof.

The other thing you should do is write up a complete outline of what you want the program to do. That's necessary for all programs (although you technically don't need to actually write it out, normally - you just need to have it in your head). For example, you could write something like this for a program to convert from Celsius to Fahrenheit:
Quote:
First, it should display a message saying what it is and what it does.

Then it should display a message saying that if you want to convert from Celsius to Fahrenheit you should enter f, and if you want to convert from Fahrenheit to Celsius you should enter c, and if you want to quit you should enter q, and then you should get a character for input.

If you get a q, skip to the end.

Then if you didn't get a q, you should ask for the temperature you want to convert, and then you should get a floating point number from input.

If you're converting to Fahrenheit, you should take that number (x) and do: y = x * 9 / 5 + 32. If you're converting to Celsius, you should do: y = (x - 32) * 5 / 9.

Then you should display the result, and go back to the beginning to ask about quitting or making another conversion.
vm_yap
it is something for school. the problem is the subject that i'm taking this for is not C programming but about Operating System.

Actually when i took C programming some years ago they werent able to teach us how to manipulate arrays.

this is how the program should do.

first a user must enter his/her full name (first name, middle name, last name)

then it will output it as (last name, first name middle name)

*note: the program should be able to recognize if the names inputted has one or two or more names

*the program doesn't have to perfect, it just needs to work.

any help will do thanks again
darth_revan
Why not get all the imputs at the same string?

then you'll use an iterator (a char pointer), scanning from the end, to the start. The last name cannot be 2 words, so, save the last word's beginning and ending spaces, then you can easily find whether user has a middle name, or not (try to scan for ' ', if you cut it right).

for example;
Code:

char string[-something-];

getline(string);

char* iterator, char* last;
iterator = string + (strlen(string)*sizeof(char)) -1 //i know that sizeof(char) is 1, but anyway.
while(*iterator == ' ') iterator --; // the string may be "Sid Meier     ". now we have the last letter, for example, for "Sid Meier        ", we have 'r'.
//then, we save the last word.
//you can either malloc for 80 bytes or have a counter like this: -this will slow the program down, while making it greedy about the memory
int j=0;
char*oldspace = iterator;
while(*iterator != ' ') { iterator--; j++; }
iterator = oldspace;
//last word is j long. You may have to cast it to char*. I use C++'s feature, new and delete, instead of malloc and free.
last = malloc(j*sizeof(char));
//we are using oldspace for iterator of last, don't misunderstand.
oldspace = last + j -1;
while(*iterator != ' ') { *oldspace = *iterator; iterator--; }

now you have the last word (probably the last name).
but for last names with more than one word, it's not possible, i think..
Indi
vm_yap wrote:
it is something for school. the problem is the subject that i'm taking this for is not C programming but about Operating System.

Actually when i took C programming some years ago they werent able to teach us how to manipulate arrays.

this is how the program should do.

first a user must enter his/her full name (first name, middle name, last name)

then it will output it as (last name, first name middle name)

*note: the program should be able to recognize if the names inputted has one or two or more names

*the program doesn't have to perfect, it just needs to work.

any help will do thanks again

No problem, but doing it here will just clutter everything up. It doesn't really make sense to have one thread for ALL C and C++ questions. So i've broken it out to another thread here: http://www.frihost.com/forums/vt-64135.html.
darth_revan
Code:
#include <fstream>
#include <iostream>
using namespace std;

int main()
{
   ifstream fin("asd.txt");
   string mahmut;
   fin >> mahmut;
   cout << mahmut;
   getchar();
   return 0;
}


doesn't seem wrong, yes. That code works with gcc (g++ for cpp files) and Dev C++. But it doesn't work with Microsoft Visual C++ 6.0.

Errors:

Quote:
F:\usaco\sdsd.cpp(9) : error C2679: binary '>>' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable conversion)
F:\usaco\sdsd.cpp(10) : error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable conversion)


Are the headers of Visual C++ wrong? Can they possibly be? Or it's just one of those mistakes that microsoft made?
Indi
darth_revan wrote:
Code:
#include <fstream>
#include <iostream>
using namespace std;

int main()
{
   ifstream fin("asd.txt");
   string mahmut;
   fin >> mahmut;
   cout << mahmut;
   getchar();
   return 0;
}


doesn't seem wrong, yes. That code works with gcc (g++ for cpp files) and Dev C++. But it doesn't work with Microsoft Visual C++ 6.0.

Errors:

Quote:
F:\usaco\sdsd.cpp(9) : error C2679: binary '>>' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable conversion)
F:\usaco\sdsd.cpp(10) : error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable conversion)


Are the headers of Visual C++ wrong? Can they possibly be? Or it's just one of those mistakes that microsoft made?

i believe Visual C++ is the one who's right, and you're wrong. You didn't include <string>. This is just from memory, but i believe that operator<<(ostream&, string const&) is defined in <string>, not <ostream> (and the same for the istream operator). At any rate, you should have included both <string> (for string) and <cstdio> for getchar().
darth_revan
what's the difference between those two codes:

Code:
while( !g_fin.eof() )
{
g_fin >> g_string; 
myVector.push_back(g_string);
}

and

Code:
while (getline(g_fin,g_string,'\n'))
{
  myVector.push_back (g_string);
}

?
Indi
darth_revan wrote:
what's the difference between those two codes:

Code:
while( !g_fin.eof() )
{
g_fin >> g_string; 
myVector.push_back(g_string);
}

and

Code:
while (getline(g_fin,g_string,'\n'))
{
  myVector.push_back (g_string);
}

?

There are two differences.

First, there is the stopping condition. The first code will stop if and only if you come to an end of file condition. The second will stop if and only if the input does not fail. These are not necessarily the same case. Neither choice is particularly wise, but the second option is a little bit better. The best option is to use the good() member function, not eof() or operator void*() (which is what the second version uses).

The other difference is that the first version reads whitespace-separated "words", while the second reads "lines". If you have the following file:
Code:
    pi is between   
            3 and 4

The first version will give you the following strings in your vector:
Code:
"pi"
"is"
"between"
"3"
"and"
"4"

The second will give you:
Code:
"    pi is between   "
"            3 and 4"
darth_revan
Hi. I've been studying on USACO (it has good problems). The problem was

Quote:
Palindromes are numbers that read the same forwards as backwards. The number 12321 is a typical palindrome.

Given a number base B (2 <= B <= 20 base 10), print all the integers N (1 <= N <= 300 base 10) such that the square of N is palindromic when expressed in base B; also print the value of that palindromic square. Use the letters 'A', 'B', and so on to represent the digits 10, 11, and so on.

Print both the number and its square in base B.
PROGRAM NAME: palsquare
INPUT FORMAT
A single line with B, the base (specified in base 10).
SAMPLE INPUT (file palsquare.in)

10

OUTPUT FORMAT
Lines with two integers represented in base B. The first integer is the number whose square is palindromic; the second integer is the square itself.
SAMPLE OUTPUT (file palsquare.out)

1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
264 69696


And, my code for doing this was:

Code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;
int TABAN=10;

template < class T >
string toString(const T& arg)
{
   ostringstream out;
   out << arg;

   return(out.str());
}

vector <string> numbers;
vector <string> squares;

void ifPalin(int a)
{
   int b = a*a;
   char temp;
   string c;
   while(b>0)
   {
      temp = (char)(b%TABAN) +48;
      if(temp > 57) temp+=7;
      c += toString( temp );
      b/= TABAN;
   }
   int i=0, j=c.size()-1;
   while(i< j){
      if(c.at(i) != c.at(j))
         return;
      i++; j--;
   }
   squares.push_back(c);
   c.erase(c.begin(), c.end());
   b=a;
   while(b>0)
   {
      temp = (char)(b%TABAN) +48;
      if(temp > 57) temp+=7;
      c += toString( temp );
      b/= TABAN;
   }
   reverse(c.begin(), c.end());
   numbers.push_back( c );
}
int main()
{   
   ifstream fin("palsquare.in");
   fin >> TABAN;
   fin.close();
   for(int start=1; start<=300; start++)
      ifPalin(start);
   vector<string>::iterator iter=numbers.begin();
   vector<string>::iterator iter2=squares.begin();
   ofstream fout("palsquare.out");
   while(iter !=numbers.end())
   {fout << *iter << " " << *iter2 << endl;
    iter++;
    iter2++;
   }
        fout.close();
   return 0;
}


My code works, but i wonder if it could get any better. I'd like to know if there is a better code for this question.
Indi
darth_revan wrote:
Hi. I've been studying on USACO (it has good problems). The problem was

Quote:
Palindromes are numbers that read the same forwards as backwards. The number 12321 is a typical palindrome.

Given a number base B (2 <= B <= 20 base 10), print all the integers N (1 <= N <= 300 base 10) such that the square of N is palindromic when expressed in base B; also print the value of that palindromic square. Use the letters 'A', 'B', and so on to represent the digits 10, 11, and so on.

Print both the number and its square in base B.
PROGRAM NAME: palsquare
INPUT FORMAT
A single line with B, the base (specified in base 10).
SAMPLE INPUT (file palsquare.in)

10

OUTPUT FORMAT
Lines with two integers represented in base B. The first integer is the number whose square is palindromic; the second integer is the square itself.
SAMPLE OUTPUT (file palsquare.out)

1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
264 69696


And, my code for doing this was:

Code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;
int TABAN=10;

template < class T >
string toString(const T& arg)
{
   ostringstream out;
   out << arg;

   return(out.str());
}

vector <string> numbers;
vector <string> squares;

void ifPalin(int a)
{
   int b = a*a;
   char temp;
   string c;
   while(b>0)
   {
      temp = (char)(b%TABAN) +48;
      if(temp > 57) temp+=7;
      c += toString( temp );
      b/= TABAN;
   }
   int i=0, j=c.size()-1;
   while(i< j){
      if(c.at(i) != c.at(j))
         return;
      i++; j--;
   }
   squares.push_back(c);
   c.erase(c.begin(), c.end());
   b=a;
   while(b>0)
   {
      temp = (char)(b%TABAN) +48;
      if(temp > 57) temp+=7;
      c += toString( temp );
      b/= TABAN;
   }
   reverse(c.begin(), c.end());
   numbers.push_back( c );
}
int main()
{   
   ifstream fin("palsquare.in");
   fin >> TABAN;
   fin.close();
   for(int start=1; start<=300; start++)
      ifPalin(start);
   vector<string>::iterator iter=numbers.begin();
   vector<string>::iterator iter2=squares.begin();
   ofstream fout("palsquare.out");
   while(iter !=numbers.end())
   {fout << *iter << " " << *iter2 << endl;
    iter++;
    iter2++;
   }
        fout.close();
   return 0;
}


My code works, but i wonder if it could get any better. I'd like to know if there is a better code for this question.

First, you can completely remove the whole toString() function. It serves no purpose. string::operator+=(char) works.

Next, I notice that you had duplicate code in the "ifPalin" function. The exact same while block is repeated. So, break it out into a function:
Code:
string format_number(unsigned int n, unsigned int base)
{
   string result;
   
   while (n > 0)
   {
      char c = static_cast<char>(n % base) + 48;
      n /= base;
     
      if(c > 57)
         c += 7;
     
      result += c;
   }
   
   return result;
}
Other than breaking it out to a function, using a local variable instead of the global, and using a C++ style cast instead of a C cast, nothing is changed. (Although, if I was writing this function, I would use a do-while loop instead of a while loop, so it works with n = 0 too - not a problem for you because n can never be 0, but eh).

Finally, I edited ifPalin() a bit to remove the calls to toString() (which are unnecessary), and all the other variables and stuff that are unnecessary now that the loops are function calls:
Code:
void ifPalin(int a)
{
   // int b = a*a;
   // char temp;
   string c;
   
   c = format_number(a * a, TABAN);
   
   int i=0, j=c.size()-1;
   while(i< j){
      if(c.at(i) != c.at(j))
         return;
      i++; j--;
   }
   squares.push_back(c);
   //c.erase(c.begin(), c.end());
   //b=a;
   
   c = format_number(a, TABAN);
   
   reverse(c.begin(), c.end());
   numbers.push_back( c );
}

So without actually changing any code at all, I got:
Code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;
int TABAN=10;

vector <string> numbers;
vector <string> squares;

string format_number(unsigned int n, unsigned int base)
{
   string result;
   
   while (n > 0)
   {
      char c = static_cast<char>(n % base) + 48;
      n /= base;
     
      if(c > 57)
         c += 7;
     
      result += c;
   }
   
   return result;
}

void ifPalin(int a)
{
   // int b = a*a;
   // char temp;
   string c;
   
   c = format_number(a * a, TABAN);
   
   int i=0, j=c.size()-1;
   while(i< j){
      if(c.at(i) != c.at(j))
         return;
      i++; j--;
   }
   squares.push_back(c);
   //c.erase(c.begin(), c.end());
   //b=a;
   
   c = format_number(a, TABAN);
   
   reverse(c.begin(), c.end());
   numbers.push_back( c );
}

int main()
{   
   ifstream fin("palsquare.in");
   fin >> TABAN;
   fin.close();
   for(int start=1; start<=300; start++)
      ifPalin(start);
   vector<string>::iterator iter=numbers.begin();
   vector<string>::iterator iter2=squares.begin();
   ofstream fout("palsquare.out");
   while(iter !=numbers.end())
   {fout << *iter << " " << *iter2 << endl;
    iter++;
    iter2++;
   }
        fout.close();
   return 0;
}

Some further trims are possible (for example, both of the calls to close() in main() are unnecessary, although the first is at least debatable - and I didn't even remove unnecessary headers), but for any more significant improvements, you're gonna have to start making some real structural changes. Continue?
Related topics
Reply to topic    Frihost Forum Index -> Scripting -> Others

FRIHOST HOME | FAQ | TOS | ABOUT US | CONTACT US | SITE MAP
© 2005-2011 Frihost, forums powered by phpBB.