#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> typedef int bool; #define true 1 #define false 0 #define 65 #define z 90 #define 97 #define z 122 #define newline 10 int main(int argc, char* argv[]) { int noargreverse(); int argreverse(int i, char* c[]); if (argc == 1){ if (noargreverse() == 0) return 0; else return 1; } if (argc > 1){ if (argreverse(argc, argv) == 0) return 0; else return 1; } else{ fprintf(stderr, "unknown error detected.\n"); return 1; } } int noargreverse() { char charinput[10000]; int pointerarray[5000]; int pointercount = 0; bool wordstart = false; int indexer; int linelength; int parser; char currinput; pointerarray[0] = 0; // first word start @ 0 default while (currinput != eof){ linelength = 0; indexer = 0; pointercount = 0; while ((currinput = getc(stdin)) != newline){ /* * implementing 10,000 char limit, seems * unreasonable length. */ if (linelength == 9999){ fprintf(stderr, "line length exceeded 10,000 chars. " "this line and, if in middle of word," "will split.\n"); break; } if (!wordstart){ if ((currinput >= && currinput <= z) || (currinput >= && currinput <= z)){ wordstart = true; } } while (wordstart){ charinput[linelength++] = currinput; currinput = getc(stdin); //if word has ended if ((currinput < || currinput > z) && (currinput < || currinput > z)){ wordstart = false; charinput[linelength++] = '\0'; if (pointercount != 0){ // @ least 1 word has been added ++indexer; pointerarray[indexer] = pointercount; pointercount = linelength; } else //first word of line added pointercount = linelength; } } } while (indexer >= 0){ parser = pointerarray[indexer--]; while (charinput[parser] != '\0') fprintf (stdout, "%c", charinput[parser++]); fprintf (stdout, " "); } fprintf (stdout, "\r\n"); if (linelength == 0){ currinput = eof; } } return 0; } int argreverse (int argc, char* argv[]) { char charinput[10000]; int pointerarray[5000]; int pointercount = 0; bool wordstart = false; int indexer; int linelength; int parser; char currinput; file *currentfile; while (argc > 0){ currentfile = fopen(argv[argc--], "r"); while ((currinput = getc(currentfile)) != eof){ linelength = 0; indexer = 0; pointercount = 0; while (currinput != newline){ /* * implementing 10,000 char limit, seems * unreasonable length single line. */ if (linelength == 9999){ fprintf(stderr, "line length exceeded 10,000 chars. " "this line and, if in middle of word, word, " "will split.\n"); break; } if (!wordstart){ if ((currinput >= && currinput <= z) || (currinput >= && currinput <= z)){ wordstart = true; } } while (wordstart){ charinput[linelength++] = currinput; currinput = getc(currentfile); //if word has ended if ((currinput < || currinput > z) && (currinput < || currinput > z)){ wordstart = false; charinput[linelength++] = '\0'; if (pointercount != 0){ // @ least 1 word has been added ++indexer; pointerarray[indexer] = pointercount; pointercount = linelength; } else //first word of line added pointercount = linelength; } } } } fclose(currentfile); } return 0; }
so first function, i'm getting error can't seem bottom while debugging, or, rather, i'm not sure how solve. function should take input stdin
, , print words in reverse order (the chars should remain in order, "this sentence" should "sentence this"). simple enough. however, when give sample input, output wrong.
input:
this sample input testing
output:
testing input sample
the input has 1 return, output has return between lines, , not split lines.
so, it's not printing newline when should, , it's printing first inputted word again when ends.
the second issue having in second set of code, argreverse
function. after file opened, in case use test.txt, simple text file couple lines of phrases , empty lines, first use of getc
returns segmentation fault. read permission or failed file opening, i'm not sure fix this. i'm trying open last file first , work down there, obviously, , should able handle multiple files, can't open one. i'm not sure fix this. i've tried moving getc
outside of while
loop, same problem. i'm guessing i'm doing wrong opening file, don't know is.
notes on style:
the bool
type, , true
, false
defined in <stdbool.h>
.
use character constants 'a' 'z' 'a' 'z' '\n'
instead of hard-coded numbers, and/or use character classification functions isalpha
<ctype.h>
.
the "reverse" functions return 0 when end, there's no point in returning anything. should declared returning void
. if did return useful, return value main
(eliminating if
statements). example,
if ( argc == 1 ) return noargreverse();
putting large arrays on stack bad idea. (large subjective, use 2k bytes rule of thumb.) non-reentrant function, can declare arrays static
them off stack. reentrant function, can malloc
arrays, , free
them @ end.
notes on design:
the fgets
function read line , put buffer. no need read character @ time.
when processing command line arguments, canonical loop is
int main( int argc, char *argv[] ) { ( int = 1; < argc; i++ ) printf( "argv[%d] \"%s\"\n", i, argv[i] ); }
the reason seg-fault using argv[argc]
, c specification guarantees null
. passing null
fopen
. furthermore, should check return value fopen
, because fopen
return null
if unable open file.
by far biggest design issue in code repetition. have 2 almost-identical functions, nightmare debug , maintain, since every change needs made twice, , tested twice. solution define reverse
function takes file pointer input. main
function should take care of opening/closing files, or can pass stdin
when there aren't args.
sample code:
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #define maxl 10000 #define maxw 5000 void reverse( file *fp ); int main( int argc, char *argv[] ) { if ( argc < 2 ) { reverse( stdin ); return 0; } file *fp; ( int = 1; < argc; i++ ) { printf( "----- %s -----\n", argv[i] ); if ( (fp = fopen( argv[i], "r" )) == null ) { printf( "***error: unable open file\n" ); } else { reverse( fp ); fclose( fp ); } } return 0; } void reverse( file *fp ) { static char line[maxl]; // buffer input line static char *word[maxw]; // array of pointers words on line while ( fgets( line, maxl, fp ) != null ) { int = -1; int count = 0; // count of words on line (;;) { // skip non-alpha characters ( i++; line[i]; i++ ) if ( isalpha( line[i] ) ) break; // check if we've reached end of line if ( !line[i] ) break; // add pointer word list word[count++] = &line[i]; // scan till reach end of word ( i++; line[i]; i++ ) if ( !isalpha( line[i] ) ) break; // check if we've reached end of line if ( !line[i] ) break; // terminate word line[i] = '\0'; } // output words in reverse order ( = count - 1; >= 0; i-- ) printf( "%s ", word[i] ); printf( "\n" ); } }