fin >> noskipws >> ch is always false - c++

I'm learning C++.
I'm trying to convert a text file like this one:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
...
Into a file like this one:
int grid[20][30] =
{
{ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
Both piece of text file are only and example to show you what I'm trying to do. The first text file doesn't generate the second text file.
I have written down this code:
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char *argv[])
{
if ((argc == 1) || (argc != 5)) {
cout << "Usage: format rows columns input_file output_file\n";
return 0;
}
// Number of rows in the image.
int rows = atoi(argv[1]);
// Number of columns in the image.
int columns = atoi(argv[2]);
// Character read from the input file.
char ch;
// Counter to create arrays of "columns" elements.
int colCount = 0;
// Counter for the number of rows added to the grid.
int rowCount = 0;
// Output file.
ofstream fout;
fout.open(argv[4], ios::out);
// Write the header to output file.
fout << "int grid[" << rows << "][" << columns << "] = {";
// Read input file.
fstream fin(argv[3], fstream::in);
while (fin >> noskipws >> ch)
{
if (colCount == 0)
fout << "\n{";
if ((!isspace(ch)) && ((ch == '1') || (ch == '0') || (ch == ','))) {
fout << ch;
colCount++;
}
if (colCount == columns) {
colCount = 0;
rowCount++;
if (rowCount != rows)
fout << "},";
}
}
fout << "}};\n";
fout.close();
return 0;
}
But it seems that it never enters into the main loop (while (fin >> noskipws >> ch)). I get this output in the text file:
int grid[365][484] = {}};
I'm compiling with g++ on Linux (Ubuntu) with the following command line:
g++ FormatMatrix.cpp -o format
What am I doing wrong?

Check if create/open your input stream 'fin' succeeded before you enter the while loop.

Related

How can I fix my C++ Connect4 checkGameOver Function

