Thread: Little C personal utilities

  1. #1
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332

    Little C personal utilities

    I find myself writing these often. Do you do this too?

    For example, I wrote a text file reformatter, as I often need to paste text into a mainframe application that can only handle lines up 72 characters wide. It accepts as input any text file, and add a CRLF after whichever word is the last to fit on a line.

    And yesterday, I wrote a horizontal editor of sorts, where I add a new line at the top of a text file and add in (what I call) margin characters. It allows me to extract a vertical section of data from the file based on the left and right margin characters. Or, if only one margin character is supplied, that makes it the rightmost column and all lines get truncated to that length.

    Both are pretty trivial. I made them to to sit on my desktop and I just drop a file on them to use them. The newly formatted data is presented in Notepad where I copy and paste the data into other applications where I need the data.
    Mainframe assembler programmer by trade. C coder when I can.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Wow, it is like screenshot day for me today

    When I was learning gtk the first thing I did was "note" and "notelist". They need a bit of touching up, but they still work fine so I haven't bothered.

    Looks like my bash notes are a little stale...oh well. Mostly the point was to have a place where I could jot down little points that need infrequent recollection, caveats on man pages, etc. Which you can include another doc file to refer to and call that up too. And categorize things with two "qualifiers". It's like your own help browser. If you can't understand yourself, who can you understand?

    Really I should stop BS'ing in General Discussions and take more notes. The last entry in "C-oversight" is "use return at the end of forked children!"
    Last edited by MK27; 09-19-2009 at 04:45 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    When I was learning gtk the first thing I did was "note" and "notelist". They need a bit of touching up, but they still work fine so I haven't bothered.
    Well you know flashiness is way overrated anyway - they look pretty handy to me.

    @Dino: Absolutely. It's a great way to make your life easier and also put your talents to good use (especially if you design them in such a way that they can be linked together with other programs (which just happens to be one of the cornerstones of "the Unix philosephy", incidentally)).

  4. #4
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    I wrote an ISO ripper because some DVD's use bad sector protection and alcohol 120 is a PITA to use in those cases.

    I only use it for DVD's I own, and you have to manually change the DVD source drive and destination name, but it works great. Took me all of like 5 minutes to write (I had to look up the syntax for physical drive access on MSDN).

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    
    int main(){
    
    	LPVOID Buffer = (LPVOID)malloc(1048576);
    
    	HANDLE hFile = CreateFile(TEXT("\\\\.\\J:") , GENERIC_READ , 7 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_READONLY , NULL);
    	FILE* pFile = fopen("C:\\DVDNAME.ISO" , "w+b");
    
    	DWORD dwBytesRead = 0;
    	unsigned __int64 BytesWritten = 0;
    
    	do {
    		ReadFile(hFile , Buffer , 1048576 , &dwBytesRead , NULL);
    		BytesWritten += dwBytesRead;
    		fwrite(Buffer , dwBytesRead , 1 , pFile);
    		printf("%d MB\n" , (BytesWritten/1048576));
    		} while(dwBytesRead);
    	
    	CloseHandle(hFile);
    	fclose(pFile);
    
    	free(Buffer);
    
    	return 0;
    	}

  5. #5
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    I have a machine size calculator type thing... Running it on a given machine gives me an idea of the sizes of different types on the machine. I don't use it to tailor code to that machine, but more as a reminder of how large of a value is a certain data type to contain.

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I know that nobody asked (and for all I know, everyone here may already be familiar with this), but I just thought I'd elaborate on ways to write programs that can be linked together.

    The example here is just a simple C program that reads binary data from a file or standard input, converts it to a hexadecimal string, and then writes the result to standard output. A basic console-based hex-dump utility.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    void dump( FILE* in, FILE* out );
    	
    int main( int argc, char** argv )
    {
    /*
    	For now, just use stdout for output, and stderr for all messages
    */
    	FILE*
    		out = stdout;
    	fprintf( stderr, "HexDump Utility\n" );	
    	if( argc == 1 )
    		dump( stdin, out );
    	else while( *( ++argv ) )
    	{
    		FILE* 
    			in = fopen( *argv, "rb" );
    		if( in == 0 )
    		{
    			fprintf( stderr, "Error: cannot process file '%s'\n", *argv );
    			continue;
    		}
    		fprintf( stderr, "File: '%s'\n", *argv );
    		dump( in, out );
    		fclose( in );
    	}
    	return 0;
    }
    
    void dump( FILE* in, FILE* out )
    {
    	unsigned char
    		ch;
    	char const
    		* pad = "",
    		table[ ] = "0123456789ABCDEF";
    	for( ;; )
    	{
    		if( !fread( &ch, 1, sizeof( ch ), in ) )
    		{
    			if( ferror( in ) )
    				fprintf( stderr, "\nError: read operation failed" );
    			break;
    		}
    		if( !fprintf( out, "%s%c%c", pad, table[ ch >> 4 ], table[ ch & 0xf ] ) )
    		{
    			fprintf( stderr, "\nError: write operation failed" );
    			break;
    		}
    		pad = " ";
    	}
    	fprintf( out, "\n" );
    }
    So the important points are:
    1) Abstract the file source and destination streams.
    2) By default, read from standard input and write to standard output. Additionally, it's often useful to provide facilities for reading/writing actual files (such as in the above example with respect to input).
    3) Sometimes it's better to write all messages to stderr (even non-error messages), especially when the output is some sort of binary data.

    Anyway, numerous utilities that I've written use some variation of that basic theme. It's pretty useful, actually.

  7. #7
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    For example, I wrote a text file reformatter, as I often need to paste text into a mainframe application that can only handle lines up 72 characters wide. It accepts as input any text file, and add a CRLF after whichever word is the last to fit on a line.

    And yesterday, I wrote a horizontal editor of sorts, where I add a new line at the top of a text file and add in (what I call) margin characters. It allows me to extract a vertical section of data from the file based on the left and right margin characters. Or, if only one margin character is supplied, that makes it the rightmost column and all lines get truncated to that length.
    Ouch. Text processing in C is a nightmare, although if you're working with old machines then perhaps there was no other choice. At work I had to make a small prog to do some processing on a csv. Since I am big and bad enough to get to do things my way, I thought I'd do it in C for a change. Perhaps I'm a little rusty with it atm, but it took me 2 hours to write a prog I could have done in 10 minutes with PHP or Python, or even bash, and I hate bash for programming. And, since it ran on a mac, I couldent even drag and drop the files on top of the binary to run it :/ Mac users dont usually like typing strange things into terminals, but the guy at work seemed happy enough with it, and thats all i care about, lol.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Anything to do with text processing that does not have the "blazingly fast" requirement, I do in Perl or Python. Text processing in C is just masochism.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by brewbuck View Post
    Anything to do with text processing that does not have the "blazingly fast" requirement, I do in Perl or Python. Text processing in C is just masochism.
    I'm actually faster at text processing in C than I am with Perl. I think this is more of a result of how bad I am at Perl than anything else I've been known to spend an hour trying to get a regex to do what I want...
    bit∙hub [bit-huhb] n. A source and destination for information.

  10. #10
    Registered User
    Join Date
    Sep 2001
    Posts
    4,912
    I've been known to spend an hour trying to get a regex to do what I want...
    Have you tried one of the online utilities? You give it a pile of sample inputs, and you can try regular expressions and instantly see what matches were made - it speeds up the process immensely.

  11. #11
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by sean View Post
    Have you tried one of the online utilities? You give it a pile of sample inputs, and you can try regular expressions and instantly see what matches were made - it speeds up the process immensely.
    I've never tried that before, but I will be sure to try it next time
    bit∙hub [bit-huhb] n. A source and destination for information.

  12. #12
    Registered User
    Join Date
    Sep 2001
    Posts
    4,912
    This is the one I use: Flex Regular Expression Tool

    It's for ActionScript and not Perl, but I'm pretty sure they're reasonably close to each other - and this has the added benefit of being VERY quick - no CGI submission or anything. It's all client-side code.

  13. #13
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    There's also Online Regular Expression Testing Tool. And for offline use, Text Crawler freeware which does include a regex testing tool.

    EDIT:Was forgetting: The best testing tool I've ever encountered so far was the incredible RegexBuddy. I never found a true necessity to cough up the money for it, but that's another suggestion.

    But paraphrasing a prolific writer, never forget that if you have one problem that requires regular expressions, you now will have two problems.
    Last edited by Mario F.; 09-21-2009 at 05:47 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Mario F. View Post
    But paraphrasing a prolific writer, never forget that if you have one problem that requires regular expressions, you now will have two problems.
    Heh. Nice one. =)

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Wow, kind of surprised that people find regular expressions such a hassle. So here's a very simple way to test them in perl:
    Code:
    #!/usr/bin/perl -w 
    use strict;
    
    use Term::ReadLine;
    # for correction and command history you must have
    # Term::ReadLine::Gnu (from CPAN) installed
    
    my $term = new Term::ReadLine 'regular expression test';
    my $OUT = $term->OUT || *STDOUT;
    
    while (1) {
            my $st=$term->readline("\ninput: ");
            my $rg=$term->readline("regexp: ");
            eval {$st =~ /$rg/};  # catch bad regexp
            if ($@) { warn $@; next; }
            print "\tFound: $&\n" while ($st =~ /$rg/g);  
    }
    Normally a badly formulated regexp results in a runtime error, but here this is prevented by using eval -- but you will still be informed of the mistake.

    Also, readline provides a command history so that you can use the arrow keys to cycle back thru your previous tries, which can be a big time saver. If you want to get backreferences out, etc, you'll have to mod the code slightly.

    Speaking of backreferences, here's something I learned recently: \1 will match the exact contents of $1. So with

    that is not this, it's that
    /(th..).*\1/
    $1 will be "that", and so then will be \1
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. New personal record
    By VirtualAce in forum Windows Programming
    Replies: 2
    Last Post: 04-10-2005, 08:21 PM
  2. Replies: 6
    Last Post: 02-01-2005, 09:41 AM
  3. Personal messages disabled temporarily
    By webmaster in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 08-11-2001, 06:25 PM