3

Just like the title says, I've been working on a fairly large program and have come upon this bug. I'm also open to alternatives for searching a file for a string instead of using . Here is my code narrowed down:

istreambuf_iterator<char> eof;
ifstream fin;
fin.clear();

fin.open(filename.c_str());

if(fin.good()){
 //I outputted text to a file to make sure opening the file worked, which it does
}

//term was not found.
if(eof == search(istreambuf_iterator<char>(fin), eof, term.begin(), term.end()){
   //PROBLEM: this code always executes even when the string term is in the file.
}

So just to clarify, my program worked correctly in Linux but now that I have it in a win32 app project in vs2010, the application builds just fine but the search function isn't working like it normally did. (What I mean by normal is that the code in the if statement didn't execute because, where as now it always executes.)

NOTE: The file is a .xml file and the string term is simply "administration."

One thing that might or might not be important is to know that filename (filename from the code above) is a XML file I have created in the program myself using the code below. Pretty much I create an identical xml file form the pre-existing one except for it is all lower case and in a new location.

void toLowerFile(string filename, string newloc, string& newfilename){
  //variables
  ifstream fin;
  ofstream fout;
  string temp = "/";
  newfilename = newloc + temp + newfilename;
  //open file to read
  fin.open(filename.c_str());
    //open file to write
    fout.open(newfilename.c_str());
    //loop through and read line, lower case, and write
    while (fin.good()){
      getline (fin,temp);
        //write lower case version
        toLowerString(temp);
        fout << temp << endl;
    }
    //close files
    fout.close();
    fin.close();
}

void toLowerString(string& data){
    std::transform(data.begin(), data.end(), data.begin(), ::tolower);
}
War Gravy
  • 1,543
  • 3
  • 20
  • 32
  • 4
    My guess is line endings. Your search term contains a \n and the file on windows contains \r\n -- which is not a match. – Timbo Jan 01 '14 at 00:31
  • Thanks Timbo, but unfortunately this isn't the problem. My search term is just a string without the \n and it's in the middle of a line in an xml file. – War Gravy Jan 01 '14 at 00:39
  • One thing I would check is compiler settings to see if term is actually char versus wchar_t string. – Richard Chambers Jan 01 '14 at 01:11
  • @Richard thanks I'm trying that now. I'm new to vs2010 so I'm going to google how to check my compiler settings. – War Gravy Jan 01 '14 at 01:42
  • Okay I'm currently working with char instead of wchar. I am new to this concept of wchar and char so I looked at this post: http://stackoverflow.com/questions/402283/stdwstring-vs-stdstring which I felt explained it well. Do I want to switch my program to use wstring instead of string? – War Gravy Jan 01 '14 at 01:52
  • Okay so I have just turned off wchar in the compiler settings under c/c++ language and that didn't solve the problem. – War Gravy Jan 01 '14 at 02:00
  • Double-check `term` contains what you think it contains. If it's empty, search will always succeed. – n. m. could be an AI Jan 01 '14 at 08:43
  • `wchar_t` is not an issue. Write standard C++, use both `char` and `wchar_t` exactly like you would on other platforms, don't use tricks like _tmain or TCHAR, suffix WinAPI functions and types with A or W explicitly as appropriate, and you should be all set. – n. m. could be an AI Jan 01 '14 at 08:51

2 Answers2

3

I'm afraid your code is invalid - the search algorithm requires forward iterators, but istreambuf_iterator is only an input iterator.

Conceptually that makes sense - the algorithm needs to backtrack on a partial match, but the stream may not support backtracking.

The actual behaviour is undefined - so the implementation is allowed to be helpful and make it seem to work, but doesn't have to.

I think you either need to copy the input, or use a smarter search algorithm (single-pass is possible) or a smarter iterator.

(In an ideal world at least one of the compilers would have warned you about this.)

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • Thank you, I'm currently looking at using a different search or iterator and then I will reply with the code. – War Gravy Jan 02 '14 at 21:06
1

Generally, with Microsoft's compiler, if your program compiles and links a main() function rather than a wmain() function, everything defaults to char. It would be wchar_t or WCHAR if you have a wmain(). If you have tmain() instead, then you are at the mercy of your compiler/make settings and it's the UNICODE macro that determines which flavor your program uses. But I doubt that char_t/wchar_t mismatch is actually the issue here because I think you would have got an warning or error if all four of the search parameters didn't use the same the same character width.

This is a bit of a guess, but try this:

if(eof == search(istreambuf_iterator<char>(fin.rdbuf()), eof, term.begin(), term.end())
jwdonahue
  • 6,199
  • 2
  • 21
  • 43
  • Thank you. Unfortunately still a no go, but after the responses I'm getting I'm going to edit my original question and add something I feel is important which I didn't realize before. I created a win32 app project (non empty) without any bells and whistles checked so my main is _TWinMain. Also the file I'm reading I create in the program myself. I tried your solution with both WChar on and off and still nothing. – War Gravy Jan 01 '14 at 02:18