We have to make Connect4 in C++ as our last assignment for one of my classes. As of right now I have a fairly functional version. I had a really promising idea for a recursive solution for checking if the game is over but the issue is it only checks starting from the token it is starting at. For example if the most recently placed token has 3 of the same kind in any direction that is valid it works, but if it has 2 in one direction and 1 the opposite way it doesn't work. Does anyone have any ideas for how I could edit my function to incorporate the 2nd situation or should I just scrap it and rewrite it differently. Here is my code.
//TODO implement checking spots other than start
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
int runGame(int, int, int);
void promptUser(int**, int[], int, int, int);
void genRanMove(int**, int[], int, int);
bool checkGameOver(int**, int, int, int, int, int, int, int, int);
void showBoard(int**, int, int);
void playAgain();
using namespace std;
int main(int argc, char *argv[]) {
if (argc < 4) {
cerr << "Not enough input, syntax is 1/2 players, # columns, and # of rows" << endl;
exit(0);
}
if (argc == 4 && (argv[1][0] == '1' || argv[1][0] == '2') && (argv[2][0] >= '1' && argv[2][0] <= '9') && (argv[3][0] >= '1' && argv[3][0] <= '9')) {
cout << "\n\nYou have chosen to play Connect 4 in " << argv[1][0] << " player mode and with " << argv[2][0] << " columns and with " << argv[3][0] << " rows.\n" << endl;
}
else {
cerr << "Improper syntax, syntax is 1/2 players, # columns, and # of rows" << endl;
exit(0);
}
cout << "Welcome to Connect 4, each player will take a turn choosing a column to select, a metaphorical coin will fall down to the highest availible row.\nThe game ends when a player has gotten 4 of their coins in a row horizontally, vertically, or diagonally.\nPlayer 1 will always use 1's and Player 2 will always be 2's.\nThe AI will always be 3's.\nEmpty slots will be shown as 0's.\n\n" << endl;
srand(time(NULL));
int winner = runGame(argv[1][0] - '0', argv[2][0] - '0', argv[3][0] - '0');
if (winner == 1 || winner == 2) {
cout << "Winner was player # " << winner << endl;
}
else if (winner == 3)
cout << "You let the AI win :(" << endl;
else if (winner == -1)
cout << "The game ended in a tie" << endl;
playAgain();
}
/******************************************************
** Function: runGame
** Description: runsGame
** Parameters: gameMode columns rows
** Pre-Conditions:
** Post-Conditions: returns winning player, 1 or 2 for player # and 3 for ai
******************************************************/
int runGame(int gameMode, int columns, int rows) { //returns which player won
int holdPoints[2] = { 0, 0 };
switch (gameMode) {
case 1:
cout << "You have chosen to play against an AI" << endl;
break;
case 2:
cout << "You have chosen to play with another human player" << endl;
break;
}
int** board = new int*[columns];
for (int i = 0; i< columns; i++) {
board[i] = new int[rows];
}
for (int i = 0; i< columns; i++) {
for (int j = 0; j< rows; j++) {
board[i][j] = 0;
}
}
for (int i = 0; i< rows*columns/2; i++) { //check for number of possible moves in order to have a tie
showBoard(board, rows, columns);
promptUser(board, holdPoints, rows, columns, 1);
if (checkGameOver(board, holdPoints[0], holdPoints[1], 0, 1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 0, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 0, -1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, -1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 0, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, -1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 1, 0, 1, rows, columns)) {
return 1;
}
cout << "\n\n";
showBoard(board, rows, columns);
if (gameMode == 2) {
promptUser(board, holdPoints, rows, columns, 2);
if (checkGameOver(board, holdPoints[0], holdPoints[1], 0, 1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 0, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 0, -1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, -1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 0, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, -1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 1, 0, 2, rows, columns)) {
return 2;
}
}
else if (gameMode == 1) {
genRanMove(board, holdPoints, rows, columns);
if (checkGameOver(board, holdPoints[0], holdPoints[1], 0, 1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 0, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 0, -1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, -1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 0, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, -1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 1, 0, 3, rows, columns)) {
return 3;
}
}
//showBoard(board, rows, columns);
cout << "\n\n";
}
for (int i = 0; i < columns; i++) {
delete[] board[i];
}
delete[] board;
return -1; //signifies a tie
}
/******************************************************
** Function: promptUser
** Description: gets input from user for their turn, stores the resting place of their token in points
** Parameters: board and array to hold point,num columns
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void promptUser(int** board, int point[], int numRows, int numColumns, int playerNum) {
int col, lowZero;
lowZero = -1;
cout << "What column would you like to choose" << endl;
cin >> col;
if (col<0 || col > numColumns -1) {
cout << "The # you chose must be >=0 and <= " << numColumns-1 << endl;
promptUser(board, point, numRows, numColumns, playerNum);
}
//now need to find the lowest possible row in the given column that has a 0
for (int i = 0; i < numRows; i++) {
if (board[col][i] == 0)
lowZero = i;
}
if (lowZero != -1) {
board[col][lowZero] = playerNum;
cout << "Player " << playerNum << " dropped a token in column " << col << " that rested at row " << lowZero << endl;
point[0] = col;
point[1] = lowZero;
return;
}
else {
cout << "Column " << col << " was full, please pick a new one" << endl;
promptUser(board, point, numRows, numColumns, playerNum);
}
}
/******************************************************
** Function: genRanMove
** Description: gets random column from "ai", stores the resting place of their token in points
** Parameters: board and array to hold point
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void genRanMove(int** board, int point[], int numRows, int numColumns) {
cout << "AI is finding a column" << endl;
int col = rand() % numColumns;
int lowZero = -1;
for (int i = 0; i < numRows; i++) {
if (board[col][i] == 0)
lowZero = i;
}
if (lowZero != -1) {
board[col][lowZero] = 3;
cout << "AI dropped a token in column " << col << " that rested at row " << lowZero << endl;
point[0] = col;
point[1] = lowZero;
return;
}
//didnt find a row that works
genRanMove(board, point, numRows, numColumns);
}
/******************************************************
** Function: showBoard
** Description: prints he current gameboard
** Parameters: the board, numrows and numcolumns
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void showBoard(int** board, int numRows, int numColumns) {
for (int i = 0; i < numColumns; i++) {
for (int j = 0; j < numRows; j++) {
cout << board[j][i] << " ";
}
cout << endl;
}
}
/******************************************************
** Function: playAgain
** Description: gets info to play again
** Parameters: n/a
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void playAgain() {
int again;
int mode, rows, columns;
cout << "Would you like to play again? Type 1 if so." << endl;
cin >> again;
if (again) {
cout << "What mode? 1 for 1 player and 2 for 2 player" << endl;
cin >> mode;
cout << "How many rows?" << endl;
cin >> rows;
cout << "How many columns?" << endl;
cin >> columns;
if ((mode<=0 || mode >2) || rows<= 0 || columns<= 0) {
cout << "Improper inputs. Mode must be 1/2 and rows and columns must both be >0" << endl;
playAgain();
}
else {
runGame(mode, columns, rows);
}
}
}
/******************************************************
** Function: checkGameOver
** Description: checks if game is over by recursively checking spots around original
** Parameters: board, curr col, curr row, change col, change row, total found, and what number it is looking for in the board
** Pre-Conditions:
** Post-Conditions:
******************************************************/
bool checkGameOver(int** board, int currCol, int currRow, int changeCol, int changeRow, int totalFound, int numSearch, int numRows, int numColumns) {
if (totalFound == 4) //base case
return true;
if (currRow <0 || currRow >numRows - 1 || currCol<0 || currCol> numColumns - 1)
return false;
if (board[currCol][currRow] == numSearch)
totalFound++;
else
return false; // the checked index didnt contain the same # we wanted
return checkGameOver(board, currCol + changeCol, currRow + changeRow, changeCol, changeRow, totalFound, numSearch, numRows, numColumns);
}
... or should I just scrap it and rewrite it differently?
That's the option I'd be going for :-)
While a recursive solution may be clever, you're probably better off, for a game-space of this size, keeping the code simple and just checking every single possibility rather than trying to recurse out from the newly-populated cell(a).
You can do this in "specialist" chunks so you don't have to worry about going off the edge of the board at any point. To do this, you limit the starting cell for each type so that it ends on an edge cell of the board, something like (pseudo-code):
# Check four cells given start and direction.
def didWin(row, col, rdelta, cdelta):
# Check if start cell not populated.
if cell[row][col] == empty:
return false
# Check if any cell in sequence doesn't match.
for i = 1 to 3 inclusive:
if cell[row][col] != cell[row+rdelta*i][col+cdelta*i]:
return false
# Otherwise, it's a win
return true
def getWinner():
# Check all possible horizontals.
for row = 0 to 5 inclusive:
for col = 0 to 3 inclusive:
if didWin(row, col, 0, 1): # cdelta=1, right.
return cell[row][col]
# Check all possible verticals.
for col = 0 to 6 inclusive:
for row = 0 to 2 inclusive:
if didWin(row, col, 1, 0): # rdelta=1, down.
return cell[row][col]
# Check all right-downs.
for row = 0 to 2 inclusive:
for col = 0 to 3 inclusive:
if didWin(row, col, 1, 1): # r/cdelta=1, right-down.
return cell[row][col]
# Check all right-ups.
for row = 3 to 5 inclusive:
for col = 0 to 3 inclusive:
if didWin(row, col, 1, -1): # rdelta=1, cdelta=-1, right-up.
return cell[row][col]
# No winner.
return empty
(a) Another good reason for doing this is that, in an educational institution, they almost always value clarity of thought over cleverness. That clarity of thought will serve you well in the start of your career and, indeed, forty years into your career, such as where I am :-)

