Write a program that takes as its input a text file that contains some C++ code.
ID: 3680139 • Letter: W
Question
Write a program that takes as its input a text file that contains some C++ code. Your program should determine if all brackets within the text file are nested with the exception of those appearing within comments and quoted strings. When your program detects a mismatched pair, it should print a message indicating the location (line numbers and column numbers) of the mismatch. If all pairs are matched, the program should indicate that at the end.
You can write your own implementation of a data structure, use an implementation developed in class, or a container from the C++ Standard Library
Your program should read the input text from a file. The skeleton program that is included here has code to read a text file line by line. This code can take the file name from the command line or ask the user. Note that code running within Visual Studio considers the project directory as the default directory in which to open files.
You have been supplied with a brackets_check.cpp C++ source file. The file is complete and should compile cleanly. This file has code to read a text file and should be used as a starting point for your code:
// brackets_check.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <cassert>
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[]) {
string filename;
if (argc >= 2) {
filename = argv[1]; // command line arguments are given. The first argument is the filename
}
else {
cout << "Enter name of file to check: ";
cin >> filename;
}
cout << "File to check:" << filename << endl;
ifstream infile(filename);
if (!infile) {
cout << "That file does not exist" << endl;
return (-1); // end the program
}
string line;
while (getline(infile, line)) {
cout << line << endl;
}
infile.close();
system("pause");
return(0);
}
Explanation / Answer
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <stack>
#include <string>
typedef std::stack<char> Brackets;
void pushOpeningBrackets(Brackets& opening, char ch)
{
if (ch == '{')
opening.push('{');
else if (ch == '(')
opening.push('(');
else if (ch == '[')
opening.push('[');
}
bool errorsFound(Brackets& stack, char openingBracket, char closingBracket)
{
// unmatched?
if (stack.empty())
{
std::cerr << "Unmatched " << closingBracket;
return true;
}
char topBracket = stack.top();
stack.pop();
// not a match?
if (topBracket != openingBracket)
{
if (topBracket == '{')
std::cerr << "Expected } but found " << closingBracket;
else if (topBracket == '(')
std::cerr << "Expected ) but found " << closingBracket;
else if (topBracket == '[')
std::cerr << "Expected ] but found " << closingBracket;
return true;
}
return false;
}
bool bracketsMatch(std::istream &in) {
std::stack<char> expectedDelimiters;
int lineNum = 0;
std::string line;
while (std::getline(in, line)) {
lineNum++;
size_t pos = 0;
while (std::string::npos != (pos = line.find_first_of("(){}[]", pos))) {
int colNum = pos + 1;
switch (line[pos]) {
case '(': expectedDelimiters.push(')'); break;
case '{': expectedDelimiters.push('}'); break;
case '[': expectedDelimiters.push(']'); break;
case ']':
case '}':
case ')':
if (expectedDelimiters.empty()) {
std::cout << "Mismatched " << line[pos]
<< " at line " << lineNum << ", col " << colNum
<< std::endl;
return false;
}
if (line[pos] != expectedDelimiters.top()) {
std::cout << "Expected " << expectedDelimiters.top()
<< ", found " << line[pos]
<< " at line " << lineNum << ", col " << colNum
<< std::endl;
return false;
}
expectedDelimiters.pop();
}
pos = colNum;
}
}
// Should check for a possible input error here, but I didn't bother.
if (!expectedDelimiters.empty()) {
std::cout << "Expected " << expectedDelimiters.top()
<< " at end of file" << std::endl;
return false;
}
return true;
}
int main(int argc, const char *argv[])
{
std::cout << "Enter a text file name: ";
std::string filename;
std::getline(std::cin, filename);
std::ifstream inFile(filename.c_str(), std::ios::in);
if (!inFile) return EXIT_FAILURE;
Brackets stack;
std::string fileLine;
while (inFile >> fileLine)
{
for (char ch : fileLine)
{
pushOpeningBrackets(stack, ch);
if (ch == '}')
{
if (errorsFound(stack, '{', '}'))
{
return EXIT_SUCCESS;
}
}
else if (ch == ')')
{
if (errorsFound(stack, '(', ')'))
{
return EXIT_SUCCESS;
}
}
else if (ch == ']')
{
if (errorsFound(stack, '[', ']'))
{
return EXIT_SUCCESS;
}
}
}
}
// checks for missing bracket or full match
if (!stack.empty())
{
char topBracket = stack.top();
stack.pop();
if ('{' == topBracket)
std::cerr << "Missing }";
else if ('(' == topBracket)
std::cerr << "Missing )";
else if ('[' == topBracket)
std::cerr << "Missing ]";
}
else
std::cout << "All brackets match!";
std::ifstream f;
std::istream &in = (argc > 1) ? (f.open(argv[1]), f) : std::cin;
if (!in) {
std::cerr << argv[0] << ": " << argv[1] << ": "
<< std::strerror(errno) << std::endl;
return 2; // A rather arbitrary error code
}
return bracketsMatch(in) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.