1 2 3 4 5 6 7 8
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Bisqwit wrote:
Bisqwit wrote:
not the solution handed on a silver platter…
But I can go with the old-fashioned [spоiler] tag. #include <stdio.h> int main() {   int a=0, len=5+2+5+1;   static const char str[] = "Hello, world ";   for(;; a=(a+1)%len) printf("%.*s%.*s\n", len-a%len, str+a%len, a%len, str); }
Bleh, evil magic numbers, don't bother defining len, and use sizeof(str) instead.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Editor, Active player (296)
Joined: 3/8/2004
Posts: 7469
Location: Arzareth
Nach wrote:
Bleh, evil magic numbers, don't bother defining len, and use sizeof(str) instead.
I did that because this is C, not C++ -- "const int x = <expression>;" is not a constant in C as it is in C++, and I opted to do this instead of using #define. Also, I'm not fond of (sizeof(x)-1) -- the nul terminator there is a trap.
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Bisqwit wrote:
Nach wrote:
Bleh, evil magic numbers, don't bother defining len, and use sizeof(str) instead.
I did that because this is C, not C++ -- "const int x = <expression>;" is not a constant in C as it is in C++, and I opted to do this instead of using #define. Also, I'm not fond of (sizeof(x)-1) -- the nul terminator there is a trap.
If you must declare len, at the very least use sizeof(str), as opposed to magic numbers. What you did is pure evil, and should be avoided. You should make your code least prone to errors when something changes. If he decided to change the text to "Hi, my name is Sally!", he'd have to completely redo the len with your definition.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Joined: 11/26/2005
Posts: 285
Bisqwit wrote:
Consider what happens to the loop terminating condition "p < LTH" when you execute "p = -n;". When do you suppose the loop ends? The simplest solution for making this _work_ involves the modulo operator, but I'm providing thought fodder here, not the solution handed on a silver platter…
I'll take a look at this; thanks. I don't know if I can use your example, because eyeing over it it seems a bit difficult for my level. Maybe it isn't, I'll see.
Banned User, Former player
Joined: 3/10/2004
Posts: 7698
Location: Finland
My (perhaps slightly obfuscated) solution to the problem. It doesn't need the modulo operator nor sizeof (or strlen). Assumes C99 (although making it C89-compatible is completely trivial). #include <stdio.h> int main(void) {   const char* str = "Hello, World! ";   const char* startPtr = str;   for(int i = 0; i < 30; ++i)   {     const char* curPtr = startPtr;     do     {       printf("%c", *curPtr);       if(!*++curPtr) curPtr = str;     } while(curPtr != startPtr);     printf("\n");     if(!*++startPtr) startPtr = str;   }   return 0; }
Joined: 11/26/2005
Posts: 285
Well, looks like I've gotten into a problem too difficult for me. I should start working on pointers instead, and I can pick this up later (by the end of summer, perhaps?). Also, I must stop posting so much in this thread. By the way, Warp: is
for(int i = 0;;)
even legal C?
Player (36)
Joined: 9/11/2004
Posts: 2623
Of course it is, you need two semicolons inside the parenthesis, Warp is simply declaring an initial value using the loop initialization argument, leaving the test empty so it loops until break, and then leaving the update argument empty as well. All of the following are legal C (assuming that the variables are defined):
for (;;) {
for (int i=0;;) {
for (;var!=2.3;) {
for (;;i++) {
Not to mention, an empty statement is completely legal which means that the following is valid, but useless code:
void main() {
  ;;;;;;;;;;;;;;;;return;
}
Build a man a fire, warm him for a day, Set a man on fire, warm him for the rest of his life.
Joined: 10/3/2005
Posts: 1332
Swedishmartin wrote:
Well, looks like I've gotten into a problem too difficult for me. I should start working on pointers instead, and I can pick this up later (by the end of summer, perhaps?). Also, I must stop posting so much in this thread. By the way, Warp: is
for(int i = 0;;)
even legal C?
It is in c99, but not in earlier standards. I think this is what Warp was alluding to...
Warp wrote:
(although making it C89-compatible is completely trivial).
Editor, Active player (296)
Joined: 3/8/2004
Posts: 7469
Location: Arzareth
Swedishmartin wrote:
I should start working on pointers instead
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node { struct node *left, *right; int key; char payload; } node;
static void AddNode(node** tree, node* newnode)
{
    if(*tree == NULL)                    { *tree = newnode; }
    else if(newnode->key > (*tree)->key) { AddNode( &(*tree)->right, newnode); }
    else                                 { AddNode( &(*tree)->left, newnode); }
}
static void Populate(node** tree)
{
    static const char msg[] = "lol, Herd!low\n";
    static const char order[sizeof(msg)-1] = {3,4,2,5,6,0,1,9,11,12,10,8,7,13};
    const char* p;
    for(p=msg; *p != '\0'; ++p)
    {
        node* n = (node*) malloc(sizeof(*n));
        n->payload = *p;
        n->left = n->right = NULL;
        n->key  = order[p-msg];
        AddNode(tree, n);
    }
}
static void Walk(node* tree, void(*visitor)(node*), void(*disposer)(node*))
{
    if(tree == NULL) return;
    Walk(tree->left, visitor, disposer);
    if(visitor != NULL) visitor(tree); /* In the between of "left" and "right" for in-order walk-through */
    Walk(tree->right, visitor, disposer);
    if(disposer != NULL) disposer(tree); /* After "left" and "right" for when-disposable-order walk-through */
}
static void dumper(node* node)   { putchar(node->payload); }
static void disposer(node* node) { free(node); }
int main()
{
    node* tree = NULL;
    Populate(&tree);
    Walk(tree, dumper, NULL);  /* These two calls could be merged */
    Walk(tree,   NULL, disposer);
    return 0;
}
Thoughtfodder. This example code is designed to maximize the density of pointer use in a small (one page) example program while still being meaningful and not just complex for the sake of being complex. (That is, I could have also made the payload a pointer, but decided not to.)
Banned User, Former player
Joined: 3/10/2004
Posts: 7698
Location: Finland
Bisqwit wrote:
Swedishmartin wrote:
This example code is designed to maximize the density of pointer use
I think it's also a good example of how obfuscated and hard to follow C quickly becomes with complex data containers. Not to talk about how easily it becomes unsafe (with unexpected memory leaks, accessing freed memory or out-of-bounds accesses). C doesn't offer many tools for encapsulation, modularity or safety.
Joined: 11/26/2005
Posts: 285
Bisqwit wrote:
static void AddNode(node** tree, node* newnode) //tree is a double pointer which makes it twice as good
Is this how it works?
Joined: 11/26/2005
Posts: 285
Project Euler, challenge two. I'm stuck.
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Find the sum of all the even-valued terms in the sequence which do not exceed four million.
#include <stdio.h>

int main()
{
	int add = 0;
	int a, b = 1;
	int c;

	for(; b < 4000000; )
	{
		c = b;
		b += a;
		a = c;

		if((b % 2) == 0)
		 add += b;
	}

	printf("%i", add);
	return 0;
}
It prints 0, and I don't know why.
Tub
Joined: 6/25/2005
Posts: 1377
int a, b = 1
this sets b to 1 and leaves a uninitialized. You want:
int a=1, b=1
hint: in such cases, it's often useful to use a debugger that allows you to view variable contents, or to sprinkle some printf's inside your program so you can see how the loop progresses.
m00
Banned User, Former player
Joined: 3/10/2004
Posts: 7698
Location: Finland
I haven't looked at the code with much thought, but at least you are using the variable 'a' uninitialized the first time the loop is executed. The behavior is thus undefined.
Joined: 11/26/2005
Posts: 285
I thought that a, b = 1 assigns 1 to both a and b. Well, that explains it. Thanks.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Warp wrote:
Bisqwit wrote:
This example code is designed to maximize the density of pointer use
I think it's also a good example of how obfuscated and hard to follow C quickly becomes with complex data containers.
since the bisqwit algorithm use some recursion function..(ouch my head!!) I doubt there language that would be easier either for the current problem.
Joined: 4/7/2008
Posts: 117
Clojure? And C++ is almost always a better choice.
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
OmnipotentEntity wrote:
void main() {
  ;;;;;;;;;;;;;;;;return;
}
That is not valid C89/C99/C++. main must return an int.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Joined: 3/11/2008
Posts: 583
Location: USA
Nach wrote:
OmnipotentEntity wrote:
void main() {
  ;;;;;;;;;;;;;;;;return;
}
That is not valid C89/C99/C++. main must return an int.
I'd've sworn otherwise, I rather habitually void main for trivial programs. edit: I suppose it's probably not standards-compliant though.
Joined: 11/1/2007
Posts: 100
eternaljwh wrote:
Nach wrote:
OmnipotentEntity wrote:
void main() {
  ;;;;;;;;;;;;;;;;return;
}
That is not valid C89/C99/C++. main must return an int.
I'd've sworn otherwise, I rather habitually void main for trivial programs. edit: I suppose it's probably not standards-compliant though.
Current standards for both C and C++ both explicitly state that main() must be int, although most compilers will only warn if main() is some other type. The reasoning is that the caller expects an int to be returned that it can interpret as an error code. EDIT: Here's something to ponder: http://homepages.tesco.net/J.deBoynePollard/FGA/legality-of-void-main.html
Joined: 11/26/2005
Posts: 285
I'm working on learning C and all is well, I just felt like sharing this:
#include <stdio.h>

int main()
{
	int n, x, y;

	for(n = 1; n <= 15; n++)
	{
		for(y = 0; y <= 15; y++) //y coord, row
		{
			for(x = 0; x <= 15; x++) //x coord, cell
				if ((x ^ y) < n)
					printf("X");
				else
					printf(" ");
			printf("\n");
		}

		printf("\n%i\n\n", n);
	}

	return 0;
}
Munching squares! It feels nice to make something simple that still looks a bit complicated; makes you feel smart.
Joined: 4/7/2008
Posts: 117
Just remember in real code, nobody likes obfuscated programming. :P
Joined: 11/26/2005
Posts: 285
I meant that the program output looks complicated, I tried to make the code itself as simple as possible. The algorithm is really simple as well: (Wolfram MathWorld)
A plot of the cells on a grid satisfying bitwise XOR(a,b)<n for consecutive values of n=1, 2, ....
Joined: 3/7/2006
Posts: 720
Location: UK
He was probably just talking about the variable names. This is a pretty simple algorithm so x, y and n suffice.
Voted NO for NO reason
Joined: 4/7/2008
Posts: 117
While those are good tips, I just meant be careful as you go on that clean, elegant, readable code are much more important that trying to do strange one liners. I'm not accusing you of doing any of those above, just a free floating tip.
1 2 3 4 5 6 7 8