0

I'm attempting to read a text file character by character. I'm using a string to read the file. My code for reading the file is below:

int main()
{   
    std::ifstream data;
    data.open("C:\\Users\\Christian Dean\\Documents\\CodeLiteWorkspace\\CplusplusPractice\\src\\test_file.qz");
    std::string data_str;
    int counter = 0;
    data >> data_str;
    for(int i = 0; i < data_str.length(); i++)
    {
        std::string tokenizer = data_str[i];
        if (tokenizer == "output")
        {
            counter++;
        }
    }
    std::cout << counter << std::endl;
    data.close();
    return 0;
}

as you can see, in my for loop I'm setting the string tokenizer equal to the zeroth index of the string data_str. However when compiling, it show the error

`main.cpp:27:37: error: invalid conversion from 'char' to ''const char*' [-fpermissive].

I really don't know how else I can read the file character by character. I tried setting tokenizer as type char. But when I run the program it says the counter variable equals 0. So obviously making the tokenizer variable a type char did not work.

The content of the text file is below if it is needed:

 output: "Hello World
Christian Dean
  • 19,561
  • 6
  • 42
  • 71
  • Please describe what you want to do, as I do not see how reading character by character ever results in the string `output` in `tokenizer`, if `tokenizer` only contains one character at a time. – Yakk - Adam Nevraumont Aug 06 '16 at 00:47
  • To expand on Yakk's comment, by walking the input one character at a time, you can never see a whole word. If instead you extracted strings until `data.eof ()` returned true, you would walk each word in the file, which you could compare and count against – nate Aug 06 '16 at 00:53
  • Not sure if I'm misreading what nate intended with his comment, but fear the loop to eof. More here: http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – user4581301 Aug 06 '16 at 00:57
  • I was not aware of that pitfall, but the basic idea is the same with additional error checking. – nate Aug 06 '16 at 01:00
  • Something tells me you could get some tokenizing ideas [from this question](https://stackoverflow.com/questions/236129/split-a-string-in-c) and its host of answers in varying degrees. There are *many* ways to tokenize input in C++. It's worth at least a few minutes of reviewing. – WhozCraig Aug 06 '16 at 01:02
  • @WhozCraig Actual no. I was trying to see if I could tokenize a file, for practice. I appreciate the link though. – Christian Dean Aug 06 '16 at 01:38
  • It wasn't meant to be a "here's a canned solution" link. More for *ideas*. Hope it helps. – WhozCraig Aug 06 '16 at 01:42
  • @WhozCraig Oh I know. I was just saying where I got my idea from. – Christian Dean Aug 06 '16 at 01:48

2 Answers2

3
std::string data_str;

defines a std::string.

std::string tokenizer = data_str[i]

defines a std::string and attempts to construct the string with a single character. std::string has no constructor that accepts a single character.

Seeing as you're going to compare this single character string against a whole word, this isn't what you want to do anyway.

data >> data_str;

reads in whitespace delimited token--effectively one word plus any punctuation.

so

while (data >> data_str)
{
    stripPunctuation(data_str);
    if (data_str == "output")
    {
        counter++;
    }
}

stripPunctuation would look like void stripPunctuation(std::string & input) and would remove all punctuation, but I only included that hack as a simplified example. This approach would work, but a better solution is something like changing the delimiter for cin (c++) to add all the punctuation you want to strip and let >> do the job for you.

Then you get

// configure stream to treat punctuation as whitespace here
while (data >> data_str)
{
    if (data_str == "output")
    {
        counter++;
    }
}

and you're done.

Community
  • 1
  • 1
user4581301
  • 29,019
  • 5
  • 26
  • 45
1

Try

std::string tokenizer = std::string(1, data_str[i]);

std::string doesn't have a constructor that takes a single char. However, the constructor overload which we are using takes a char in the second argument, and creates an std::string containing a repetition of that char of length given by the first argument.

Fatih BAKIR
  • 2,499
  • 1
  • 13
  • 18