|
#136
|
|
|
|
|
> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
>> arnuld wrote: > Lots of people /would/ write it like that. In *my* code, I consider an > "early return" like that to be a bug that I should fix, because in *my* > code I want every function and every loop to have *one* entry point and > *one* exit point. I find that this makes my programs much easier to read > and thus to maintain. Will not that make the program less efficient as program has to go till it finds the return ? >> **pw = calloc( arr_size, sizeof **pw ); > Surely you mean *pw = calloc( arr_size, sizeof **pw ); you say that calloc() will automatically return a pointer to pointer ? > Oh, by the way - I don't see the bit where you point the array's > elements to words. Why isn't get_words calling get_single_word? because I did not wrote it yet ;) . I wanted to remove some confusions first and then proceed ahead. |
|
|
|
#137
|
|
|
|
|
arnuld said:
>> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote: > >>> arnuld wrote: > >> Lots of people /would/ write it like that. In *my* code, I consider an >> "early return" like that to be a bug that I should fix, because in *my* >> code I want every function and every loop to have *one* entry point and >> *one* exit point. I find that this makes my programs much easier to read >> and thus to maintain. > > Will not that make the program less efficient as program has to go till > it finds the return ? Only if the compiler is really brain-damaged. Let's say the code is: if(ptr != NULL) /* A */ { /* lots of code, translating to 500 bytes of assembly instructions */ } return ptr; /* B */ The compiler will do something like this: CMP ptr, 0 JE _B (500 bytes of assembly instructions here) _B: MOV RR, ptr On the second pass, JE _B will be translated into a jump to a specific (relocatable) address, and the jump will consist simply of changing the instruction pointer to have that new value. The program doesn't have to "go till it finds the return" - it simply has to assign a new value to the instruction pointer, and it doesn't give tuppence whether that value is close to the value it had before or not. >>> **pw = calloc( arr_size, sizeof **pw ); > >> Surely you mean *pw = calloc( arr_size, sizeof **pw ); >> you say that calloc() will automatically return a pointer to pointer ? No, calloc returns void * - and I don't see the relevance of your question to the point I made. |
|
#138
|
|
|
|
|
> On Thu, 18 Sep 2008 11:16:13 +0000, Richard Heathfield wrote:
> Only if the compiler is really brain-damaged. > > Let's say the code is: > > if(ptr != NULL) /* A */ > { > /* lots of code, translating to 500 bytes of assembly instructions */ > } > > return ptr; /* B */ > > The compiler will do something like this: > > CMP ptr, 0 > JE _B > (500 bytes of assembly instructions here) > _B: > MOV RR, ptr hey.. thats assembly :) > On the second pass, JE _B will be translated into a jump to a specific > (relocatable) address, and the jump will consist simply of changing the > instruction pointer to have that new value. The program doesn't have to > "go till it finds the return" - it simply has to assign a new value to the > instruction pointer, and it doesn't give tuppence whether that value is > close to the value it had before or not. Nobody taught me that way on comp.lang.c++. Seems like C is very closer to assembly language. > No, calloc returns void * - and I don't see the relevance of your > question to the point I made. I quoted the wrong code. See this code: char*** pw; *pw = calloc( arr_size, sizeof **pw ); *pw means pointer to pointer. I want to dynamically allocate an array of pointers. but calloc() gives void* in return not void**. So how can I dynamically allocate an array of pointers. The array elements (pointers) will point to words ,which again are pointers. This is going to be base for get_words function, which will be passed the address of a pointer to pointer, making the 3 levels of indirection coming into the picture. |
|
#139
|
|
|
|
|
arnuld said:
>> > hey.. thats assembly :) When we're talking about efficiency (and it was you who raised the subject), the language definition is no longer adequate, because it doesn't have anything to say about efficiency, so we have to look at typical characteristics of implementations, knowing that what we say is no longer universally true. Note that the assembly language above was only mildly modelled on real assembly languages, and probably won't do you much good if you try to insert it into your own program. >> On the second pass, JE _B will be translated into a jump to a specific >> (relocatable) address, and the jump will consist simply of changing the >> instruction pointer to have that new value. The program doesn't have to >> "go till it finds the return" - it simply has to assign a new value to >> the instruction pointer, and it doesn't give tuppence whether that value >> is close to the value it had before or not. > > Nobody taught me that way on comp.lang.c++. Well, nobody would have taught you that way on comp.lang.c either, except that you raised the subject of efficiency and suggested that a particular style is inefficient. To demonstrate that it isn't could not be done from within the context of the language itself. > Seems like C is very closer to assembly language. Yes, except that there really isn't any such thing as "assembly language" - rather, there are many different assembly languages. > char*** pw; > *pw = calloc( arr_size, sizeof **pw ); >> *pw means pointer to pointer. I want to dynamically allocate an array of > pointers. but calloc() gives void* in return not void**. Right. (So do malloc and realloc.) Why would you need void **? > So how can > I dynamically allocate an array of pointers. T **p; p = malloc(n * sizeof *p); if(p != NULL) { p[0] through p[n - 1] are now pointers to T, with indeterminate values If you are passing p via a function parameter, you will need an additional level of indirection, so take it as T ***p and do: *p = malloc(n * sizeof **p); if(*p != NULL) { (*p)[0] through (*p)[n - 1] are now pointers to T... |
|
#140
|
|
|
|
|
> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
> ...SNIP.. > Surely you mean *pw = calloc( arr_size, sizeof **pw ); > > Oh, by the way - I don't see the bit where you point the array's elements > to words. Why isn't get_words calling get_single_word? Okay here is my new code: #include <stdio.h> #include <stdlib.h> #include <ctype.h> enum { WORD_SIZE = 28, ARRSIZE = 10 }; enum { GSW_OK, GSW_ENOMEM, GSW_ENORESIZE } ; enum { GW_OK, GW_ENOMEM, GW_ENORESIZE }; int get_words( char***, size_t* ); int get_single_word( char** ); int main( void ) { char** pword; /* pw means pointer to word */ size_t word_count; int num; pword = NULL; word_count = 0; num = get_words( &pword, &word_count ); printf("words = %d, num = %d\n", (int) word_count, num); free(pword); return 0; } int get_words( char*** pw, size_t* cnt ) { size_t idx; int mem_check; char **pw_begin, **new_mem; char* pword; size_t arr_size; arr_size = ARRSIZE; mem_check = GW_ENOMEM; *pw = calloc( arr_size, sizeof **pw ); pw_begin = *pw; if( *pw ) { mem_check = GW_OK; pw_begin = *pw; for( idx = 0; (! get_single_word( &pword )) && *pword; ++idx ) { if( idx == arr_size ) { new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem)); if( new_mem ) { pw_begin = new_mem; } else { mem_check = GW_ENORESIZE; } } if( GSW_OK == mem_check ) { pw_begin++ = &pword; } } pw_begin = NULL; } *cnt = idx; return mem_check; } int get_single_word( char** pc ) { int mem_check; unsigned idx; int ch; size_t curr_size; char *new_mem; char *pc_begin; mem_check = GSW_ENOMEM; /* will updat eit on first use */ curr_size = WORD_SIZE; *pc = calloc(curr_size, sizeof(**pc)); if( (! *pc) ) { mem_check = GSW_ENOMEM; return mem_check; } else { mem_check = GSW_OK; pc_begin = *pc; } while( (ch = getchar()) && (isspace( (unsigned char) ch)) ) { continue; /* skip leading white space */ } if( EOF != ch ) { *pc_begin++ = ch; } while( (GSW_OK == mem_check) && ((ch = getchar()) != EOF) && (! isspace( (unsigned char) ch)) ) { if( idx == curr_size ) { new_mem = realloc( pc_begin, (2 * curr_size * sizeof(*new_mem))); if( new_mem ) { pc_begin = new_mem; curr_size *= 2; } else { mem_check = GSW_ENORESIZE; /* error, couldn't not enlarge */ *pc_begin = '\0'; return mem_check; } } if( GSW_OK == mem_check ) { *pc_begin++ = ch; } } *pc_begin = '\0'; return mem_check; } ======================= OUTPUT ======================== [arnuld@dune ztest]$ gcc -ansi -pedantic -Wall -Wextra sort-input.c sort-input.c: In function `get_words': sort-input.c:79: error: invalid lvalue in assignment [arnuld@dune ztest]$ Line 79: pw_begin++ = &pword; I don't understand why I am getting this error. |
|
#141
|
|
|
|
|
arnuld said:
<snip> > Line 79: pw_begin++ = &pword; > > I don't understand why I am getting this error. The assignment operator requires a modifiable lvalue as its left operand. The ++ operator yields a value as its result. The above is equivalent in spirit to a statement such as: 6 = &pword; which simply makes no sense. The implementation is obliged to diagnose this, and has done so. What you meant to write is: *pw_begin++ = pword; This is legal because * has higher precedence than = so what happens is that ++ yields the old value of pw_begin, * gives us the object to which that old value points, and = now assigns to the object. Since pw_begin has type char **, pw_begin++ has type char **, *pw_begin++ has type char * and is a real object, so we can assign a char * value to it. pword is one such value. |
|
#142
|
|
|
|
|
arnuld wrote:
.... >> *pc = calloc(cursize, sizeof **pc); >> if(*pc != NULL) >> { .... > This whole program is based on that condition of *pc != NULL. Why don't > we put a line like, *pc == NULL and then return from the program with the > ENOMEM value right there ? If you return from the program, the fact that errno contains ENOMEM has no further significance. |
|
#143
|
|
|
|
|
Richard Heathfield wrote:
.... > The compiler will do something like this: > > CMP ptr, 0 > JE _B > (500 bytes of assembly instructions here) > _B: > MOV RR, ptr > > On the second pass, JE _B will be translated into a jump to a specific > (relocatable) address, and the jump will consist simply of changing the > instruction pointer to have that new value. The program doesn't have to > "go till it finds the return" - it simply has to assign a new value to the > instruction pointer, and it doesn't give tuppence whether that value is > close to the value it had before or not. It depends upon the assembly language; I've written assembly in languages where a short jump used a faster instruction than a long jump. However, it was only a little bit faster; not enough to justify worrying about in C code. |
|
#144
|
|
|
|
|
Richard Heathfield wrote:
> arnuld said: .... >> My meaning of academic means, "being not practical" . In Indian computer >> education system, clrscr() is the function that belongs to a language >> named TURBO C, which is better than C. > > I've never heard such baloney. C is a language. Turbo C is an ancient > implementation, no longer supported, which runs on only one tiny class of > platforms. > >> There is *only* one good C and that is TURBO C. > > Try telling that to the OS390 guys. I would imagine, since he prefaced his statement with "In Indian computer education system ...", that this would imply that the specified system doesn't have any OS390 guys. He wasn't making a more general statement. The wording of his statement leaves open the possibility that there are implementations of C which are better than the ones he listed, they just don't happen to be available in that system. If this is the case, he has my sympathy - I thought the Indians were more advanced than that. However, India is a huge place, and I doubt that arnuld has seen the entire "Indian computer education system". I suspect that he's describing the attitude of one particular piece (of unknown size) of that system. However, his description of that piece of the system might be perfectly accurate. |
|
#145
|
|
|
|
|
arnuld <sunrise> writes:
>> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote: <snip> > Okay here is my new code: A few comments. [..] > *pw = calloc( arr_size, sizeof **pw ); > pw_begin = *pw; > > if( *pw ) > { > mem_check = GW_OK; > pw_begin = *pw; >> for( idx = 0; (! get_single_word( &pword )) && *pword; ++idx ) I find this counter-intuitive. I had to go check what get_single_word returns for success (GSW_OK) and then go check that this was indeed zero so ! of it was true. I'd write > for( idx = 0; get_single_word( &pword ) == GSW_OK; ++idx ) and try hard to make sure that there is no need for the extra check on *pword. I have not checked if you need it. > { > if( idx == arr_size ) > { > new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem)); > > if( new_mem ) > { > pw_begin = new_mem; Surely not? The next words has to go after the existing ones in the new memory not at the start. > } > else > { > mem_check = GW_ENORESIZE; > } > } > > if( GSW_OK == mem_check ) This looks wrong. You set mem_check only once and that is to GW_OK. Now GW_OK == GSW_OK (probably) but why test it anyway since we are in an the if where it was set? I.e. you get to this test unless mem_check is GW_OK. > { > pw_begin++ = &pword; > } > } I find this a gruesome waste of space, but that is only style! You go with what feels right. [..] > } > else > { > mem_check = GSW_OK; > pc_begin = *pc; > } >> > while( (ch = getchar()) && (isspace( (unsigned char) ch)) ) Ah! The cast is wrong here. Not just unneeded, but wrong. I'll gladly say why but I think you get way more out of it if you can work out why for yourself. It won't actually fail o any system that I can recall but it is, technically, not portable. > { > continue; /* skip leading white space */ > } >> if( EOF != ch ) > { > *pc_begin++ = ch; > } > > while( (GSW_OK == mem_check) && > ((ch = getchar()) != EOF) && > (! isspace( (unsigned char) ch)) ) And here it is unneeded but can't, even theoretically, cause a problem. > { > if( idx == curr_size ) > { > new_mem = realloc( pc_begin, (2 * curr_size * sizeof(*new_mem))); > > if( new_mem ) > { > pc_begin = new_mem; Again, is this right? New characters need to go after the ones that are there already. [..] |
|
#146
|
|
|
|
|
arnuld <sunrise> writes:
>> On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote: [...] >>> **pw = calloc( arr_size, sizeof **pw ); > >> Surely you mean *pw = calloc( arr_size, sizeof **pw ); >> you say that calloc() will automatically return a pointer to pointer ? [...] No, calloc() returns a void*. The assignment implicitly converts that void* result to the type of the left side; in this case, whatever type *pw has. |
|
#147
|
|
|
|
|
> On Thu, 18 Sep 2008 13:41:08 +0000, James Kuyper wrote:
> I thought the Indians were more advanced than that. You are wrong. Most Indian students say that you need Windows to run a computer, without Windows you can not use a computer. I have yet to meet a person who uses Linux as his daily use OS. > However, India is a huge place, and I doubt that arnuld has seen the > entire "Indian computer education system". I suspect that he's > describing the attitude of one particular piece (of unknown size) of > that system. I am graduated from "Panjab University", one of the top 4 most respected universities in India. You can think about what rest of will be like. 2nd, other than these top 4, most do not eve have proper working hardware available to them. Most shocking fact is that you won't find a computer teachers, even if you find institute. Only *a few* are good, hear of IIT, Indian Institute of Technology, a supreme quality Engg. College with 5 or 8 branches all over India. It is the only institute which gives quality education. I met a programmer, 2 years ago, he asked me what I am doing at that time. I said I was reading Haskell, he had first devision in his Computer Science Engg. degree and was earning 20,000 rupees a month. He asked me "What is Husk... a..all.... some sort of Fictional Novel ? ".... :-\ |
|
#148
|
|
|
|
|
arnuld wrote:
> > On Thu, 18 Sep 2008 09:04:49 +0000, Richard Heathfield wrote: > > > I've never heard such baloney. C is a language. Turbo C is an > > ancient implementation, no longer supported, which runs on only one > > tiny class of platforms. > > I did not know that TURBO C is an ancient compiler. As of 2008, the > Indian Computer Education system still rely on TURBO C compiler. That's because it's free. Brian |
|
#149
|
|
|
|
|
Andrew Poelstra wrote:
> On 2008-09-17, arnuld <sunrise> wrote: > > > > My meaning of academic means, "being not practical" . In Indian > > computer education system, clrscr() is the function that belongs to > > a language named TURBO C, which is better than C. There is only one > > good C and that is TURBO C. Same for VC++ which, of course , is > > much better than C++. Microsoft has created a better language than > > C. > > > > Well, TURBO C is not C, and VC++ is not C++. Microsoft should not have > named their products so similarly to those real languages. Then you should the same complaint about gcc and almost every other C implementation. Almost all offer some sort of extensions. Turbo C contained a nearly conforming C89 compiler. I believe I've heard that there were a few bugs, but I don't recall what they were. The manual had a portability statement for every library function included that specified whether it was ANSI C, UNIX, or platform-specific. Oh, and Turbo C was Borland, not Microsoft. Brian |
|
#150
|
|
|
|
|
Richard Heathfield wrote:
> arnuld said: > > This whole program is based on that condition of *pc != NULL. Why > > don't we put a line like, *pc == NULL and then return from the > > program with the ENOMEM value right there ? > > Lots of people would write it like that. In my code, I consider an > "early return" like that to be a bug that I should fix, because in my > code I want every function and every loop to have one entry point and > one exit point. I find that this makes my programs much easier to > read and thus to maintain. Our company coding standard now allows early return for initial parameter checking. In the old days, the usual method was something like: int func(int a, int b) { returnval = 0; if (a > 10) { returnval = -1; } else if (b > 20) { returnval = -2; } if (returnval == 0) { /* do the real work and set returnval appropriately */ } return returnval; } Now you can do: int func(int a, int b) { returnval = 0; if (a > 10) { return -1; } if (b > 20) { return -2; } /* do the real work and set returnval appropriately */ return returnval; } I don't know if it's better, worse, or just differently-abled. Brian |
|
|
|
|
| Similar Threads | |
| Best way to input from stdin? I'm writing a program that supports input from stdin. To be able to do that I tend to rely on a simple loop that tests the return of fgets(), such as the following... |
|
| How to accept input from stdin? Hi, I try to make a wrapper around an existing program, which would behave exactly the same as the original one. But my following attempt was failed. Would you pleaes let me... |
|
| Input using stdin How can I give input to a program using STDIN Suppose I want the program to take the value x=10 On some other site i found it as STDIN.read,but its not working. |
|
| getting input from stdin Hi Im new to unix scripting and now Im trying to get user input from stdin and this is what I did echo "enter your name: " read name and it will run with the pointer to... |
|
| Checking available input on stdin I know this has probably come up frequently, but couldn't find a satisfactory reference... I have some code which needs to read from stdin but must not block waiting for... |
|
|
All times are GMT. The time now is 06:08 AM. | Privacy Policy
|