3

My program requires to get input from a textfile and output it on a single line.

However if the amount of characters on a singular line exceed 60, there should be a new line.

The code I have so far:

 int main(int argc, char *argv[]){
 FILE *pFile;
 char x[10];
 char *token;
 pFile = fopen("test5.txt","r");
 int wordLength;
 int totalCharLength;
 char newline[10] = "newline";


 if(pFile != NULL){
        while (fgets(x, sizeof(x), pFile) != NULL) {
         token = strtok(x,"\r\n");
         if(token != NULL){
                printf("%s",x);

            }

         else{
                printf("%s",x);
        }
        //counter++;
        wordLength = strlen(x);
        totalCharLength += wordLength;
        printf("%d",totalCharLength);
        if(totalCharLength == 60){
            printf("%s",newline);
        }

    }

        fclose(pFile);
}
}

Textfile:

 a dog chased 

 a cat up the 

 tree. The cat 

 looked at the dog from 

 the top of the tree.  

There are 5 separate lines. Which displays this. This is not all on one line.

Output:

 a dog chased a cat up the tree. The cat looked at the dog from the top of the tree.

Now the program needs to be able to get input text in that format and print out in a single line.

So the above Output there should be a new line at the 60th char which is before second word "dog".

However I want to add a feature so that there is a counter for character and it prints a new line when character count = 60.

Now with some more debugging I added the code

 printf("%d",totalCharLength);

just before the if(totalCharLength==60) line and I realize that the characters get counted in random increments instead of one by one. Output:

 a dog cha9sed 13a cat up 22the 26tree. The35 cat 40looked at49 the dog 58 from 63 the top o72f the tre81e.  85

So this shows that it does not count character by character. However when I change charx[10] to a lower value it does not print everything on one line. It will leave gaps.

Example: Changing charx[10] to charx[2]

This correctly gets character by character however the output is not in on one line.

The only time there should be a new line is when characters exceed 60 in a line. Not 14 (First line).

 a2 3d4o5g6 7c8h9a10s11e12d13 14
 30a17 18c19a20t21 22u23p24 25t26h27e28 29
 46t32r33e34e35.36 37T38h39e40 41c42a43t44 45
 71l48o49o50k51e52d53 54a55t56 57t58h59e60newline 61d62o63g64 65f66r67o68m69   70
 72t73h74e75 76t77o78p79 80o81f82 83t84h85e86 87t88r89e90e91.92 93 94
bob9123
  • 725
  • 1
  • 9
  • 31
  • 0) `int totalCharLength;` is uninitialize and need reset. – BLUEPIXY Nov 03 '15 at 21:20
  • @BLUEPIXY Yeah I understand that I have to reset the totalCharLength to 0 everytime it hits 60 however that does not solve my main problem. totalCharLength 'skips' past 60. – bob9123 Nov 03 '15 at 21:23
  • input one by one and count one by one. – BLUEPIXY Nov 03 '15 at 21:25
  • I did this at the end of my post. When i input one by one and count one by one. However, the output is not all in one line. The only time it there should be a new line if there is 60 characters. This makes a new line at 14 characters. – bob9123 Nov 03 '15 at 21:27
  • Your use of `strtok` is suspect. The function itself is dangerous to use if not used properly as well as it walks the string passed in, never resetting the pointer. I suspect you are scribbling. Try rewriting the using this question's [answer](http://stackoverflow.com/questions/3501338/c-read-file-line-by-line) as an example. – pedwards Nov 03 '15 at 21:35
  • try `/* else{ printf("%s",x); } */` – BLUEPIXY Nov 03 '15 at 21:42
  • @BLUEPIXY To which if statement? Adding it to the second if statement outputs the same. – bob9123 Nov 03 '15 at 21:44
  • I think It have a bad in combination with one character reading of fgets and strtok. – BLUEPIXY Nov 03 '15 at 21:47
  • @BLUEPIXY I could not find another way around it. The only way I know of that can get input from text file with many lines and output in one line. Very new C programmer so not sure. – bob9123 Nov 03 '15 at 21:48
  • _To which if statement?_ `token` doesn't need print and count of string if `token` became `NULL`(If `x` is composed of `\r` or `\n`). – BLUEPIXY Nov 03 '15 at 22:04
  • _There are 5 separate lines._ is `" a dog chased \n", "\n", " a cat up the \n", "\n", " tree. The cat \n", "\n", " looked at the dog from \n", "\n", " the top of the tree. "` ? – BLUEPIXY Nov 03 '15 at 22:51
  • @BLUEPIXY Yeah, sorry if that was not clear. – bob9123 Nov 03 '15 at 22:54
  • The space between the words is unified into one? also Do newline replace with space ? – BLUEPIXY Nov 03 '15 at 22:56
  • No the spaces remain how they should be. Yeah newline is essentially replaced with spaces. So hypothetically if there is a large text file there should be many long single lines with max 60 characters. – bob9123 Nov 03 '15 at 23:04
  • Your output samples it seems the two spaces(if replace newline, three spaces), as only once. – BLUEPIXY Nov 03 '15 at 23:07
  • @BLUEPIXY Not clear what you are saying. – bob9123 Nov 03 '15 at 23:31
  • E.g `" a dog chased \n"` + `" a cat up the \n"` (delete newline, remain space) => `" a dog chased a cat up the "`(chaseda) but your sample `" a dog chased a cat up the "`(chaseda) – BLUEPIXY Nov 03 '15 at 23:34
  • Yeah it's supposed to be one space between new lines. – bob9123 Nov 03 '15 at 23:49

