Read words from a file one char at a time

I have read up a bit on this at this link:

http://stackoverflow.com/questions/4373047/read-text-file-into-char-array-c-ifstream

I am still struggling though. The program is supposed to read a .txt file and then populate and format a new .txt file showing specific data like how many words, average word length, etc. The function below would count words:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char countWords ( char fileName [] ) {
    ifstream infile;
    char letter [81];
    int n = 0;

    infile.open (fileName);

    while ( infile.peek()  != EOF ) {
        while ( letter != " " ){
            infile.read ( letter,1 );
            cout << letter << endl;
            n++;
        }
    }
}


My thought is that I can get infile.read to read in a word one char at a time and store that word in an array. The function would simply keep track of the word count and pass arrays on to other functions.

So my first issue is that the function will read in chars one at a time and output them to the console. However, each character is accompanied by the whole last line of the .txt file. How can I get the function to only output the character?

Also, I cannot get the function to recognize the end of each word.
Line 10 puts the char in the first index of an array, but it does not give it a null terminator. When you cout "letter" you print until your array reaches a null terminator, and I guess you are just getting lucky when leterr[81] is junk data from your own program.
OH! It looks like infile.read only takes a character type and a string size. How do I add \0 ?
infile.peek() seems like overkill in this case. To count words you could just use the standard insertion operator >> because it will automatically stop at whitespaces.

To count words at the most basic level (any separated chars) you could just do this.

1
2
3
4
5
6
while (infile)
{
    infile >> tmp;
    OutputChars(outfile, tmp);
    n++;
}

To output chars you could make a simple function that outputs a string.

1
2
3
4
5
void OutputChars(ostream& out, string str)
{
    for (int i = 0; i < str.length(); i++)
         out << str[i];
}
Last edited on
For read()? Your second argument was the amount you read, therefore letters[amountRead] = '\0'; is perfectly fine (assuming that your array is big enough).

C++ is more dynamic than that. I do think that basic c-string knowledge is a good thing to have (especially because they are so easy to print out).

C++ would provide you with something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <vector>
#include <string>
#include <fstream>
#include <iostream>

int main(void)
{
  std::vector<std::string> words;
  std::ifstream input("input.txt");
  
  // We could check if input is open now, or just see if our vector size is zero later

  std::string temp;
  while (input >> temp)  words.push_back(temp);

  std::cout << "I read " << words.size() << " words and here they are\n";
  

  // This is a problem with an empty vector.
  std::vector<std::string>::iterator iter;
  for (iter = words.begin(); iter != words.end(); iter++)
    std::cout << *iter << std::endl;

  return 0;
}


c-string route will probably teach you more though.
Last edited on
Well, this gives me outputs of only one character. I should be able to make strings from this and count words. Oddly, the function wont cout line #19. Also, after the .txt file has been read, the program starts spitting out gibberish. I am guessing that this is a null terminator issue still, but I have not figured out how to deal with that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

char countWords ( char fileName [] ) {
    ifstream infile;
    char letter[0];
    int n = 0;
    char entry;

    infile.open (fileName);

    while ( infile.peek()  != EOF ) {
        while ( letter != " " ){
            infile.read ( letter,1 );
            cout << letter << endl;
            n++;
            cout << "enter something: ";
            cin >> entry;
            cout << endl;
        }
        cout << "I'll take swords for 400." << endl;
    }
}
Line 4 should give you problems. Arrays are zero based when accessed but they are not zero based when being declared.

Plus, an array by definition must contain at least 2 components, otherwise it's moot. So change line 4 to either:

char letter;


or


char letter[2]; // storage for 2 letters
Last edited on
Why line 15 - 17? In fact, there is a lot here that doesn't make much sense.

Line 10 isn't so great, what if something other than EOF goes wrong with your file.

Line 11 doesn't make sense, letter doesn't equal anything at that point, and it should be ' '

Use get() instead of read() at line 12, this way you don't need [0] for letter.

Remove 15-17 (and 19 ).

What do you have? letter will be a ' ' and n is the amount of letters in the first word. Even n is a little buggy, what if the first character is a space?

Last edited on
I didn't see the previous comments at ~6:30 PM. Sorry about that.

The "string" file type is disallowed for this program. I am not sure what std:: does, I can look into it, but I am fairly certain that it's not permitted in this program either.

Also not allowed are:
# include <vector>
# include <string>

So I'm hosed there.

Lines 15-17 are there so that I can see how the program is working when I run it. Same with 19. Also, as it turns out, those lines kept the function from running infinitely. So I'm just using the couts as a way to step through the program.

If the first character in the text file is a space, then my word count is off by one. For this program, that is something I can live with.

Yes, I realize that letter[0] should cause me problems. I could not get "letter" to work as a regular char though. And wen I tried to use letter[2] I kept getting gibberish on the back of each character.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char countWords ( char fileName [] ) {
    ifstream infile;
    char letter[0];
    int n = 0;
    char entry;
    int wordCount = 0;
    int ch = 0;

    infile.open (fileName);

    while ( (ch=infile.peek())  != EOF ) {
        while ( letter != " " ){
            infile.read ( letter, 1 );
            cout << letter << endl;
            n++;
        }
        wordCount++;
    }
    letter[n] = '\0';
    cout << wordCount << endl;
    infile.close ();
}


The code above still goes on infinitely. I'm guessing I used letter[n] = '\0'; incorrectly.
Con someone help me terminate this array?
letter is a array with size 1, how could you ever give it a meaningful null terminator?

Make line 3 char letter[64];, and then you could null terminate it. However, you still are only ever reading into the first index of letter, so you're going to get garbage printed.

This function rarely makes sense.

You can't use strings? If it is because you haven't learned about them, then I doubt your teacher expects you to use read(). Must you read these one at a time? The >> operator is going to take care of whitespace for you.
What I really need to do is read words from a text file. Then I can count words, figure out the average length, put them in alphabetical order, etc. I figured that reading characters until I encountered a blank space would work well.
This function does what I need it to do. Thanks for the help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char countWords ( char fileName [] ) {
    ifstream infile;

    char word [21];
    int wordCount = 0;

    infile.open (fileName);

    while ( infile.peek() != EOF ) {
        infile >> word;
        wordCount++;
        cout << word << ", ";
    }
    cout << wordCount << endl;
    infile.close ();
}




Enter a file name to be displayed and copied: test.txt
Okay: Copying file: test.txt to new file: Copy of test.txt
Reading: I'll have a Sam Adams
Reading: It's 9:30 in the morning
There were 2 lines read

I'll, have, a, Sam, Adams, It's, 9:30, in, the, morning, 10

Process returned 0 (0x0)   execution time : 3.653 s
Press any key to continue.
Topic archived. No new replies allowed.