I decided to make a program that is looking for TODO: in files. Here is the code:

#include <iostream> #include <fstream> #include <cstdlib> using namespace std; ifstream inFile; const int SIZE = 60; int i,d; string todo[200]; int main() { char filename[SIZE]; string filecontents; cout <<"Place this executable to source folder" << endl <<"and enter filename to start search" << endl <<"filename can't start from space" << endl <<"Maximum count of TODOs is 200."<< endl <<"Maximum size is 60 symbols. Enter q to quit." << endl; while (cin.getline(filename, SIZE)) { if (filename[0] == 'q') { cout << "Terminating...\n"; exit(EXIT_SUCCESS); } else if (filename[0] != ' ') { if (filename[0] != '\n') { inFile.open(filename); if (!inFile.is_open()) { cout << "Can't open file called " << filename << endl; } else { int count = 1; string temp; cout << "Opened file called " << filename << endl << "Searching for todos..." << endl; while (getline(inFile, temp)) { filecontents += temp + '\n'; } while (i < filecontents.size()) { if (filecontents[i] == 'T') { if (filecontents[i+1] == 'O') { if (filecontents[i+2] == 'D') { if (filecontents[i+3] == 'O') { if (filecontents[i+4] == ':') { string temp = ""; char temp2; int temp3 = i + 5; while (temp2 != '\n') { temp += filecontents[temp3]; //TODO: test todo m8 temp2 = filecontents[temp3+1]; ++temp3; } ++d; todo[d] = temp; temp = ""; cout << "Found todo: " << todo[d] << endl; } } } } } i++; } } } else cout << "Please enter correct filename according to rules:\n"; // TODO: another todo as always } else cout << "Please enter correct filename according to rules:\n"; inFile.close(); d = 0; cout<< "Please enter filename: "; } return 0; } 

When I run this compiled program on my own source code, it only reads the first TODO and only once. How can this be fixed? Or am I just blind and do not see the obvious?
Compiler: Clang ++ LLVM Compiler
System: Fedora 23

  • That would seem to be the simplest case. The program searches for TODO in text files. But I want to draw attention to the fact that such a “simple” problem can be tripped several times. Starting with the fact that the original file encoding may be different. Yes, yes, yes, I saw Unicode-encoded files * .c and * .cpp. Moreover, a simple and stupid code can also stumble on Russian-language CP1251 texts. The character encoding 'I' corresponds to the character 0xFF, which, as some think, marks the end of the file (EOF) ... etc. Maybe even with ++ is not the best language for working with text strings and it is better to try something else? - gecube

1 answer 1

This is not the case with this code. Starting with global variables. Since it searches for invalid TODOs (first, the colon is not needed, and secondly, it will find SOMETODO: in the comments, and TODO: as a label, and a variable ending in TODO in the ternary operator, etc.) With an incomprehensible limit on the number of rows found. And ending with noodles.

But even considering the search for only substrings without context, all this can be written more beautifully, more clearly and more conveniently for debugging:

 const char TODO[] = "TODO:"; static size_t substring_count(const char * where, const char * what, size_t what_length) { size_t count = 0; const char * ptr = strstr(where, what); while (ptr) { count++; ptr = strstr(ptr + what_length, what); } return count; } int main() { size_t todos = 0; std::vector<std::string> lines; std::ifstream inFile; std::string temp; inFile.open("123.txt"); while (std::getline(inFile, temp)) { size_t todo_count = substring_count(temp.c_str(), TODO, sizeof(TODO) - 1); if (todo_count) { todos += todo_count; lines.push_back(temp); } } inFile.close(); std::cout << "Found " << todos << " TODO in " << lines.size() << " lines." << std::endl; } 
  • Wow, I forgot about the vector when I wrote it, I did not hear about size_t at all, and about strstr () too. What is called done on the basis of their knowledge: D. Well, you have to read about vectors at least to read ... And so thanks ... - cheloca