Code is my geek porn.
LordoftheMonkeys
Veteran
Joined: 15 Aug 2009
Age: 35
Gender: Male
Posts: 927
Location: A deep,dark hole in the ground
I am turned on by code. Especially if it's my own. I mean, just look at this work of art:
#include <stdlib.h>
#include "filestext.h"
int main( int argc, char *argv[] ){
int numOfLines;
FILE *fp;
fp = fopen( argv[1], "r" );
numOfLines = getNumOfLines( fp );
printf( "Lines: %d\n", numOfLines );
int *chars = numsOfChars( fp );
for( int i = 0; i < numOfLines; i++ ){
printf ( "Line %d: %d\n", i, chars[i] );
}
fclose( fp );
return 0;
}
int *numsOfChars( FILE *fp ){
int numLines = getNumOfLines( fp );
int *lines = (int *) malloc( sizeof(int) );
char ch;
for( int j = 0; j < numLines; j++ ){
lines[j] = 0;
while( (ch = fgetc( fp )) != '\n' ){
lines[j]++;
}
}
rewind( fp );
return lines;
}
int getNumOfLines( FILE *fp ){
int lines = 0;
char ch;
while( (ch = fgetc( fp )) != EOF ){
if( ch == '\n' )
lines++;.
}
rewind( fp );
return lines;
}
It is beautifully complex, yet elegant at the same time, wonderfully confusing to someone unfamiliar with C/C++, which makes me feel special for understanding it. I have utilized both file access functions and dynamic memory management to create these functions, and they work perfectly. I'm planning to use them for the text editor I'm building, and maybe my own RDBMS.
I find myself just sitting and staring at it, my pupils dilating and my gaze transfixed. It excites me in an erotic way. Erotic and mystic indeed is the process of writing the beautiful, mathematically perfect poetry that gives me ultimate control over the computer, then trudging through the gruesome battlefield commonly known as the debugging phase, and finally vanquishing the bug army and emerging gloriously with something that actually works... works and has great potential.
And it's mine. All mine.
I am in awe at my own handiwork. I wonder - am I an artistic genius, or a shameless narcissist?
My game is 21596 lines of messy code like this.
{
if ((Person[PN].gaveupstatus==GAVEUP_NOT && (Person[PN].health+damage)!=1) &&
(LIMIT_NONLETHAL_COMBAT_TO_PLAYER_ONLY==FALSE || PN==0) //if the flag is set, only player can give up
)
{
Person[PN].health=1; //giving him last chance
if (IsHumanoid(source)!=0 && IsHumanoid(PN)!=0)
if (GETFACTIONRELATION(GetPersonStat(source,"faction"),GetPersonStat(PN,"faction"))!=HOSTILE)
{
PersonGiveUp(PN,source);
PersonStopShooting(source); //preventing chaingun death from killing the guy
}
} else
{
strcpy(msg,Person[PN].base.name);
if (Person[PN].health<=-25) strcat(msg," dies violently, killed by "); else strcat(msg," dies, killed by ");
if (source>0) strcat(msg, Person[source].base.name);
else
if (source==0) strcat(msg,"you");
else
strcat(msg,"environment");
strcat(msg,".");
Textbox_Output(msg,TEXTBOXCOLOR,Person[PN].x,Person[PN].y);
KillPerson(source,PN); //KillPerson makes its own animation and kill noise
}
}
I'm afraid not. Your use of malloc is utterly wrong. Depending on the environment (particular runtime, process instance, OS), your code will result in various failure modes.
Your program also has a problem, should there be no parameter or a parameter that is not the path to of an existing, readable file. Extra paramters are ignored... not a bug, but still silly.
I have no idea why you have made the design decision to print the number of lines before the individual line counts. That forces you to either read the file twice, or set aside memory to store ALL the line counts. You don't do the former (as you actually read the whole file THREE times), and try, but fail, to do the latter (which is essentially impossible, anyway, and then you ignore the error return from malloc)
You also do not zero out the allocated malloc space - although many implementations will do this for you - which is to my mind entirely wrong. You should use calloc.
You appear to have skipped this.
I'd suggest that you turn on all the warnings in your compiler. It will point out many of the other flaws in your code. I always let the compiler do all the leg-work for me. It will point out your misuse of EOF, for instance.
(Also, most editors tend to agree on calling the first line in a file "line 1". I.e. line numbers, when intended for human consumption, usually are show starting at one.)
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
LordoftheMonkeys
Veteran
Joined: 15 Aug 2009
Age: 35
Gender: Male
Posts: 927
Location: A deep,dark hole in the ground
I did turn on all the warnings. I got no compiler errors and no runtime errors, and as far as I have been able to tell from running this program, it works perfectly.
And the main() function is only there for testing purposes. It's not supposed to make sense; I just wanted to see if the other two functions worked.
LordoftheMonkeys
Veteran
Joined: 15 Aug 2009
Age: 35
Gender: Male
Posts: 927
Location: A deep,dark hole in the ground
And the main() function is only there for testing purposes. It's not supposed to make sense; I just wanted to see if the other two functions worked.
Warnings are not errors.
If you want, this is the rather too rigorous output:
cc -lm -Wall -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wunused-parameter -Wunknown-pragmas -Wextra -Wdeclaration-after-statement -Wshadow -Wunsafe-loop-optimizations -Wpointer-arith -Wbad-function-cast -Wc++-compat -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wsign-compare -Waggregate-return -Wold-style-definition -Wmissing-field-initializers -Wmissing-noreturn -Wmissing-format-attribute -Wredundant-decls -Wnested-externs -Wunreachable-code -Werror -pedantic -pedantic-errors -Wmissing-prototypes -Wmissing-declarations -Wtraditional liner.c -o liner
liner.c:4:23: error: filestext.h: No such file or directory
cc1: warnings being treated as errors
liner.c: In function ‘main’:
liner.c:6: warning: traditional C rejects ISO C style function definitions
liner.c:10: warning: implicit declaration of function ‘getNumOfLines’
liner.c:10: warning: nested extern declaration of ‘getNumOfLines’
liner.c:12: warning: implicit declaration of function ‘numsOfChars’
liner.c:12: warning: nested extern declaration of ‘numsOfChars’
liner.c:12: error: initialisation makes pointer from integer without a cast
liner.c:12: error: ISO C90 forbids mixed declarations and code
liner.c:13: error: ‘for’ loop initial declaration used outside C99 mode
liner.c: At top level:
liner.c:6: warning: unused parameter ‘argc’
liner.c:20: warning: no previous prototype for ‘numsOfChars’
liner.c:20: error: conflicting types for ‘numsOfChars’
liner.c:12: error: previous implicit declaration of ‘numsOfChars’ was here
liner.c: In function ‘numsOfChars’:
liner.c:20: warning: traditional C rejects ISO C style function definitions
liner.c:24: error: ‘for’ loop initial declaration used outside C99 mode
liner.c: At top level:
liner.c:34: warning: no previous prototype for ‘getNumOfLines’
liner.c: In function ‘getNumOfLines’:
liner.c:34: warning: traditional C rejects ISO C style function definitions
liner.c:39: error: expected expression before ‘.’ token
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
When using EOF, bear in mind that the result being returned by fgetc is an int, and EOF is defined as an int. However, you have stored the result from fgetc in a char. This will truincate it to eight bit (and a char may or may not be treated as signed... depending on which compiler you use.)
In any case, once the int value has been chopped down to eight bits, you cannot distinguish between the genuine EOF value (which in int sized) and the DEL character (0xFF). I.e. your program will stop early, should the file you pass it happen to contain such a character.
========
So far as you program working... it does not. You have not allocated memory for your line counts.
int *lines = (int *) malloc( sizeof(int) );
That allocates space for a single count. Depending on the particular implementation of malloc, you may find that the area of memory allocated is rather larger than a single int, but you cannot reply on that. As you attempt to process files with more and more lines, eventually you will get a run-time error, of some obscure nature, when the memory beyond whatever happens to be available there is corrupted by your program, or the memory management steps in (typically giving you a seg fault).
Minimally, you shaould change it to say:
int *lines = (int *) calloc( numLines, sizeof(int) );
which will also guarantee that the memory is cleared to zero.
=======
Another flaw is that you never free the memory. Not entirely a problem, in your simple program, but it is untidy, and a typical cause of "memory leak" in more complex cases.
=========
Also, should your program be applied to a file which is actively being written to, while you are performing your counting, again you run a risk of overrunning the allocated array of counts... because the rescan of the file may find there are more lines on the third pass, than there were present on the second pass.
=========
Also, a file could even be truncated, between passes two and three. This would have a disastrous effect in the loop where you insist that a character count continues incrementing until you reach the line feed you KNOW is still there (but it happens to no longer be there).
========
Also, your program has a small problem with a file whose last line is not terminated with a line feed. This is not entirely your problem - it is a common problem. What to do with the trailing characters? Count them? Ignore them? Awkward.
========
Is that enough to be getting on with?
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
Similar Topics | |
---|---|
Unlock Temu Pakistan code **acq826526**PKR 15,000 Savings!! |
31 Dec 1969, 7:00 pm |
Unlock Temu Pakistan code **acq826526**PKR 15,000 Savings!! |
31 Dec 1969, 7:00 pm |