Outputting Issue with File Conversion - c++

This is a remake of a question I just asked a few minutes ago. Basically I want a line break to be displayed that is one less than the number of new line carriage returns. So if there are three new lines in a row, the line breaks should be two. Is there any way to do this?
while( infile.get( ch ) )
{
switch( ch )
{
case '\n':
outfile << "<br />";
break;
case '\t':
outfile << tab;
break;
case '&':
outfile << "&";
break;
case '<':
outfile << "<";
break;
case '>':
outfile << ">";
break;
case '"':
outfile << """;
break;
default:
outfile << ch;
break;
}
if( ch == '\n' )
{
inputLines++;
}
}
Sample output should look like this: https://gist.github.com/anonymous/b5a647913f83f796914c

This might work for you. Essentially it skips the first newline detected. If you have 3 newline input, you'll have 2 line breaks. Note that if you have only one newline, you'll just get a newline character (not a line break).
bool first_nl = true;
while( infile.get( ch ) )
{
switch( ch )
{
case '\n':
if ( first_nl ) {
outfile << "\n";
first_nl = false;
} else {
outfile << "<br />\n";
}
break;
case '\t':
outfile << tab;
break;
case '&':
outfile << "&";
break;
case '<':
outfile << "<";
break;
case '>':
outfile << ">";
break;
case '"':
outfile << """;
break;
default:
outfile << ch;
break;
}
if( ch == '\n' )
{
inputLines++;
} else {
first_nl = true;
}
}
Using this, you won't have to deal with any "peeking" at the next character.

To solve this problem, you will have to detect that you have "multiple of the same", which means building a statemachine of sorts.
A simple version, to cope only with what you are doing is to have a "peek-buffer";
#include <fstream>
#include <iostream>
using namespace std;
int buffer = 0;
int peek(ifstream &infile)
{
if (buffer) return buffer;
char ch;
if (!infile.get( ch ))
buffer = -1;
else
buffer = ch;
return buffer;
}
int get(ifstream &infile)
{
int ch = peek(infile);
buffer = 0;
cout << "ch = " << ch << endl;
return ch;
}
int main(int argc, char **argv)
{
ifstream infile(argv[1]);
ofstream outfile(argv[2]);
int ch;
while( (ch = get(infile)) != -1 )
{
int count = 0;
switch( ch )
{
case '\n':
while (peek(infile) == '\n')
{
count ++;
get(infile);
}
count--; // One less.
if (count <= 0) count = 1; // Assuming we want one output if there is only one.
for(int i = 0; i < count; i++)
{
outfile << "<br />";
}
break;
default:
outfile << (char)ch;
break;
}
}
}
I'm sure there are other clever ways to do this.

Related

Check whether a set of brackets consisting of parenthesis, square brackets, and Curly brackets are valid or not?

