Fstream gives error when reused on a file - c++

I have two text files.
Original Output:
Log.txt
Joe hello
Joe gargabash
Joe random unnecessary text
Hello
How are you?
Log2.txt is another text file that is initially blank.
When I run this code, it succesfully copies all of the lines that don't start with Joe. However, I want to copy the text back to the original .txt. When I uncomment out the selection I commented to try to do that, I get errors. Anyone know what i'm doing wrong? Thanks so much for reading all of this mess.
For clarification, the bool STRINGCONTAINS(int, char, char, int) checks if a char array matches with another char array.
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
using namespace std;
bool STRINGCONTAINS(bool CaseSensitive, //If this is true, we are checking a case sensitive string, if it's false, we're not.
char * input1, // First string [Type: Char Array]
char * input2, //Second String [Type: Char Array]
int MAXSTRINGLENGTH) // Integer representing max possible length of string.
{
if (CaseSensitive)
{
for(int i=0;i<MAXSTRINGLENGTH;i++)
{
if (*input1 == *input2)
{
input1++;
input2++;
} else
{
return 0;
}
}
} else
{
int char1, char2;
for(int i=0;i<MAXSTRINGLENGTH;i++)
{
char1 = *input1;
char2 = *input2;
if (char1 == char2 || char1 == (char2+32) || char2 == (char1+32))
{
input1++;
input2++;
} else
{
return 0;
}
}
}
return 1;
}
int main() {
int input;
char * loadedline = new char[192];
ifstream log;
ofstream templog;
log.open("log.txt");
templog.open("log2.txt");
while(log.getline(loadedline,sizeof(log)))
{
if (!STRINGCONTAINS(0,loadedline,"joe",3))
{
cout << loadedline << endl;
templog << loadedline << endl;
}
}
log.close();
templog.close();
/*ifstream templog2;
ofstream log2;
templog2.open("log2.txt");
log2.open("log.txt");
while(templog2.getline(loadedline,sizeof(templog2)))
{
log2 << loadedline << endl;
}
templog2.close();
log2.close;*/
delete[] loadedline;
cin >> input;
return 0;
}

The error in your program is that you are missing a parenthesis in your log2.close.
Change it to log2.close(); and it will run!

Related

C++ function `getline()` doesn't work correctly for char[]

I need to extract the first 150 characters from a line and save them in a char[] array (no strings allowed). My code below doesn't work and i just can't find the reason why:
#include <ifstream>
#include <iostream>
using namespace std;
int main()
{
ifstream myFile;
myFile.open("message.txt");
if(!myFile.is_open()) cout<<"error"; //added this after edit
const int SIZE = 151;
char buffer[SIZE]={};
while(myFile.getline(buffer, 151)){
buffer[150]='\0';
cout<<buffer<<endl;
}
myFile.close();
}
Here's a snippet of "message.txt":
abcdefg
hijklmn
opqrstuv
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
hello
It simply prints out nothing. The file "message.txt" exists and has several lines of characters in it. Where am I wrong?
EDIT: if the characters on a line are less than 150, they should all be read. If they are more than 150, the rest should be ignored.
If you are trying to read the first 150 characters of the 1st line, then you don't need the while loop. And you don't need to null-terminate the buffer manually, istream::getline() will do that for you, eg:
#include <ifstream>
#include <iostream>
using namespace std;
int main()
{
ifstream myFile("message.txt");
if (!myFile.is_open())
{
cout << "error";
return 0;
}
const int SIZE = 151;
char buffer[SIZE] = {};
myFile.getline(buffer, SIZE);
cout << buffer << endl;
myFile.close();
return 0;
}
If you want to read the first 150 characters of a specific line only, then you need a loop to skip all lines regardless of their length until you reach the desired line, and then you can read the 150 characters of just that line, eg:
#include <ifstream>
#include <iostream>
#include <limits>
using namespace std;
int main()
{
ifstream myFile("message.txt");
if (!myFile.is_open())
{
cout << "error";
return 0;
}
size_t lineIndex = ...;
while (lineIndex > 0)
{
if (!myFile.ignore(numeric_limits<streamsize>::max(), '\n'))
{
cout << "error";
return 0;
}
if (myFile.eof())
{
cout << "eof";
return 0;
}
--lineIndex;
}
const int SIZE = 151;
char buffer[SIZE] = {};
myFile.getline(buffer, SIZE);
cout << buffer << endl;
myFile.close();
return 0;
}
If you want to read the first 150 characters of each line, then after a successful read you need to skip any remaining characters prior to a line break before you can then read the next line, eg:
#include <ifstream>
#include <iostream>
#include <limits>
using namespace std;
int main()
{
ifstream myFile("message.txt");
if (!myFile.is_open())
{
cout << "error";
return 0;
}
const int SIZE = 151;
char buffer[SIZE] = {};
do
{
myFile.getline(buffer, SIZE);
if (myFile.bad())
{
cout << "error";
return 0;
}
if (myFile.fail())
{
// SIZE-1 characters were extracted before a line break
// was reached, need to reset the error to keep going...
myFile.clear();
myFile.ignore(numeric_limits<streamsize>::max(), '\n');
}
cout << buffer << endl;
}
while (!myFile.eof());
myFile.close();
return 0;
}

