I use getchar() and loop to get a text and use fputc() to put into the text file, but it always leaves the first line empty in the text file after writing. The loop stops when character input is a dot (.). How can I delete the first line?
Updated (12/29/2016): I used DevC++ and the codes run finely without creating an empty blank, but my VisualStudio2015 had the problem.
Example: create a file named test.txt
input: this is a text.
output: (in the text file)
[ a blank line ]
this is a text
void writeFile(char *fileName){
FILE *fp;
fp = fopen(fileName, "wt"); //write text
if (fp == NULL) {
cout << "Failed to open" << endl;
fclose(fp);
}
else {
int i = 0;
char c = '\0';
cout << "Enter a text and end with dot (.): ";
fflush(stdin);
//c = getchar();
while (c != '.') {
fputc(c, fp);
c = getchar();
}
cout << "Written successfully" << endl;
fclose(fp);
}
}
Out of curiosity, is there a reason for the C functions? Doing something like this in C++ would be better suited to using streams, like:
#include <iostream>
#include <fstream>
using namespace std;
void writeFile(const char *fileName)
{
ofstream writeToFile;
writeToFile.open(fileName);
if (!writeToFile.is_open()) {
cout << "Failed to open" << endl;
return;
} else {
string stringToWrite{""};
char c = '\0';
cout << "Enter a text and end with dot (.): ";
while (c != '.') {
std::cin >> c;
stringToWrite += c;
}
writeToFile << stringToWrite << endl;
cout << "Written successfully" << endl;
writeToFile.close();
}
}
int main()
{
const char *fileName="test.txt";
writeFile(fileName);
return 0;
}
or, alternatively:
#include <iostream>
#include <fstream>
using namespace std;
void writeFile(const char *fileName)
{
ofstream writeToFile;
writeToFile.open(fileName);
if (!writeToFile.is_open()) {
cout << "Failed to open" << endl;
return;
} else {
string stringToWrite{""};
cout << "Enter text and press return: ";
getline(cin, stringToWrite);
writeToFile << stringToWrite << endl;
cout << "Written successfully" << endl;
writeToFile.close();
}
}
int main()
{
const char *fileName="test.txt";
writeFile(fileName);
return 0;
}
c is 0 on the first pass, hence the blank line.
change the while loop to
while( (c = getchar()) != EOF)
{
if(c == '.')
break;
}
It looks a bit odd, but is idiomatic for reading characters from a stream in C.
Related
I am supposed to ask the user for two file names (input and output files). The contents from the input file should be read and the first letter of each sentence should be made uppercase while every other letter should be made lowercase. The results should then be stored in the output file.
I am aware that there are ways of using the toupper and tolower functions that include pointers, arrays, or even ASCII values of chars but I am trying to get this code to work by using if/else and while statements, as well as boolean statements. I have had various results ranging from all the letters being capitalized to none of the letters being capitalized however, I think right now I am on the right track with the code and am just overlooking the way I am incrementing through the characters causing the code to not capitalize after a period and a space.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string input_file; // To hold input file name
string output_File; // To hold output file name
char ch; // To hold character
fstream inputFile;
fstream outputFile;
bool new_sentence = true;
cout << "Enter input file name: " << endl;
cin >> input_file;
cout << "Enter output file name: " << endl;
cin >> output_File;
outputFile.open(output_File, ios::out);
inputFile.open(input_file, ios::in);
if (inputFile) {
while (inputFile.get(ch)) {
if (isprint(ch)) {
if (new_sentence) {
outputFile.put(toupper(ch));
}
else {
outputFile.put(tolower(ch));
}
new_sentence = false;
}
else {
if (ch == '.') {
new_sentence = true;
outputFile.put(ch);
}
}
}
inputFile.close();
outputFile.close();
}
else {
cout << "Cannot open file(s)." << endl;
}
cout << "\nFile conversion complete." << endl;
return 0;
}
With my current code I am able to capitalize the first letter of the first sentence and make every other letter lowercase. I am able to store and show the results in the output file. My issue is that the first letter of every other sentence after the first one won't change to uppercase. This makes me think the issue is in this part of the code:
if (new_sentence)
{
outputFile.put(toupper(ch));
}
else
{
outputFile.put(tolower(ch));
}
Am I missing something here?
You have a minor logical error.
You first need to check, if the character is a period. This state you need to remember. If then a next character isalpha, then we check, if recently the newsentence flag has been set. In this case, and only in this case, we reset the new sentence flag and convert the character to uppercase.
All other alpha characters will be converted to lowercase. Other charcaters will not be converted.
In your solution you always reset the newsentence flag. Even, if the next print character is a space (Which is most liekly the case).
Please see updated solution:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string input_file; // To hold input file name
string output_File; // To hold output file name
char ch; // To hold character
fstream inputFile;
fstream outputFile;
bool new_sentence = true;
cout << "Enter input file name: " << endl;
cin >> input_file;
cout << "Enter output file name: " << endl;
cin >> output_File;
outputFile.open(output_File, ios::out);
inputFile.open(input_file, ios::in);
if (inputFile) {
while (inputFile.get(ch)) {
if (ch == '.') {
new_sentence = true;
}
if (isalpha(ch)) {
if (new_sentence) {
ch = toupper(ch);
new_sentence = false;
}
else {
ch = tolower(ch);
}
}
outputFile.put(ch);
}
inputFile.close();
outputFile.close();
}
else {
cout << "Cannot open file(s)." << endl;
}
cout << "\nFile conversion complete." << endl;
return 0;
}
And then, please see some further improvements:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
int main() {
// Will hold the input and output filename
std::string filename;
// This is our flag to indicate that a new sentence will come
bool newSentence = true;
// Get input filename
std::cout << "Enter input file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ifstream inFile(filename);
std::cout << "Enter output file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ofstream outFile(filename);
// Only convert, if the input and output file could be opened
if (inFile && outFile) {
char ch;
while (inFile.get(ch)) {
if (ch == '.') {
newSentence = true;
}
if (isalpha(ch)) {
if (newSentence) {
ch = toupper(ch);
newSentence = false;
}
else {
ch = tolower(ch);
}
}
outFile.put(ch);
}
}
else {
std::cout << "Cannot open file(s)\n";
}
std::cout << "\nFile conversion program complete\n";
return 0;
}
And the full blown "C++ with algorithm" solution. Here the conversion, or transformation is done in one statement
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <algorithm>
#include <iterator>
int main() {
// Will hold the input and output filename
std::string filename;
// Get input filename
std::cout << "Enter input file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ifstream inFile(filename);
std::cout << "Enter output file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ofstream outFile(filename);
// Only convert, if the input and output file could be opened
if (inFile && outFile) {
// Do the conversion
std::transform(
std::istreambuf_iterator<char>(inFile),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(outFile),
[newSentence = true](char c) mutable {
if (c == '.') newSentence = true;
if (std::isalpha(c))
if (newSentence) {
newSentence = false;
c = std::toupper(c); }
else c = std::tolower(c);
return c;
}
);
}
else {
std::cout << "Cannot open file(s)\n";
}
std::cout << "\nFile conversion program complete\n";
return 0;
}
But if the last solution adds additional value? I am not sure . . .
This part of your code should be changed:
// if (isprint(ch)) {
if (ch != '.') {
if (new_sentence) {
outputFile.put(toupper(ch));
}
else {
outputFile.put(tolower(ch));
}
new_sentence = false;
}
else {
new_sentence = true;
outputFile.put(ch);
}
std::isprint() only checks if the character is printable.
Full code:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string input_file; // To hold input file name
string output_File; // To hold output file name
char ch; // To hold character
fstream inputFile;
fstream outputFile;
bool new_sentence = true;
cout << "Enter input file name: " << endl;
cin >> input_file;
cout << "Enter output file name: " << endl;
cin >> output_File;
outputFile.open(output_File, ios::out);
inputFile.open(input_file, ios::in);
if (inputFile) {
while (inputFile.get(ch)) {
if (ch != '.') {
if (new_sentence) {
outputFile.put(toupper(ch));
}
else {
outputFile.put(tolower(ch));
}
new_sentence = false;
}
else {
new_sentence = true;
outputFile.put(ch);
}
}
inputFile.close();
outputFile.close();
}
else {
cout << "Cannot open file(s)." << endl;
}
cout << "\nFile conversion complete." << endl;
return 0;
}
I want to print out the first character in the input file is the last character in the output file and vice-versa. But I stuck at how to print out the output.
I need to use arrays. I will read from input file into a character array and the write from the array to the output file.
Example:
Input.txt: A B C D E H
output.txt: H B C D E A
This is my code
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string FileName, FileName2;
string s, temp, FirstChar, LastChar;;
char again = 'Y';
bool close = false;
char MAXSIZE[1024];
while (close == false)
{
cout << "Open the file: ";
cin >> FileName;
ifstream ReadFromFile(FileName);
if (ReadFromFile.is_open())
{
cout << "Succeed to open the file!\n";
// Read character from the input to array
while (!ReadFromFile.eof())
{
ReadFromFile >> MAXSIZE;
cout << MAXSIZE << " ";
}
cout << endl;
cout << "Enter the first character: ";
cin >> FirstChar;
cout << "Enter the last character: ";
cin >> LastChar;
swap(FirstChar, LastChar);
// I stuck at here
ifstream in(FileName);
cout << "Enter a name for a copy file: ";
cin >> FileName2;
ofstream out(FileName2);
while (getline(in, s))
out << s << "\n";
cout << "Close the program and then open your copy file.";
cout << endl << endl;
close = true;
}
else{
cout << "Failed to open the file!\n";
do {
cout << "Do you want to do it again(Y) or Close (N)? ";
cin >> again;
} while (again != 'y' && again != 'Y' && again != 'n' && again != 'N');
if (again == 'y' || again == 'Y')
close = false;
else
close = true;
cout << endl;
}
}
system("pause");
return 0;
}
Your task (according to your explanation) require:
1) reading from input file to array
2) changing the first and the last characters
3) saving array to output file
So, the first and the last characters should not be asked from standard input (keyboard).
#include <iostream>
#include <fstream>
using namespace std;
// filenames can be given as command line arguments
// change the code if you want to read them from standard input
int main(int argc, char* argv[])
{
ifstream inf;
ofstream outf;
size_t counter = 0;
const size_t MAXSIZE = 1024; // MAXSIZE - name of constant
char buffer[MAXSIZE]; // buffer - name of array
// check the command line arguments
// Alternatively you can define: string InpFileName, OutFileName;
// as it is in your code and enter values (cin >>) instead using argv
// if so, you should change inf.open(argv[1]); to inf.open(InpFileName);
// and outf.open(argv[2]); to outf.open(OutFileName);
if (argc != 3)
{
cerr << "Two arguments are required:" << endl
<< " 1) name of existing file (to read)" << endl
<< " 2) name of new file (to create)" << endl;
return 1;
}
// open files
inf.open(argv[1]);
outf.open(argv[2]);
// check files
if (!inf.is_open() || !outf.is_open())
{
cout << "ERROR: some trouble with files." << endl;
return 2; // stop the program
}
// process
// 1) reading
while (counter < MAXSIZE){
buffer[counter] = inf.get();
if (buffer[counter] != EOF)
{
counter++;
}
else
{
counter--; // the last character is not valid
break; // end of file
}
}
// 2) changing
char b = buffer[counter];
buffer[counter] = buffer[0];
buffer[0] = b;
// 3) output
for (int i = 0; i <= counter; i++)
{
outf.put(buffer[i]);
}
// close files
inf.close();
outf.close();
return 0;
}
UPDATE:
Clarify the task for cases when some unprintable character (like space) is the first or the last
Looks like a homework problem for a C++ class. One hint which may help is to
divide the file into blocks of X bytes and read the blocks in reverse order....
std::istream::seekg
I have the following program:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
void tellen ()
{
ifstream input;
ofstream output;
char kar;
input.open ("test",ios::in);
kar = input.get();
while ( !input.eof() ){
if ( kar >= '0' and kar <= '9'){
cout << kar;
kar = input.get();
}
else
kar = input.get();
}
//cout << "Aantal characters:" << aantalchar << endl;
//cout << "Aantal regels:" << aantalregels << endl;
}
int main()
{
tellen();
return 0;
} //main
What I intended this program to do is to show me all numbers in a certain text file ("Test" in this case) in the command window. I'm wondering why this doesn't work? I have a file called test but when I run this the command prompt gives me a blank. The problem persists when I change "test" to "test.txt". Does anyone have a clue what the problem is? Maybe it has to do with the location of the file?
The following code will give you output of a txt file called test.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
void tellen() {
ifstream input;
ofstream output;
int kar;
char charKar;
input.open("test.txt", ios::in);
// could replace "test.txt" with a variable such as filePath = "/downloads/test.txt"
if (input.is_open()) {
while (!input.eof()) {
kar = input.get(); //kar gets inputed as an ASCII
charKar = static_cast<char>(kar);//charKar converts the ASCII into a char variable
if (charKar >= '0' && charKar <= '9'){ //Evaluate charKar, not kar
cout << charKar << endl;
}
}
input.close();
}
else {
cout << "\nFile Did Not Open!";
}
}
int main() {
tellen();
return 0;
} //main
I have tested the code and it works! Sorry if it's messy I was making eggs while coding this so if you have any questions just ask!
Things to change:
Add a check to make sure that the file was opened successfully.
Use type int when reading characters using istream::get() instead of char.
Change the while statement a bit.
void tellen (){
ifstream input;
ofstream output;
input.open ("test",ios::in);
if ( !input )
{
std::cerr << "Unable to open file.\n";
return;
}
int kar; // Don't use char.
while ( (kar = input.get()) != EOF ){
if ( kar >= '0' and kar <= '9'){
cout.put(kar); // I prefer this.
// cout << (char)kar;
}
}
//cout << "Aantal characters:" << aantalchar << endl;
//cout << "Aantal regels:" << aantalregels << endl;
}
I am currently trying to build a program that reads in a file, scans through that file, and outputs all words in that file surrounded by " marks. I am currently stumped and was hoping to get some help!
#include <iostream>
// For file I/O:
#include <fstream>
#include <cstdlib>
#include <iomanip>
using namespace std;
// Prototype the count function so we can have it below it's first
// use in main().
void count(istream& in, int& lines, int& words, int& characters);
/*
* wc <filename>
*/
int main(int argc, char *argv[])
{
if (argc < 2) {
cerr << "Usage: wc <filename>" << endl;
return 0;
}
// Open the file specified by argv[1] for reading:
// Constructs a ifstream object called "in":
ifstream in(argv[1]);
// Was there a problem opening the file?
if (!in.good()) {
cerr << "Unable to open file [" << argv[1] << "] for reading." << endl;
return 1;
}
int lines = 0, words = 0, characters = 0;
count(in, lines, words, characters);
cout << setw(5) << lines << " " << words << " " <<
characters << " " << argv[1] << endl;
// Close the input stream:
in.close();
}
void count(istream& in, int& lines, int& words, int& characters)
{
int i;
char s;
int ch;
bool inword = false;
// Read until the end of file is reached, or there was an error:
while (!in.eof()) {
// Read a character from the input stream "in":
s = in.get(); //Set char s = in.get
for(i=0; s != 0; i++){ //Loop to iterate through the characters
while(s == '"'){ //While s is equal "
cout << s << endl; // Print s
if(s == '"') // If we hit another ", then we break
break;
}
}
if (in.good() == false) return;
characters++;
if (!isspace(ch) && !inword) {
inword = true;
words++;
} else if (isspace(ch) && inword) {
inword = false;
}
if (ch == '\n') lines++;
}
}
your algorithm seems wrong.. in the for loop you compare to 's' but you're not updating it... try something like this in your main loop(QnD):
while (!in.eof() && (s = in.get()) != '"'); // read to first quote char
/* this is the word we want.. run to end quote marks.. */
while (!in.eof() && (s = in.get()) != '"') {
cout << s;
}
cout << endl;
I am working on a project where I will be able to read in a file that contains any text, like the sample text below. Then, character by character, it will be able to output n-character long sequences (represented below as a read-in value given by the user along the lines of 1, 2, 3, 4...) along the whole length of the text. So, for example:
As Gregor Samsa awoke one morning from uneasy dreams he found himself transformed in his bed into a gigantic insect.
If the user provided 2 as the sequence length, the program should spit out: "As" "s " " G" "Gr" "re" "eg" "go" "or" "r " and so on...
I have written this code but don't know why it won't work. Right now, it doesn't spit out every possible variation of the sequence. Any suggestions would be very helpful. Thanks.
#include "genlib.h"
#include <iostream>
#include <fstream>
#include "simpio.h"
#include "random.h"
#include "vector.h"
#include "map.h"
/* Private Instance Variables */
int seed_length;
string line;
string seed_string;
string next_string;
char ch;
/* Function Prototypes */
string promptUserForFile(ifstream & infile);
int main() {
ifstream infile;
promptUserForFile(infile);
// Ask what order of Markov model to use.
cout << "What order of Markov model should we use? ";
cin >> seed_length;
while (infile.eof() == false) {
ch = infile.get();
for (int i = 0; i < seed_length - 1; i++) {
cout << "ch up here is " << ch << endl;
if (isspace(ch) && i == 0) {
seed_string += ch;
} else {
seed_string += ch;
ch = infile.get();
}
}
next_string = ch;
if (isspace(ch)) {
next_string = " ";
} else {
char trythis = infile.get();
next_string += trythis;
}
cout << seed_string << endl;
cout << next_string << endl;
seed_string = "";
next_string = "";
}
cout << "TEST" << endl;
// Close the file when you're done storing all of the scores.
infile.close();
return 0;
}
string promptUserForFile(ifstream & infile) {
string prompt = "Please input your filename: ";
while(true) {
cout << prompt;
string filename;
getline (cin, filename);
infile.open(filename.c_str());
if(!infile.fail()) return filename;
infile.clear();
cout << "Unable to open that file. Try again." << endl;
if (prompt == "") prompt == "Input file: ";
}
return 0;
}
The code has two problems.
The special handling for isspace is broken:
if (isspace(ch) && i == 0) {
seed_string += ch;
} else {
seed_string += ch;
ch = infile.get();
}
This essentially means that if the first character in this loop is a space, it will be added twice.
Every character received from infile.get() is only added to seed_string once (with the exception of isspace characters).
A better way to code this is to recognize that:
You have to ignore consecutive isspace characters.
Every sequence can be obtained by removing the first character of the preceding sequnce and appending the next character from the file.
Here is a better implementation; it takes the order of the Markov model in the first command line parameter and takes the text from standard input. By encapsulating the skipping of duplicate spaces in a separate function, you don't have to deal with it in the main body of the algorithm.
#include <iostream>
#include <cstdlib>
char next_character() {
static bool was_space = false;
char ret = 0;
do {
ret = std::cin.get();
} while (was_space && std::isspace(ret));
if (std::isspace(ret)) {
was_space = true;
ret = ' ';
} else {
was_space = false;
}
return ret;
}
int main(int argc, char **argv) {
if (argc != 2) return 0;
int mlen = std::atoi(argv[1]);
std::string seq;
for (unsigned i = 0; i < mlen; ++i) {
seq += next_character();
}
std::cout << seq << '\n';
while (true) {
seq.erase(0, 1);
char c = next_character();
if (std::cin.eof()) break;
seq += c;
std::cout << seq << '\n';
}
return 0;
}
Example input:
This is a test
Example output:
This
his i
is is
s is
is a
is a
s a t
a te
a tes
test