Knight's Tour Brute Force Recursion

I'm trying to write a program that allows the user to enter any coordinate on a chess board and complete the knight's tour using brute force recursion. I am getting an infinite loop and I have no idea why. This is in C++, and I have to write this only using brute force recursion. After entering the starting place for the knight, my console output window prints the current board after each move (only temporarily, for troubleshooting purposes), but according to my output, the move number is stuck at 1, and the program isn't trying any other moves. Any help is appreciated.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
void printBoard();
bool moveKnight(int col, int row, int movNum);
int totalMoves = 0;
int board[7][7] = { { 0 } };
int main()
{
cout << "Welcome to the Knight's Tour Program! Enter a starting place for the knight on a chess board to get started.\n";
int col;
int row;
int a;
int b;
while (1 == 1)
{
col = 0;
row = 0;
cout << "Enter column (0-7): ";
cin >> col;
cout << "Enter row (0-7): ";
cin >> row;
if (row < 0 || row > 7 || col < 0 || col > 7)
{
cout << "Invalid knight placement. Please try again.\n";
}
else
{
break;
}
}
int movNum = 1;
board[col][row] = movNum;
totalMoves++;
moveKnight(col, row, movNum);
if (moveKnight(col, row, movNum == true))
{
cout << "Tour finished! Total moves: " << totalMoves << endl;
printBoard();
cout << "\n\n";
}
system("pause");
return 0;
}
void printBoard()
{
cout << "Current board\n";
for (int i = 0; i < 8; i++)
{
for (int x = 0; x < 8; x++)
{
cout << setw(3) << board[i][x] << " ";
if (x == 7)
{
cout << "\n\n";
}
}
}
cout << "\n";
}
bool moveKnight(int col, int row, int movNum)
{
printBoard(); //just for troubleshooting
cout << "\n" << totalMoves << endl;
if (moveKnight(col, row, movNum) == false)
{
board[col][row] = 0; //if there are no available moves then set the current space to 0 and move back a spot
}
if (movNum == 64)
{
return true; //if tour complete return true
}
if (totalMoves % 10000 == 0)
{
printBoard(); //printBoard() every 10000 moves
}
if (col >= 0 && col <= 7 && row >= 0 && row <= 7 && board[row][col] == 0) //check if space is on board and if it is unoccupied
{
board[col][row] = movNum;
totalMoves++;
if (moveKnight(col + 1, row - 2, movNum + 1) != false)
moveKnight(col + 1, row - 2, movNum + 1);
else if (moveKnight(col + 2, row - 1, movNum + 1) != false)
moveKnight(col + 2, row - 1, movNum + 1);
else if (moveKnight(col + 2, row + 1, movNum + 1) != false)
moveKnight(col + 2, row + 1, movNum + 1);
else if (moveKnight(col + 1, row + 2, movNum + 1) != false)
moveKnight(col + 1, row + 2, movNum + 1);
else if (moveKnight(col - 1, row + 2, movNum + 1) != false)
moveKnight(col - 1, row + 2, movNum + 1);
else if (moveKnight(col - 2, row + 1, movNum + 1) != false)
moveKnight(col - 2, row + 1, movNum + 1);
else if (moveKnight(col - 2, row - 1, movNum + 1) != false)
moveKnight(col - 2, row - 1, movNum + 1);
else if (moveKnight(col - 1, row - 2, movNum + 1) != false)
moveKnight(col - 1, row - 2, movNum + 1);
else
return false;
}
}
If you look in the moveKnight() function, notice that the line if (moveKnight(col, row, movNum) == false) does a recursive call of the function no matter what the inputs are.
Whenever you use a recursive function, it must have what is called a base case, where a recursive call does not happen. Otherwise, the recursive calls will just keep going on until a stack overflow since one execution of the function will start another one which will start another one and so on..
By the way, the bunch of if statements in the function make no sense since you are calling a function and checking the output, and if it is true then you call the function a second time with the exact same arguments. Also, if you want an infinite loop that you will break later, there is no need for something like while(1 == 1). Use while(1) or while(true).
int board[7][7] = { { 0 } };
Chess board is 8 x 8, so you need 8 elements in the array (from 0 to up to and including 7, that's 8)
if (moveKnight(col, row, movNum == true))
You have syntax erros, the compiler will tell you about all this. In Visual Studio make sure warning level is set to 4. Then make sure the program is compiled with zero errors and zero warnings.
I would recommend writing a program which does not require user input. This will make it easier to debug the program and fix the logic.
Below is a simple recursion which moves the knight until the knight gets stuck at the end. You will have to further improve the logic so that it covers all the squares.
Make sure the recursive function is allowed to break. That's discussed in more detail in the other answer.
int board[8][8] = { 0 };
void printBoard()
{
cout << "Current board\n";
for(int i = 0; i < 8; i++)
{
for(int x = 0; x < 8; x++)
cout << board[i][x] << " ";
cout << "\n";
}
cout << "\n";
}
int test(int &row, int &col, int move_row, int move_col)
{
int r = row + move_row;
int c = col + move_col;
if(r >= 0 && r < 8 && c >= 0 && c < 8 && !board[r][c])
{
row = r;
col = c;
return 1;
}
return 0;
}
bool move_knight(int &row, int &col)
{
board[row][col] = 1;
printBoard();
system("pause");
if(!test(row, col, 1, 2))
if(!test(row, col, 1, -2))
if(!test(row, col, -1, 2))
if(!test(row, col, -1, -2))
if(!test(row, col, 2, 1))
if(!test(row, col, 2, -1))
if(!test(row, col, -2, 1))
if(!test(row, col, -2, -1))
return false;
move_knight(row, col);
return true;
}
int main()
{
int col = 0;
int row = 0;
move_knight(col, row);
system("pause");
return 0;
}

converting an array of integers to string

If I have an array that looks like
int digits[size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4}
I want to remove the leading zeros and to do so I'm attempting to convert the array of integers into a string (which is an array of chars).
My attempt looks like
string toString(int digits[], int size){
string number = " ";
for(int i = 0; i < size - 1; i++){
number[i] = digits[i];
}
return number;
}
which came out horribly broken.
I also can't simply remove all zeros, just the leading ones.
Also if I may dogpile another question here:
how can I identify if a string is numeric?
e.g
string number = "12a4"
cout << "not a number"
you can use C++11 function std::to_string() here is an example
#include <string>
#include <iostream>
int main()
{
int size = 15;
int digits[size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
std::string result = "";
for (int i = 0; i < size; i++)
{
if (!(digits[i] == 0 && result.size() == 0))
result += std::to_string(digits[i]);
}
std::cout << result << std::endl;
}
you can check if a string is numeric using this function
bool isNb(std::string str)
{
if (str.size() == 0)
return false;
for (int i = 0; i < str.size(); i++)
{
if (std::isdigit(str.at(i)) == false)
return false;
}
return true;
}
Instead of changing digits with your for loop, add them with
number += to_string(digits[i]);
Also, you can remove the toString line you have, and just use it as I put here.
As to your other question, just use a for loop to check each digit in the string and its ASCII value, if there is any whose ASCII value is less than 48 or greater than 57 then it's not a number.
Try the following way:
int i = 0;
while(digits[i] == 0) i++;
for (; i < size; i++)
result += to_string(digits[i]);
To answer your actual question (How to remove the leading zeros?) here a solution without strings:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
std::vector<int> x = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
// ...or if you insist on the array...
// int x[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
// std::vector<int> x = {x,x+15};
auto it = std::find_if_not(x.begin(),x.end(),[](int i){return i==0;});
std::vector<int> y{it,x.end()};
for (auto i : y) std::cout << i << " ";
}
prints:
1 2 3 0 4
You can use a string stream to convert from any type to string:
#include <sstream> //<-- ALLOWS USE OF std::stringstream
const int size = 15;
int digits[size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
std::stringstream ss; //<-- DECLARE STREAM
int k;
for (k = 0; k < size; ++k)
if (digits[k] != 0)
break; //FIND FIRST NON-0 INDEX
for (int i = k; i < size; ++i)
ss << digits[i]; //ADD TO THE STREAM s
std::cout<< ss.str() << std::endl; //PRINT STREAM
12304

Struct Array Indexes not being filled after first index

I have an input file with 3 fields on each line that are type: string, double, double. There are 15 lines with data.
The format of the input file data is:
Katmandu, -34, 28
cityName, lowTemp, highTemp
....
...
..
It's obvious that it's not getting the 3rd input on the line, based on the output.
Here is the code:
for (int index = 0; index < 15; index++)
{
getline(inFile, weatherInfo[index].city, ',');
inFile >> weatherInfo[index].low >> weatherInfo[index].high;
inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
For some reason this is my output:
Katmandu (-34, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
I know my program is able to read the other lines because when I add
inFile.ignore(20);
to the beginning of my statement it the loop it outputs
28
Perth (92, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
Output Code:
void ShowAll(int count) //Show entire data function
{
int x = 0; //loop through the index of city[], lowTemp[], highTemp[], and print them.
while (x < count)
{
cout << weatherInfo[x].city << " (" << weatherInfo[x].low << ", " << weatherInfo[x].high << ")" << endl;
x++;
}
cout << endl;
}
If the data in a line are separated by commas then you should use the following approach
#include <sstream>
//...
std::string line;
for ( int index = 0; index < 15 && std::getline( inFile, line ); index++)
{
std::istringstream is( line );
getline( is, weatherInfo[index].city, ',');
std::string field;
if ( getline( is, field, ',') ) weatherInfo[index].low = std::stod( field );
if ( getline( is, field, ',') ) weatherInfo[index].high = std::stod( field );
}
The problem with your code is that an error occurs when you are trying to read double values and a comma is encountered. In this case ths state of the stream will be erroneous and all other input will be ignored.
Also you should check what is the point representation for doubles in the locale you are using.

Algorithm ByteRun, decompression gone wrong, .bmp

I have a little problem with algorithm ByteRun(very similar to RLE). Well when i make the decompression smth go wrong and my output isn't the same as input. The orginal cookie is saved in format .bmp (24 pixels). The output should be our format eg. ".xd".
I saw (as far) only 4 options and it depends on how many pixels we have in width.
for 421 we have
for 422 we have
for 423 we have
and for 424 we have
and the original:
Tbh I thought that I consider padding but idk what makes my poor cookie broke. :( Please help me save the cookie. :D
#include <iostream>
#include <stdlib.h>
#include <fstream>
using namespace std;
struct colour // structure of every pixel BGR
{
unsigned char b;
unsigned char g;
unsigned char r;
};
unsigned int reading_and_writing_the_header(FILE *file_in, FILE *file_out, unsigned char header[])
{
unsigned int width = 0;
unsigned int height = 0;
unsigned int bite_for_pixel = 0;
unsigned int amount_of_pixels = 0;
unsigned int padding = 0;
unsigned int row = 0;
fread(header, 1, 54, file_in); // reading the header // 1=sizeof(unsigned int) = sizof(uni8_t)
fwrite(header, 1, 54, file_out); // wrting header
width = *(unsigned int*)&header[18];
height = *(unsigned int*)&header[22];
bite_for_pixel = *(unsigned int*)&header[28];
padding = width % 4; // counting padding
row = width * 3 + padding; // bites in a row
amount_of_pixels = height * row; // amount of bites after header
return amount_of_pixels;
}
void compression_ByteRun(FILE *file_in,FILE *file_out, unsigned int aop)
{
colour *q = new colour[aop];
fread(q, 1, aop, file_in);
int k = 0;
colour x, y;
int counter1 = 0;
int counter2 = 0;
char *the_same_colours = new char[4];
char *diffrent_colours = new char[128 * 3 + 1];
while (k < (aop / 3))
{
x = q[k];
y = q[k + 1];
if (x.r == y.r && x.b == y.b && x.g == y.g) //if the same R and B and G
{
if (counter1 == 126) // not sure about what exactly should be here
{
the_same_colours[0] = (counter1)*(-1);
fwrite(the_same_colours, 1, 4, file_out);
counter1 = 0;
}
if (counter2 != 0)
{
diffrent_colours[0] = counter2 / 3 - 1;
fwrite(diffrent_colours, 1, counter2 + 1, file_out);
counter2 = 0;
}
counter1++;
k++;
continue;
}
else // if we have diffrent colours side by side
{
if (counter1 != 0)
{
the_same_colours[0] = (counter1)*(-1);
the_same_colours[1] = x.b;
the_same_colours[2] = x.g;
the_same_colours[3] = x.r;
fwrite(the_same_colours, 1, 4, file_out);
counter1 = 0;
k++;
}
else
{
diffrent_colours[counter2 + 1] = x.b;
diffrent_colours[counter2 + 2] = x.g;
diffrent_colours[counter2 + 3] = x.r;
counter2 = counter2+ 3;
if (counter2 / 3 == 127) // same here, not sure about what exactly should be here
{
diffrent_colours[0] = counter2 / 3 - 1;
fwrite(diffrent_colours, 1, counter2 + 1, file_out);
counter2 = 0;
}
k++;
}
}
}
}
void decompression_ByteRun(FILE *file_in,FILE *file_out)
{
char x; // variavle where we keep how many colours we need 2 write
char y, z, o; // variables for comparing values
bool game_over; // variable for checking if the file isn't over
game_over = fread(&x, 1, 1, file_in);
while (game_over == true)
{
if (x >= 0) // if we had diffrent colours side by dide
{
for (int i = 1; i <= x * 3 + 3; i++)
{
fread(&y, 1, 1, file_in);
fwrite(&y, 1, 1, file_out);
}
game_over = fread(&x, 1, 1, file_in);
continue;
}
else // if we have the same colours
{
fread(&z, 1, 1, file_in);
fread(&o, 1, 1, file_in);
fread(&y, 1, 1, file_in);
for (int i = 1; i <= (-(x)+1); i++)
{
fwrite(&z, 1, 1, file_out);
fwrite(&o, 1, 1, file_out);
fwrite(&y, 1, 1, file_out);
}
game_over = fread(&x, 1, 1, file_in);
}
}
}
int main()
{
FILE *file_in;
FILE *file_out;
int number = 0;
char* name = new char;
char* name_out = new char;
unsigned char header[54];
unsigned int amount_of_pixels = 0;
cout << "Write input file: " << endl;
cin >> name;
cout << endl;
cout << "Write output file:" << endl;
cin >> name_out;
cout << endl;
cout << "What u wanna do (1- compression or 2- decompression ";
cin >> number;
file_in = fopen(name, "rb");
if (file_in == NULL)
{
cout << "Error we couldn't open that file.\n Contact our IT group 4 more help" << endl;
system("PAUSE");
exit(0);
}
file_out = fopen(name_out, "wb");
if (file_out == NULL)
{
cout << "Error we couldn't open that file.\n Contact our IT group 4 more help" << endl;
system("PAUSE");
exit(0);
}
switch (number)
{
case 1:
cout << "Compression Byterun" << endl;
amount_of_pixels = reading_and_writing_the_header(file_in, file_out, header);
compression_ByteRun(file_in, file_out, amount_of_pixels);
break;
case 2:
cout << "Decompression Byterun" << endl;
amount_of_pixels = reading_and_writing_the_header(file_in, file_out, header);
decompression_ByteRun(file_in, file_out);
break;
}
system("PAUSE");
return 0;
}