Convert char array to a string with cin.getline(.)

hi guys so my question is how to convert a char array to a string. here is my code:
#include<iostream>
using namespace std;
int main()
{
while (true) {
char lol[128];
cout << "you say >> ";
cin.getline(lol,256);
cout << lol << endl;;
}
return 0;
}
so I want to convert lol to a string variable like "stringedChar" (if thats even english lol)
so I can do stuff like:
string badwords[2] = {"frick","stupid"};
for (int counter = 0; counter < 2;counter++) {
if(strigedChar == badwords[counter]) {
bool isKicked = true;
cout << "Inappropriate message!\n";
}
}
Sorry im just a c++ begginer lol
Do something like this :
as char lol[128];
into string like: std::string str(lol);
Line : cin.getline(lol,256); <--> should be changed to cin.getline(lol,128)
Just invoke std::getline() on a std::string object instead of messing about with a char array, and use std::set<std::string> for badwords as testing set membership is trivial:
#include <iostream>
#include <set>
#include <string>
static std::set<std::string> badwords{
"frick",
"stupid"
};
int main() {
std::string line;
while (std::getline(std::cin, line)) {
if (badwords.count(line) != 0) {
std::cout << "Inappropriate message!\n";
}
}
return 0;
}
Note that this tests whether the entire line is equal to any element of the set, not that the line contains any element of the set, but your code appears to be attempting to do the former anyway.
First off, you have a mistake in your code. You are allocating an array of 128 chars, but you are telling cin.getline() that you allocated 256 chars. So you have a buffer overflow waiting to happen.
That said, std::string has constructors that accept char[] data as input, eg:
#include <iostream>
using namespace std;
int main()
{
while (true) {
char lol[128];
cout << "you say >> ";
cin.getline(lol, 128);
string s(lol, cin.gcount());
cout << s << endl;;
}
return 0;
}
However, you really should use std::getline() instead, which populates a std::string instead of a char[]:
#include <iostream>
#include <string>
using namespace std;
int main()
{
while (true) {
string lol;
cout << "you say >> ";
getline(cin, lol);
cout << lol << endl;;
}
return 0;
}

Trouble with cin.getline and strstr