6 Answers6

1

I think you are best just printing each char on his own, and check for a space before adding the newline.

Something like:

((charCount > 60) && (currentChar == ' ')) {
    // print newline and reset counter
    printf("\n");
    charCount = 0;
}

Edit: before anything check if the current char is a newline already and skip it. Check the carriage return \r as well since in windows newlines are \r\n.

#include <stdio.h>

int main(void) {
  FILE *f = fopen("test.txt", "r");
  if(!f) {
    printf("File not found.\n");
    return 1;
  }

  char c;
  int cCount = 0;
  while((c = fgetc(f)) != EOF) {
    if(c == '\r') continue;
    if(c == '\n') c = ' ';

    printf("%c", c);
    if((cCount++ > 60) && (c == ' ')) {
      printf("\n");
      cCount = 0;
    }
  }

  fclose(f);
  return 0;
}
  • With all the fgetc methods It still only outputs the last two lines with a new line between. " looked at the dog from \n the top of the tree". – bob9123 Nov 03 '15 at 22:11
  • 1
    `a dog chased a cat up the tree. The cat looked at the dog from the top of the tree. ` is my output with a copy paste from your question. that has a problem with double spaces with double newlines. but it prints it all. are you sure you haven't modified your original test file? – Andrea Gilmozzi Nov 03 '15 at 22:26
  • I tested your code and I works only when the input file text is already printed is already in one line. In my case the input file has many 5 separate lines. Sorry if that was not clear. – bob9123 Nov 03 '15 at 22:37
  • this is unusual. my test file has 5 lines separated by a blank line. just like you, and the output is just how I posted earlier. maybe you are saving on windows and so you have that weird `\r\n` line ending. so it prints the return carriage and overwrites the previous line. until the new line is forced. – Andrea Gilmozzi Nov 03 '15 at 22:45
  • try adding `if(c == '\r') continue;` right before or after the `if(c == '\n') c = ' ';` code in answer updated to reflect this if you want to fresh copy-paste – Andrea Gilmozzi Nov 03 '15 at 22:46
  • Yeah I am using Windows 10. Will try your new if code now. – bob9123 Nov 03 '15 at 22:47
  • Yeah did that it! There is a newline after from. Now something I don't understand is why the new line is after 'from' and not the second 'dog'. Surely after 'dog' is the 60th character? – bob9123 Nov 03 '15 at 22:59
  • As if you add 'from' that will make it over 60 characters. – bob9123 Nov 03 '15 at 23:02
  • the 60th character is the `r` in `from` I believe. Spaces count as character as well. if you want a different behavior you might just want to `cCount--;` on spaces and newlines converted to spaces. – Andrea Gilmozzi Nov 03 '15 at 23:05
  • Sorry if this is a silly question but isn't what the line "if(c == '\n') c = ' ';" does? It replaces a new line with a ' '? – bob9123 Nov 03 '15 at 23:15
  • that just replace the '\n' char with the ' ', a space. – Andrea Gilmozzi Nov 03 '15 at 23:17
  • Quick question.( You don't have to go into a through answer). words like ".sp 2" and ".ce" are formatting commands. What will be the best way to detect these commands and launch a appropriate action while going through the text? – bob9123 Nov 03 '15 at 23:47
  • while going trough the text you might check for a dot, read the next X characters and check if they are a command. is dot -> read X chars in buffer[X] -> if == sp -> read number (`atoi(char)`) -> do stuffs <- else if == ce -> do stuffs <- else -> for each char in buffer -> things you did before the dot. you will probabilly want to `include ` for function as `strcmp()`. – Andrea Gilmozzi Nov 04 '15 at 00:13
  • Yeah thanks I was thinking this way. Now in C is there a way to directly read the next char? So if it detects a . is there a function that can read the next to chars? Or do I have to make my code for it – bob9123 Nov 04 '15 at 00:32
  • we should avoid so many comments, but check `fgets()` or just `getc()`. – Andrea Gilmozzi Nov 04 '15 at 00:42
1

There you go

int main() {
    FILE *pFile = fopen("test.txt","r");
    int c, counter = 0;
    if (pFile != NULL) {
        while ((c = getc(pFile)) != EOF) {
            counter++;
            if (c != '\n') { putchar(c); }
            if (counter == 60) {
                counter = 0;
                printf("\n");
            }
        }
    }
    fclose(pFile);
}
Lukas
  • 3,423
  • 2
  • 14
  • 26
  • Thanks for the code however the output is still incorrect. It misses the first 3 lines and prints "looked at the \n the top of the tree". \n obviously being a newline in the output. – bob9123 Nov 03 '15 at 22:22
  • add `#include ` as the first line and this compiles with `gcc test.c` and runs just fine for me. – pedwards Nov 03 '15 at 22:28
  • 1
    first three lines? I don't see how thats possible. I tested it with your file and it works well. only problem I noticed is it prints white space even after newline which is kinda not necessary – Lukas Nov 03 '15 at 22:38
  • @Lukas The code only works if the input file words are all on one line. In my case the the input file has 5 separate lines that displays the text which crashes the program. – bob9123 Nov 03 '15 at 22:41
  • I tested it with 5 line strings just like yours and it works. make sure you imported , , – Lukas Nov 03 '15 at 22:49
  • Imported everything. Still same error. Does me being on Windows change anything? – bob9123 Nov 03 '15 at 22:57
0
if(token != NULL){
            printf("%s",x);
           strcat(newArray, x);
        }

After printing out the token, have a separate array that you concatenate the token too. This will give you the entire file on one line. It will be much easier from here to parse out the 60 characters then print lines as you go.

scerrecrow
  • 259
  • 1
  • 9
  • So I add x into new array and then print out all elements of the array while counting characters? – bob9123 Nov 03 '15 at 21:41
  • you add x into the new array. Then once the array is filled with all the characters (minus the new line characters). You can create a separate for loop that prints out all the characters one by one, when you reach 60, print a new line. Continue until no other letters are left in array. – scerrecrow Nov 04 '15 at 14:47
0

It goes like this,

#include<stdio.h>
//#pragma warning(disable : 4996)


int main()
{
    FILE *pfile;
    char data;
    int count = 1;
    pfile = fopen("test.txt", "r");
    printf("Opening file...\n");
    if (pfile == NULL)
    {
        printf("Error!\n");
    }

    while ((data = fgetc(pfile)) != EOF)
    {
       if (count != 60)
       {
          if (data != '\n')
          {
            printf("%c", data);
            count++;
          }

       }
       else
       {
          printf("\n");
          count = 1;
       }

    }
    fclose(pfile);
  return 0;
}
Mutex202
  • 31
  • 4
  • With the input textfile from my description, it only outputs "looked at the do \n the top of the tree. – bob9123 Nov 03 '15 at 21:54
0

In the first case, when you had char x[10], fgets will read up to 9 characters, or until a newline is found. So the output is

a dog cha9sed 13a cat up 22the 26

because the first call to fgets reads 9 characters (and then prints 9), the second call reads up to the newline (prints 13), the third call reads nine characters (prints 22), and the fourth call reads up to the newline (prints 26).

When you change to char x[2], fgets will only read one character at a time. And this causes strtok to work differently than you expect. When a string contains only delimiter characters, strtok will return NULL and the string is unmodified. So if the string contains only a newline character, strtok won't remove the newline, like you expect.

To fix the code, use fgetc to read characters and don't use strtok at all.

int main( void )
{
    FILE *pFile;
    if ( (pFile = fopen("test5.txt","r")) == NULL )
        exit( 1 );

    int c, count;

    count = 0;
    while ( (c = fgetc(pFile)) != EOF ) {
        if ( c == '\n' )
            putchar( ' ' );
        else
            putchar( c );

        count++;
        if ( count == 60 ) {
            putchar( '\n' );
            count = 0;
        }
    }
    putchar( '\n' );
    fclose(pFile);
}

Here's the file that I tested with

a dog chased
a cat up the
tree. The cat
looked at the dog from
the top of the tree.
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • Thanks for explanation. However it still has a weird output. " looked at the \n the top of the tree. " – bob9123 Nov 03 '15 at 22:07
  • Basically the code is not displaying the first three lines and impartially displaying the fourth From the fourth line it misses out "from" at the end of the line. – bob9123 Nov 03 '15 at 22:19
  • Yeah. I'm having the exact same error with other people's code so not sure if it's me causing the a mistake. – bob9123 Nov 03 '15 at 22:23
  • Does using Windows have an effect on my strange output? – bob9123 Nov 03 '15 at 22:58
  • Nope, it shouldn't. I suggest looking at your input file with a hex editor, to see what's actually in it. – user3386109 Nov 03 '15 at 23:04
  • Only asking this because for another answer which was similar to yours adding 'if(c == '\r') continue;' made it work. – bob9123 Nov 03 '15 at 23:07
  • On windows, that means that your file contains a `\r` that is not followed by a `\n`. – user3386109 Nov 03 '15 at 23:16
  • That did it thanks. Quick question.( You don't have to go into a through answer). words like ".sp 2" and ".ce" are formatting commands. What will be the best way to detect these commands and launch a appropriate action while going through the text? – bob9123 Nov 03 '15 at 23:48
0
#include <stdio.h>
#include <ctype.h>

int main(void){//unused argv
    FILE *pFile;
    int ch, prev = 0;
    int totalCharLength = 0;
    int wrap_size = 60;
    //char newline[] = "newline";

    pFile = fopen("test5.txt","r");

    if(pFile != NULL){
        while((ch = fgetc(pFile)) != EOF){
            if(isspace(ch))
                ch = ' ';
            if(prev == ' ' && ch == ' ')
                continue;//unified
            prev = ch;
            putchar(ch);
            if(++totalCharLength == wrap_size -1){//-1 : include newline
                putchar('\n');//printf("%s", newline);
                totalCharLength = 0;
            }
        }
        fclose(pFile);//put inside if-block
    }

    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • Basically the code to 'predict' if the next word will go over a 60 character limit. So individual words can't be split up. If the next word is going to go over make a new line before that happens. – bob9123 Nov 04 '15 at 00:30
  • @bob9123 Although I think that such conditions have not been written... It is possible of course. In that case towards the reading of the word unit it would be better. – BLUEPIXY Nov 04 '15 at 00:33
  • Yeah I did not declare this earlier I apologize . Just wanted to add this here to improve the program. – bob9123 Nov 04 '15 at 00:36
  • you try it. (and post new question) – BLUEPIXY Nov 04 '15 at 01:05