0

I have a file which call text.cpp. My mission was read from the file.

text.cpp file (inside the file)

#include <iostream>     
#include <cstring>
#include <ctype.h>
#include "program.h"
#include "binarytree.h" 
#include "linkedlist.h"

When i detect

 '#' symbol

the system will start looping, if it detect '<' & '"' symbol, it will print out the remain word. Example output : iostraem

I can detect '<' symbol and print the output success. But when i detect '"' symbol, i can print remain word (program.h), but it will follow 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫 behind the word.

May i know whats wrong of my code?

My code was below:

 #include <iostream>
    #include <string>
    #include <fstream>

    using namespace std;

    int main()

    {   char temPlate[100];
        char FileName[20];


    cout << "Enter Filename:" ;
    cin >> FileName;

    fstream read(FileName);
    if (read.is_open())
    {
        while(!read.eof())
        {
        read.getline(temPlate, 100);

            for (int k = 0; k < 100 ;k++)
            {
                if(temPlate[k] == '#')
                {
                    for(int i = 0; i < 100; i++)
                    {
                        if(temPlate[i] == '<' ||  temPlate[i] == '"')
                        {
                            for (int j = i+1; j < 100; j++)
                            {
                                if(temPlate[j] == '>' || temPlate[j] == '"')
                                {
                                    break;

                                }
                                cout << temPlate[j];

                            }
                            cout  <<endl;
                        }       
                    }
                 }
            }
        }
    }

    else
    {
        cout << "File does not exist, press enter to exit the program." <<  endl;
        system("pause");
        exit(EXIT_SUCCESS);

    }
    system("pause");

}

Output:

Enter FileName: text.cpp
iostream
cstring
ctype.h
program.h
 ype.h
binarytree.h
 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
linkedlist.h
 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
rorypicko
  • 4,194
  • 3
  • 26
  • 43
  • 1
    Why all the nested loops? There should just be one loop, scanning the text; remember which state you are in (i.e. outside a <> or "", or inside one), and print or not print accordingly. – Scott Hunter Sep 04 '13 at 15:25
  • 1
    Of course temPlate is null-terminated. istream::getline() null terminates the string. That's sort of the opposite of the problem -- the terminator is emitted, but never handled. – Sneftel Sep 04 '13 at 15:26
  • You are writing far more code than you need to accomplish this task. – Zac Howland Sep 04 '13 at 15:29

5 Answers5

3

Proximally, it's because you're scanning the entire buffer, not just the portion of it that was actually read in during the last getline().

But on a more fundamental level, it's because you're using character arrays instead of strings. C++ strings are there for many reasons, but one of the biggies is to avoid the many bugs associated with fixed-size buffers.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
0

Your line:

for(int i = 0; i < 100; i++)

should be:

for(int i = k+1; i < 100; i++)
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
0

You shouldn't use:

while(!read.eof())

Because the EOF bit is only set when you read after the last character in the file. For more information take a look at this thread: Why is iostream::eof inside a loop condition considered wrong?

Community
  • 1
  • 1
ThunderStorm
  • 766
  • 8
  • 24
0

Use while (std::getline(stream, line)) instead of while(!stream.eof()) and also avoid using C-style strings ~> use std::string objects instead.

Parsing the file line by line could look like this:

std::string filename;
std::cout << "Enter Filename: ";
std::cin >> filename;

std::ifstream read(filename.c_str());
if (read.is_open())
{
    std::string line;
    while (std::getline(read, line))
    {
        // skip empty lines:
        if (line.empty())
            continue;
        ...

Now instead of your "procedural" approach, processing of every line could look like this:

std::size_t pos = line.find("#include");
if (pos != std::string::npos)
    processInclude(line.substr(pos + 8));

and to avoid "cooking spaghetti code" it would be neat to sometimes extract some functionality into the standalone function rather than nesting another scope (if(){ for(){ if(){ for(){ ...):

void processInclude(std::string line)
{
    std::string filename;
    for (size_t i = startPos; i < line.size(); ++i)
    {
        if (line[i] == '<')
        {
            std::getline(std::istringstream(line.substr(i + 1), filename, '>');
            break;
        }
        else if (line[i] == '"')
        {
            std::getline(std::istringstream(line.substr(i + 1), filename, '"');
            break;
        }
    }
    if (!filename.empty())
        std::cout << filename << std::endl;
}

Hope this helps or makes you look at your code in a bit different way at least :)

LihO
  • 41,190
  • 11
  • 99
  • 167
0

This is really way more complicated than it needs to be. You might consider something like this:

#include <iostream>
#include <string>
#include <fstream>

int main()
{   
    std::string inputFilename;
    std::cout << "Enter Filename:";
    std::cin >> inputFilename;

    std::ifstream inputFile(inputFilename);
    if(inputFile)
    {
        std::string line;
        while(std::getline(inputFile, line))
        {
            if(line.find('#') != std::string::npos)
            {
                size_t startPos = line.find_first_of("<\"");
                size_t endPos = line.find_last_of(">\"");
                if(startPos != std::string::npos && endPos != std::string::npos)
                {
                    //advance start to after the < or "
                    ++startPos;
                    //sanity check just in case the line was ill formed
                    if(startPos < endPos)
                    {
                        std::cout << line.substr(startPos, endPos - startPos) << std::endl;
                    }
                }
            }
        }
    }
    else
    {
        std::cout << "File '" << inputFilename << "' does not exist." <<  std::endl;
    }
    return 0;
}
Retired Ninja
  • 4,785
  • 3
  • 25
  • 35