Im trying to write a simple program that will read in a list of names and allow you to search through them. Im having a problem with my cin.getline and my strstr. Im new to c++ and im have a hard time getting my head around c string and its functions.
The error I get from the cin.getline is cannot convert parameter 1 from 'std::ifstream' to 'char *'
and cannot convert parameter 1 from 'char' to 'char *'
The error I get from the strstr is error C2665: 'strstr' : none of the 2 overloads could convert all the argument types
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
const int SIZE = 50;
int size = 0;
// Array of product descriptions
char phoneDirectory[SIZE];
char name; // For user input
char *strPtr = NULL; // Result from strstr
ifstream inFile;
inFile.open("phonebook");
while (!inFile.fail())
{
cin.getline(inFile,phoneDirectory[size]);
size++;
}
inFile.close();
// Get user input
cout << "Enter a name to search for: ";
cin.getline(name, SIZE);
// Search for the string
int index = 0;
while(index < size)
{
strPtr = strstr(phoneDirectory[index], name);
if (strPtr != NULL)
break;
index++;
}
// Output the result of the search
if (strPtr == NULL)
cout << "No matching names were found.\n";
else
cout << phoneDirectory[index] << endl;
return 0;
}
I cant seem to fix the cin.getline's and the strstr.
char name doesn't represent a string, but 1 single character. The getline function accepts a character pointer and an integer, and in your case you're feeding it a character and an integer.
Also, in c++ I'd suggest using std::string instead of characters array. It's much easier to handle and less error prone.
I've corrected your code to do what I think you're looking for. let me know if that's not what you're looking for:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
const int SIZE = 50;
int size = 0;
// Array of product descriptions
string phoneDirectory[SIZE];
string name; // For user input
char *strPtr = NULL; // Result from strstr
ifstream inFile;
inFile.open("phonebook");
while (!inFile.fail())
{
getline(inFile, phoneDirectory[size]);
size++;
}
inFile.close();
// Get user input
cout << "Enter a name to search for: ";
getline(cin, name);
// Search for the string
int index = 0;
while(index < size)
{
strPtr = strstr(phoneDirectory[index].c_str(), name.c_str());
if (strPtr != NULL)
break;
index++;
}
// Output the result of the search
if (strPtr == NULL)
cout << "No matching names were found.\n";
else
cout << phoneDirectory[index] << endl;
return 0;
}
If you really want to stick with the characters array, here's what your code should look like:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
const int DIRECTORY_SIZE = 50;
const int STRING_SIZE = 50;
int size = 0;
// Array of product descriptions
char phoneDirectory[DIRECTORY_SIZE][STRING_SIZE];
char name[STRING_SIZE]; // For user input
char *strPtr = NULL; // Result from strstr
ifstream inFile;
inFile.open("phonebook");
while (!inFile.fail() && size < DIRECTORY_SIZE)
{
inFile.getline(phoneDirectory[size], STRING_SIZE);
size++;
}
inFile.close();
// Get user input
cout << "Enter a name to search for: ";
cin.getline(name, STRING_SIZE);
// Search for the string
int index = 0;
while(index < size)
{
strPtr = strstr(phoneDirectory[index], name);
if (strPtr != NULL)
break;
index++;
}
// Output the result of the search
if (strPtr == NULL)
cout << "No matching names were found.\n";
else
cout << phoneDirectory[index] << endl;
return 0;
}

Storing a variable in C++

