1

I want to read inputtext.txt line by line and reverse the order of words in each line and print them out (input: hello world,output: world hello). With this code my output is all messed up and I get a runtime error #2 saying the stack around my array "string" is corrupted. I tried resetting the strings to null after each while loop iteration but I still get the same error. Does anybody have any suggestions to get rid of the runtime error or help the code run more smoothly?

int main() {
    FILE *inp,*outp;        //file input and output
    int i,wordcount;                    //define counter variables
    int k = 0,j=0;
    char string[200];       //define string to scan sentence into
    char words[20][20];     //2D string for each word in the sentence
    inp = fopen("inputtext.txt", "r");
    outp = fopen("output.txt", "w");
    if (inp == NULL) {
        printf("File not found.\n");
    }
    else {
        while (!feof(inp)) {

            fgets(string, 1000, inp);
            printf("GOT SENTENCE\n");
            for (i = 0; string[i] != '\0'; i++) {


                if (string[i] == ' ') {
                    words[k][j] = '\0';
                    k++;
                    j = 0;
                }
                else
                {
                    words[k][j] = string[i];
                    j++;
                }

            }

            words[k][j] = '\0';
            wordcount = k;
            for (i = wordcount; i >= 0; i--) {
                printf("%s ", words[i]);
            }
            printf("\n\n");

        }
    }
    return 0;
}
jnimrod
  • 21
  • 3
  • 1
    We can't tell what `words` is or what `j` or `k`'s initial value is because your code is not complete. – David Schwartz Mar 26 '19 at 22:00
  • Updated question with full code. Hope it helps. – jnimrod Mar 26 '19 at 22:02
  • 1
    Can you tell us what input you're providing? Also, why do you set to `k` and `j` to zero only once when they need to be zero each time you try to process a line? – David Schwartz Mar 26 '19 at 22:02
  • The input is a file with a sentence on each line with no punctuation. I'm not sure how to show you. – jnimrod Mar 26 '19 at 22:08
  • At the end of the loop i reset k and j to 0 which cleaned up the output and got rid of the runtime error, thanks for the suggestion. Now my only problem is that it prints a newline after the first word. The first line in inputtext.txt is "birds and bees", so the output should be "bees and birds". The output I am getting is "bees\n and birds". – jnimrod Mar 26 '19 at 22:27
  • 1
    Your ``string`` array might overflow (length 200), if your ``fgets`` reads a line longer than 199 characters (null byte), as your tell it to read up to 1000 chars. If that happens, your stack gets corrupted – LeBlue Mar 26 '19 at 22:31
  • `for (i = 0; string[i] != '\0' && string[i] != '\n'; i++)`. It reads and prints a `\n` at the end of your sentence. So, this could solve it. – koleygr Mar 26 '19 at 23:01
  • the posted code does not cleanly compile! Amongst other problems, it is missing the `#include` statements for the needed header files – user3629249 Mar 26 '19 at 23:35
  • regarding: `while (!feof(inp)) {` please read: [why while(!feof() ) is never correct](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) – user3629249 Mar 26 '19 at 23:38
  • OT: regarding: `if (inp == NULL) { printf("File not found.\n"); }` 1) error messages should be output to `stderr`, not `stdout`. 2) when the error is from a C library function should also output (to `stderr`) the text reason the system thinks the error occurred. The function `perror( "fopen for reading inputtext.txt failed");` performs the above functionality and that probably should be followed by: `exit( EXIT_FAILURE );` Note `exit()` and `EXIT_FAILURE` are from the header file: `stdlib.h` (cont) – user3629249 Mar 26 '19 at 23:42
  • (cont) 3) don't place other statements between the call to `fopen()` and `if ... == NULL )` code block, so that `errno` still contains the correct value. 4) the same testing needs to be done for the call to `fopen()` for writing `output.txt` – user3629249 Mar 26 '19 at 23:45
  • regarding: `while (!feof(inp)) { fgets(string, 1000, inp);` Suggest replacing with: `while ( fgets(string, 200, inp) ) {` Note: using 200 rather than 1000 because the length of the array: `string[]` is only 200 – user3629249 Mar 26 '19 at 23:49
  • after calling `fgets()` need to remove the trailing newline . This can easily be performed via: `string[ strspn( string, "\n" ) ] = '\0';` – user3629249 Mar 27 '19 at 00:05

1 Answers1

0

the following proposed code:

  1. cleanly compiles
  2. properly checks for errors
  3. properly outputs error messages to stderr
  4. performs the desired functionality
  5. properly limits the max length of an input
  6. assumes no line in the input file is over 199 characters
  7. minimizes the number of times the function: strlen() is called
  8. actually writes the reversed sentences to the output file

And now, the proposed code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main() 
{
    FILE *inp,*outp;        //file input and output
    int wordcount;                    //define counter variables
    int k = 0;
    int j = 0;
    char string[200];       //define string to scan sentence into
    char words[20][20];     //2D string for each word in the sentence

    inp = fopen("inputtext.txt", "r");
    if( !inp )
    {
        perror( "fopen to read: inputtext.txt failed" );
        exit( EXIT_FAILURE );
    }

    outp = fopen("output.txt", "w");
    if( !outp )
    {
        perror( "fopen to write: output.txt failed" );
        // cleanup
        fclose( inp );
        exit( EXIT_FAILURE );
    }


    size_t strLength = strlen( string );

    for (size_t i = 0; i < strLength; i++)
    {
        // remove any trailing newline
        string[ strspn( string, "\n" ) ] = '\0';

        printf("GOT SENTENCE\n");

        for (size_t i = 0; i < strlen(string); i++) 
        {
            if (string[i] == ' ') 
            {
                words[k][j] = '\0';
                k++;
                j = 0;
            }

            else
            {
                words[k][j] = string[i];
                j++;
            }
        }

        words[k][j] = '\0';
        wordcount = k;

        for ( int i = wordcount; i >= 0; i--) 
        {
            printf("%s ", words[i]);
            fprintf( outp, "%s ", words[i] );
        }
        printf("\n\n");
        fprintf( outp, "\n" );
    }

    return 0;
}
user3629249
  • 16,402
  • 1
  • 16
  • 17