I have a small problem here: Our teacher asked us to write a program that checks whether parenthesis, square brackets, and Curly brackets are valid. eg: [[{{{(())}}}]] is a valid usage but ())), [[((]])) (the latter are interleaved here) are invalid.
Here is my try:
int main(){
string input;
cout << "Enter a text: "
cin >> input;
int nSquareBracketRight = count(s.begin(), s.end(), '[');
int nSquareBracketLeftt = count(s.begin(), s.end(), ']');
if(nSquareBracketRight != nSquareBracketLeft)
cout << "Invalid!" << endl;
else
cout << "Valid Usage!" << endl;
return 0;
}
It looks ok above but if the occurrences are equal but if a "Closing" one is in the smaller index then it is considered invalid eg: {}}{ Invalid.
Please help and thank you, guys!
This is the kind of situation that a stack is good for, such as std::stack, eg:
#include <iostream>
#include <string>
#include <stack>
using namespace std;
bool areBracketsValid(const string &input)
{
stack<char> stk;
for(string::size_type i = 0; i < input.size(); ++i)
{
char ch = input[i];
switch (ch)
{
case '(':
case '[':
case '{':
{
stk.push(ch);
break;
}
case ')':
case ']':
case '}':
{
if (stk.empty())
return false;
char openingCh = (ch == ')') ? '(' : (ch == ']') ? '[' : '{';
if (stk.top() != openingCh)
return false;
stk.pop();
break;
}
}
}
return stk.empty();
}
int main()
{
string input;
cout << "Enter a text: ";
cin >> input;
if (areBracketsValid(input))
cout << "Valid Usage!" << endl;
else
cout << "Invalid!" << endl;
return 0;
}
Live Demo
Using std::count is good but that is not what you need here in your program; You need something that is interested in the indexes moreover.
You can declare for each type of brackets a variable that holds the number of its occurrences
and inside a loop increment the target variable if it matches the tested character.
And right inside the loop after increment check whether the opening bracket number is smaller than the closing,
if so it is considered an invalid one eg: (()))(
As you can see above the number of opening and closing is OK but it is considered an invalid usage as the fact that a never a parenthesis begins with a closing one!
So break the loop signaling the invalid usage.
finally compare the number of opening and closing ones outside the loop, that is it because
inside a loop we can open n parenthesis so the checking is only after the loop ends to get the number of closing ones. eg:
(([[[{{{ cannot be checked inside the loop.
#include <iostream>
#include <string>
int main(){
std::string str;
std::cin >> str;
int nParR = 0, nParL = 0, nBrackR = 0,
nBrackL = 0, nCurlR = 0, nCurlL = 0;
for(auto i(0); i != str.length(); ++i){
switch(str[i]){
case '(':
nParR++;
break;
case ')':
nParL++;
break;
case '[':
nBrackR++;
break;
case ']':
nBrackL++;
break;
case '{':
nCurlR++;
break;
case '}':
nCurlL++;
break;
}
if(nParR < nParL || nBrackR < nBrackL ||
nCurlR < nCurlL){
std::cout << "Invalid usage!" << std::endl;
break;
}
}
if(nParR == nParL && nBrackR == nBrackL && nCurlR == nCurlL)
std::cout << "Valid usage!" << std::endl;
else
std::cout << "Invalid Usage!";
std::cout << std::endl;
return 0;
}
It is really easy to achieve: Let's say you have an input like this: ([{}]) it is considered correct isn't it? but ([)] is invalid.
In the correct one you can see in some point that element i is an opening bracket and element i + 1 is a closing bracket of the same family of brackets. Which is considered valid So the trick is to remove this subset brackets until the stack/vector is empty. If so then the whole input is correct otherwise is invalid.
Tip: inside a loop erase element i and element i + 1 if only and if element i is opening and element i + 1 is closing and element i and element i + 1 are of the same family eg: {}, [], ().
#include <iostream>
#include <string>
#include <vector>
int main(){
std::string str = "[({}{})]"; // valid
// std::string str = "["; // invalid
// std::string str = "[(])"; // invalid
// std::string str = "[({}{})]]"; // invalid
// std::string str = "[({}{}])"; // invalid
// std::string str = "{{}[{}]{(())}}"; // valid
// std::string str = "][(){}"; // invalid
std::vector<char> vecStr;
bool isDone = false;
for(auto i(0); i != str.length(); ++i)
vecStr.push_back(str[i]);
for(auto i(0); i != vecStr.size(); ++i)
std::cout << vecStr[i];
std::cout << std::endl;
for(auto i(0); i < str.length() / 2 && !isDone; ++i){
for(auto j(0) ; j < vecStr.size() - 1; ++j){
if(!vecStr.size()){
isDone = true;
break;
}
switch(vecStr[j]){
case '{':
if(vecStr[j + 1] == '}'){
vecStr.erase(&vecStr[j]);
vecStr.erase(&vecStr[j]);
}
break;
case '(':
if(vecStr[j + 1] == ')'){
vecStr.erase(&vecStr[j]);
vecStr.erase(&vecStr[j]);
}
break;
case '[':
if(vecStr[j + 1] == ']'){
vecStr.erase(&vecStr[j]);
vecStr.erase(&vecStr[j]);
}
break;
}
}
}
std::cout << "size: " << vecStr.size() << std::endl;
if(vecStr.size())
std::cout << "Invalid Input!" << std::endl;
else
std::cout << "valid Input!" << std::endl;
std::cout << std::endl;
return 0;
}
just switch uncommenting the input lines above and see the result. Or input it using std::cin.

How can I display this Sokoban board?

I'm new here, and I have a basic level of programming, and the problem is that I've been trying to display this Sokoban board for a week, and I don't know what to do anymore.
As I'm new here and I don't know very well how this forum works, I show you the part of my program that I consider important.
bool loadLevel(ifstream &file, tSokoban &sokoban, int level) { //Falta leer el nivel hasta que vuelva a leer Level
tGame game;
bool found = false;
string line;
int index, x = 0;
game.sokoban.ncol = 0;
game.sokoban.nrows = 0;
file >> line;
while (!file.eof())
{
if (line == "Level")
{
file >> index;
if (index == level)
{
found = true;
}
}
while (found && !file.eof())
{
if (found)
{
getline(file, line);//File reads "" , so I put it again so the program works
getline(file, line);
if (line.length() > game.sokoban.ncol)
{
game.sokoban.ncol = line.length();
}
for (int i = 0; i < line.size(); i++)
{
switch (line[i])
{
case '#':
sokoban.board[x][i] = Wall;
break;
case ' ':
sokoban.board[x][i] = Free;
break;
case '.':
sokoban.board[x][i] = GoalFree;
break;
case '*':
sokoban.board[x][i] = GoalBox;
break;
case '+':
sokoban.board[x][i] = GoalPlayer;
break;
case '#':
sokoban.board[x][i] = Player;
game.sokoban.playerX = x;
game.sokoban.playerY = i;
break;
case '$':
sokoban.board[x][i] = Box;
sokoban.boxCount++;
break;
}
}
x++;
sokoban.nrows++;
getline(file, line);
}
else
{
cout << "Could not find the level you were looking for..." << endl;
}
}
}
return found;
}
void draw(const tGame &game){
system("cls");
cout << "File: " << game.fileName << endl;
cout << "Level " << game.curLevel << endl;
cout << endl;
cout << endl;
for (int i = 0; i < game.sokoban.ncol; i++)
{
for (int f = 0; f < game.sokoban.nrows; f++)
{
drawTile(game.sokoban.board[i][f]);
}
cout << endl;
}
cout << game.numMoves;
}
void drawTile(tTile tile){
switch (tile)
{
case Free:
backgroundColor(1);
cout << " ";
break;
case Wall:
backgroundColor(3);
cout << " ";
break;
case GoalFree:
backgroundColor(7);
cout << "..";
break;
case GoalBox:
backgroundColor(8);
cout << "**";
break;
case GoalPlayer:
backgroundColor(11);
cout << "++";
break;
case Player:
backgroundColor(11);
cout << "00";
break;
case Box:
backgroundColor(13);
cout << "()";
break;
}
}
My file just contains one level, which is in this format:
Level 0
###################
##### ###########
#####$ ###########
##### $###########
### $ $ ##########
### # ## ##########
# # ## ##### ..#
# $ $ ..#
##### ### #### ..#
##### #########
###################
The problem is that when the program reads the file and has to display its contents, it just doesn't, and I don't know where the problem is, so I'm desperate now. If anyone could help me with this I would appreciate it very much :). Thank you all.

Trouble with whole sentence manipulation

Im making a pig latin converter, I can get it to manipulate one word and need it to convert whole sentences, making each word outputted in pig latin, below is my code:
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;
bool isVowel (char);
string rotate(string);
string plString(string);
int main()
{
string str;
cout <<"Enter a sentence: ";
getline (cin, str);
cout << endl;
cout << str <<" in pig latin - " << plString(str) << endl;
ifstream infile;
infile.open("input.txt");
infile >> str;
while(infile)
{
cout << plString(str) << " ";
infile >> str;
}
cout << endl;
}
bool isVowel (char ch)
{
switch (ch)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'Y':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'y':
return true;
default:
return false;
}
}
string rotate(string str)
{
string::size_type len = str.length();
string str1;
str1 = str.substr(1, len - 1) + str[0];
return str1;
}
string plString(string str)
{
string::size_type len;
bool vowel;
string::size_type counter;
if (isVowel (str[0]))
str = str + "way";
else
{
str = str + "";
str = rotate(str);
len = str.length();
vowel = false;
for (counter = 1; counter < len - 1; counter++)
if (isVowel (str[0]))
{
vowel = true;
break;
}
else
str = rotate(str);
if(!vowel)
str = str.substr(1,len) + "way";
else
str = str + "ay";
}
return str;
}
any advice on how to get this to do full sentences would be greatly appreciated!
You would need to split your string into words (splitting by white space delimiter). Maybe this would help if you insert it after the getline call instead of the " in pig latin - " line:
char delimiter = ' ';
string::size_type i = 0;
string::size_type j = str.find(delimiter);
while (j != string::npos) {
string word = str.substr(i, j-i);
std::cout << plString(word) << std::endl;
i = ++j;
j = str.find(delimiter, j);
if (j == string::npos) {
word = str.substr(i, s.length());
std::cout << plString(word) << std::endl;
}
}

Comparing strings in a 2D array to user input

I'm trying to get the user to choose a team (names are contained in 2D array), type the desired name/team, then use a for loop to compare the user's typed word with the words of a 2D array, and use that loop to access each string in the array:
#include <string>
#include <iostream>
#include <string.h>
int main(int argc, char* argv[]){
char cPlaychar[10][15] = { "BlackFurs", "EppiGods", "FairyDusters",
"Dwarvin", "Bloods", "Cryptics", "ArcAngels",
"DarkVillians", "Heroiteks", "Mass", };
char cKeyInput[15];
int results[10];
std::cout << "Please select a character
by typing the name and pressing enter" << std::endl;
std::cin >> cKeyInput;
for(int Array = 0; Array < 10; Array++){
switch (Array){
case '0':
results[0] = strcmp(cPlaychar[Array], cKeyInput);
if (results[0] = 0){
std::cout << "you have picked the first char";
}
break;
case '1': results[1] = strcmp(cPlaychar[Array], cKeyInput);
if (results[1] = 0){
std::cout << "you have picked the secound char";
}
break;
case '2':results[2] = strcmp(cPlaychar[Array], cKeyInput);
if (results[2] = 0){
std::cout << "you have picked the third char";
}
break;
case '3':results[3] = strcmp(cPlaychar[Array], cKeyInput);
if (results[3] = 0){
std::cout << "you have picked the fourth char";
}
break;
case '4':results[4] = strcmp(cPlaychar[Array], cKeyInput);
if (results[4] = 0){
std::cout << "you have picked the fith char";
}
break;
case '5':results[5] = strcmp(cPlaychar[Array], cKeyInput);
if (results[5] = 0){
std::cout << "you have picked the sixth char";
}
break;
case '6':results[6] = strcmp(cPlaychar[Array], cKeyInput);
if (results[6] = 0){
std::cout << "you have picked the seventh char";
}
break;
case '7':results[7] = strcmp(cPlaychar[Array], cKeyInput);
if (results[7] = 0){
std::cout << "you have picked the eighth char";
}
break;
case '8':results[8] = strcmp(cPlaychar[Array], cKeyInput);
if (results[8] = 0){
std::cout << "you have picked the ninth char";
}
break;
case '9':results[9] = strcmp(cPlaychar[Array], cKeyInput);
if (results[9] = 0){
std::cout << "you have picked the tenth char";
}
break;
} // end of switch
} // end of for
system("pause");
return 0;
}
first you can put
using namespace std ;
in the beginning and remove all (std::)
second in if (results[ ] = 0) this must be if (results[ ] == 0)
third i don't know why you use this method , you can do it easily like this
string names[] = {"a","b"} ;
string num[] = { "first", "second" } ;
string input;
cin >> input;
for (int i = 0; i < 2; ++i)
{
if (input == names[i])
cout << "you choose" << num[i] << endl;
}
but if you want 2d array you can do this
char names[2][2] = { "a", "b" };
char num[2][7] = { "first", "second" };
char input[2];
cin >> input ;
for (int i = 0; i < 2; ++i)
{
if (!strcmp(input,names[i]))
cout << "you choose " << num[i] << endl;
}

Program is ignoring input

I'm trying to write a simple brainfuck interpreter in C++. It works great so far, but it ignores the character input command (',').
The Interpreter:
#include <iostream>
#include <fstream>
#include <windows.h>
using namespace std;
#define SIZE 30000
void parse(const char* code);
int main(int argc, char* argv[])
{
ifstream file;
string line;
string buffer;
string filename;
cout << "Simple BrainFuck interpreter" << '\n';
cout << "Enter the name of the file to open: ";
cin >> filename;
cin.ignore();
file.open(filename.c_str());
if(!file.is_open())
{
cout << "ERROR opening file " << filename << '\n';
system("pause");
return -1;
}
while (getline(file, line)) buffer += line;
parse(buffer.c_str());
system("pause");
return 0;
}
void parse(const char* code)
{
char array[SIZE];
char* ptr = array;
char c;
int loop = 0;
unsigned int i = 0;
while(i++ < strlen(code))
{
switch(code[i])
{
case '>': ++ptr; break;
case '<': --ptr; break;
case '+': ++*ptr; break;
case '-': --*ptr; break;
case '.':
cout << *ptr;
break;
case ',':
cin >> *ptr;
break;
case '[':
if (*ptr == 0)
{
loop = 1;
while (loop > 0)
{
c = code[++i];
if (c == '[') loop ++;
else if (c == ']') loop --;
}
}
break;
case ']':
loop = 1;
while (loop > 0)
{
c = code[--i];
if (c == '[') loop --;
else if (c == ']') loop ++;
}
i --;
break;
}
}
cout << '\n';
}
The UtraSimple brainfuck code that breaks everything:
,.
Does anyone know what causes it to skip the input character?
I'd be looking at this for a start:
unsigned int i = 0;
while(i++ < strlen(code)) // increments i NOW !
{
switch(code[i]) // uses the incremented i.
The first character that will get processed there will be code[1], not code[0].
So the program ",." will first process . then \0 (end of string) hence there will be no input command , processed.
You can see this if you change the code as follows:
unsigned int i = 0;
while(i++ < strlen(code))
{
cout << "DEBUG [" << i << ":" << (int)code[i] << ":" << code[i] << "]\n";
switch(code[i])
and you'll see:
DEBUG [1:46:.]
DEBUG [2:0: ]
You need to hold off on incrementing i until after you're finished with it.