The problem is that file won't be read...Apparently there's a problem with an array but I don't really know how fix this issue...I'm a beginner to C++ 'arrays' and 'strings'...
My file should read the code, then translate the file, then output the text into a new file..
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <string.h>
using namespace std;
int main()
{
// Declarations
string reply;
string inputFileName;
ifstream inputFile;
ofstream outFile;
char character;
cout << "Input file name: ";
getline(cin, inputFileName);
// Open the input file.
inputFile.open(inputFileName.c_str());
// Check the file opened successfully.
if ( ! inputFile.is_open()) {
cout << "Unable to open input file." << endl;
cout << "Press enter to continue...";
getline(cin, reply);
return 1;
}
// This section reads and echo's the file one character (byte) at a time.
while (inputFile.peek() != EOF) {
inputFile.get(character);
//cout << character;
//Don't display the file...
char cipher[sizeof(character)];
//Caesar Cipher code...
int shift;
do {
cout << "enter a value between 1-26 to encrypt the text: ";
cin >> shift;
}
while ((shift <1) || (shift >26));
int size = strlen(character);
int i=0;
for(i=0; i<size; i++)
{
cipher[i] = character[i];
if (islower(cipher[i])) {
cipher[i] = (cipher[i]-'a'+shift)%26+'a';
}
else if (isupper(cipher[i])) {
cipher[i] = (cipher[i]-'A'+shift)%26+'A';
}
}
cipher[size] = '\0';
cout << cipher << endl;
}
cout << "\nEnd of file reached\n" << endl;
// Close the input file stream
inputFile.close();
cout << "Press enter to continue...";
getline(cin, reply);
return 0;
}
To make it short: You're on c++ so just don't use the whole C stuff.
Don't use character arrays, use std::string
Don't use islower(char) but use std::islower(char,locale)
Don't use C-style arrays but std::array (compile time constant size) or std::vector (dynamic size)
You'll want to have it more like this:
#include <string>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <locale>
int main (void)
{
std::string input_filename;
std::cout << "Input file name: ";
std::getline(std::cin, input_filename);
unsigned int shift;
do
{
std::cout << "Enter a value between 1-26 to encrypt the text: ";
std::cin >> shift;
}
while ((shift == 0) || (shift > 26));
try
{
std::string filestring;
std::ifstream input(input_filename, std::ios_base::in);
if (input)
{
input.seekg(0, std::ios::end);
filestring.reserve(input.tellg());
input.seekg(0, std::ios::beg);
filestring.assign
(std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>());
}
else
{
std::string error_string("Reading failed for: \"");
error_string.append(input_filename);
error_string.append("\"");
throw std::runtime_error(error_string);
}
std::string result;
result.reserve(filestring.size());
std::locale const loc;
for (auto character : filestring)
{
char const shifter(std::islower(character, loc) ? 'a' : 'A');
result.push_back((character-shifter+shift)%26+shifter);
}
std::cout << result << std::endl;
}
catch (std::exception & e)
{
std::cout << "Execution failed with an exception: " << std::endl;
std::cout << e.what() << std::endl;
}
}
This solution requires C++11 support. If you do not have C++11 you can replace the loop with:
size_t const N(filestring.length());
for (size_t i(0u); i<N; ++i)
{
char const shifter(std::islower(filestring[i], loc) ? 'a' : 'A');
result.push_back((filestring[i]-shifter+shift)%26+shifter);
}
From looking at your code, "character" is declared as a char which means it can only store one byte of information. Yet later on you start using it as if it was an array of characters.
You are also declare "cipher" as a char array that you manual manage like a string which is error prone. The real issue however is that you're mixing C-like code in C++. In other words, the way your code is written isn't considered idiomatic C++.
Pixelchemist already went over the important points so I'll just present a minimal refactored working example of your above code:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main()
{
string filename;
cout << "enter input file: ";
cin >> filename;
ifstream inputFile( filename.c_str() );
string plaintext;
do
{
plaintext += inputFile.get();
}while(inputFile);
cout << plaintext << endl;
string &ciphertext = plaintext;
//Caesar Cipher code...
int shift = rand() % 26 + 1;
for(size_t i = 0; i < ciphertext.size(); ++i)
{
if (islower(ciphertext[i])) {
ciphertext[i] = (ciphertext[i] - 'a' + shift) % 26 + 'a';
}
else if (isupper(ciphertext[i])) {
ciphertext[i] = (ciphertext[i] - 'A' + shift) % 26 + 'A';
}
}
cout << ciphertext << endl;
}
You'll notice in the refactor that I've done away with char and char[] arrays altogether and replaced it with std::string. I'm also performing the cipher operation inplace on the plaintext input. This is done by making a reference alias to plaintext called ciphertext for readability. Also in my example, the shift is done randomly for prototyping but you should change it to take it as a user input instead.
You are working with a single char, thats e.g. just one letter or a number. So the whole thing with size handling is useless, because the size is always 1. You probably should use const char*. But then you can't use filestream.get() at all, because it only returns a single char (not and cstring aka const char*).
And you can use fstream.get() as condition for the loop, so you don't need to ask for the eof flag.
char my_char;
std::ifstream infstream("filename.txt");
if(!infstream.isopen())
return -1;
while(infstream.get(my_char) {
//do some stuff
}
or
std::string my_string;
std::ifstream infstream("filename.txt");
if(!infstream.isopen())
return -1;
while(infstream >> my_string) {
//do some stuff
}
for dynamic arrays in C++ use std::vector or std::list or ... one of the other STL containers, so you don't have to waste your time on memory management and using static sized arrays.
And std::string is the way to go for strings in C++. It is something similar to the STL containers, but just for char's.

C++ program to read a txt file and sort data

I'm a physics PhD student with some experience coding in java, but I'm trying to learn C++.
The problem I'm trying to solve is to read in data from a .txt file and then output all the numbers > 1000 in one file and all those <1000 in another.
What I need help with is writing the part of the code which actually reads in the data and saves it to an array. The data itself is only separated by a space, not all on a new line, which is confusing me a bit as I don't know how to get c++ to recognise each new word as an int. I have canabalised some code I have got from various sources online-
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include<cmath>
using namespace std;
int hmlines(ifstream &a) {
int i=0;
string line;
while (getline(a,line)) {
cout << line << endl;
i++;
}
return i;
}
int hmwords(ifstream &a) {
int i=0;
char c;
a >> noskipws >> c;
while ((c=a.get()) && (c!=EOF)){
if (c==' ') {
i++;
}
}
return i;
}
int main()
{
int l=0;
int w=0;
string filename;
ifstream matos;
start:
cout << "Input filename- ";
cin >> filename;
matos.open(filename.c_str());
if (matos.fail()) {
goto start;
}
matos.seekg(0, ios::beg);
w = hmwords(matos);
cout << w;
/*c = hmchars(matos);*/
int RawData[w];
int n;
// Loop through the input file
while ( !matos.eof() )
{
matos>> n;
for(int i = 0; i <= w; i++)
{
RawData[n];
cout<< RawData[n];
}
}
//2nd Copied code ends here
int On = 0;
for(int j =0; j< w; j++) {
if(RawData[j] > 1000) {
On = On +1;
}
}
int OnArray [On];
int OffArray [w-On];
for(int j =0; j< w; j++) {
if(RawData[j]> 1000) {
OnArray[j] = RawData[j];
}
else {
OffArray[j] = RawData[j];
}
}
cout << "The # of lines are :" << l
<< ". The # of words are : " << w
<< "Number of T on elements is" << On;
matos.close();
}
But if it would be easier, i'm open to starting the whole thing again, as I don't understand exactly what all the copied code is doing. So to summarise, what I need is it to-
Ask for a filepath in the console
Open the file, and store each number (separated by a space) as an element in a 1D array
I can manage the actual operations myself I think, if I could just get it to read the file the way I need.
Thanks very much
Using C++11 and the Standard Library makes your task fairly simple. This uses Standard Library containers, algorithms, and one simple lambda function.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <vector>
int main()
{
std::string filename;
std::cout << "Input filename- ";
std::cin >> filename;
std::ifstream infile(filename);
if (!infile)
{
std::cerr << "can't open " << filename << '\n';
return 1;
}
std::istream_iterator<int> input(infile), eof; // stream iterators
std::vector<int> onvec, offvec; // standard containers
std::partition_copy(
input, eof, // source (begin, end]
back_inserter(onvec), // first destination
back_inserter(offvec), // second destination
[](int n){ return n > 1000; } // true == dest1, false == dest2
);
// the data is now in the two containers
return 0;
}
Just switch the type of variable fed to your fistream, created from new std:ifstream("path to file") into a int and c++ will do the work for you
#include <fstream> //input/output filestream
#include <iostream>//input/output (for console)
void LoadFile(const char* file)
{
int less[100]; //stores integers less than 1000(max 100)
int more[100]; //stores integers more than 1000(max 100)
int numless = 0;//initialization not automatic in c++
int nummore = 0; //these store number of more/less numbers
std::ifstream File(file); //loads file
while(!file.eof()) //while not reached end of file
{
int number; //first we load the number
File >> number; //load the number
if( number > 1000 )
{
more[nummore] = number;
nummore++;//increase counter
}
else
{
less[numless] = number;
numless++;//increase counter
}
}
std::cout << "number of numbers less:" << numless << std::endl; //inform user about
std::cout << "number of numbers more:" << nummore << std::endl; //how much found...
}
This should give you an idea how should it look like(you shoudnt use static-sized arrays tough) If you got any probs, comment back
Also, please try to make nice readable code, and use tabs/ 4 spaces.
even though its pure C, this might give you some hints.
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#define MAX_LINE_CHARS 1024
void read_numbers_from_file(const char* file_path)
{
//holder for the characters in the line
char contents[MAX_LINE_CHARS];
int size_contents = 0;
FILE *fp = fopen(file_path, "r");
char c;
//reads the file
while(!feof(fp))
{
c = fgetc(fp);
contents[size_contents] = c;
size_contents++;
}
char *token;
token = strtok(contents, " ");
//cycles through every number
while(token != NULL)
{
int number_to_add = atoi(token);
//handle your number!
printf("%d \n", number_to_add);
token = strtok(NULL, " ");
}
fclose(fp);
}
int main()
{
read_numbers_from_file("path_to_file");
return 0;
}
reads a file with numbers separated by white space and prints them.
Hope it helps.
Cheers