Stdin with getc producing additional output, and opening file causing segmentation fault in C -


#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" );     } }