Weird white spaces added using ofstream - c++

I am processing a .txt file of format shown below:
Header 1:\n Header 2: \n 1 \n 2 \n 3 \n Header 1a: \n ...
And my code is as follows:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
ifstream infile(argv[1]);
string file_name = argv[1];
int after_underscore = 0;
string cut_name;
for (int i = 0; i < file_name.length(); i++) {
if (!ispunct(file_name[i])) {
cut_name += file_name[i];
}
else
break;
}
ofstream outfile(cut_name + std::string("_processed.txt"));
cout << "Processing " << argv[1] << "..." << endl;
string line;
int header_no = 7; // change this if the number of headers in the txt file changed
size_t points_no = 0; // this is the number of recorded points for each entry
size_t no_of_events = 0;
// define the needed header
string header1 = "Record Length";
string header2 = "Event Number";
size_t foundHeader1, foundHeader2 = 0;
while (!infile.eof()) {
// to process the header
for (unsigned int i = 0; i < header_no; i++) {
getline(infile, line);
foundHeader1 = line.find(header1);
foundHeader2 = line.find(header2);
int found_colon = line.find(":");
// looking for the "Record Length " header and find the number of points recorded
// Also look for "Event Number" header and count how many events are recorded
if (foundHeader1 != string::npos) {
line = line.substr(found_colon + 1);
points_no = stoi(line);
continue;
}
else if (foundHeader2 != string::npos) {
no_of_events += 1;
continue;
}
else
continue;
}
}
infile.close();
infile.clear();
// to process the numbers
outfile << "Number of points per entry: " << points_no << endl;
outfile << "Number of events recorded: " << no_of_events << endl;
outfile << endl;
infile.open(argv[1]);
while (infile) {
cout << "Hello" << endl;
for (unsigned int i = 0; i < header_no; i++) {
getline(infile, line);
}
for (unsigned int i = 0; i < points_no; i++) {
getline(infile, line);
outfile << line << " ";
}
outfile << endl;
}
outfile.close();
cout << "Done processing! " << cut_name << "_processed.txt is produced" << endl;
}
The code gives me the correct output, but I noticed that there are some white spaces added in the output file towards the end of my output.
I wanted my entries to end after "730 \n" but oddly some white spaces are added after then and an extra \n is there too. These white spaces are unwanted and gave me issues when I want to further process the output file. I could not figure out why they are present there. Can anyone help me to check what went wrong or give me some advise? Thanks you.

Related

Why is my program skipping over the indices of repeated words

I am having problems with my program. Basically it finds the word count of a text file, the most and least repeated word, and have the user find a word. My problem is that when I find a words, it skips the indices of the repeated words. For example, if a text file has the words:
one two one one three five
and the user searches for "three", it will output that the index is 2. It skips over the repeated words. Why is that?
Here is my code:
int main() {
int counts[ARRAY_SIZE] = { 0 };
string words[ARRAY_SIZE];
ifstream inFile;
string filename, searchWord, lowerCase;
int wordCount = 0, totalWords = 0, index = 0;
int result, mostIndex, leastIndex;
cout << "Enter a text file: ";
cin >> filename;
inFile.open(filename);
while (!inFile.is_open()) {
if (filename == "q") {
inFile.close();
return 0;
}
else if (inFile.is_open()) {
cout << filename << " is open";
}
else {
cout << "Enter a valid file or type \"q\".";
}
cout << "The file you enetered is not valid, please enter a valid file or type \"q\" to quit.";
cin >> filename;
inFile.open(filename);
}
while (!inFile.eof()) {
while (inFile >> lowerCase) {
wordCount++;
lowerCase = convertCase(lowerCase);
result = search(words, lowerCase, totalWords);
if (result == NOT_FOUND) {
words[totalWords] = lowerCase; // lowerCase is a new word, so add it to the array,
counts[totalWords] = 1; // and set it's count to 1.
totalWords++;
}
else {
counts[result]++; // The word was found, so increment the times we've seen it.
}
}
cout << endl << "Total words: " << wordCount << endl;
cout << "Search a word: ";
cin >> searchWord;
index = search(words, searchWord, totalWords);
if (index == NOT_FOUND) {
cout << "\"" << searchWord << "\"" << " was not found." << endl;
}
else {
cout << endl << "the word " << "\"" << searchWord << "\"" << " is found on at index " << index << endl;
}
mostIndex = findIndexOfMost(counts, totalWords);
leastIndex = findIndexOfLeast(counts, totalWords);
cout << "The most repeated word is \"" << words[mostIndex] << "\" and was found " << counts[mostIndex] << " time(s)." << endl;
cout << "The least repeated word is \"" << words[leastIndex] << "\" and was found " << counts[leastIndex] << " time(s)." << endl;
}
system("pause");
return 0;
}
string convertCase(string word){
for (int i = 0; i < word.length(); i++) {
word[i] = tolower(word[i]);
}
return word;
}
int search(string words[], string searchWord, int totalWords){
int index = NOT_FOUND;
for (int i = 0; i < totalWords; i++){
if (words[i] == searchWord){
index = i;
break;
}
}
return index;
}
int findIndexOfMost(int counts[], int totalWords){
int most; // assume most is first count.
int index = 0, i;
most = counts[index];
for (i = 0; i < totalWords; i++)
{
if (counts[i] > most){
most = counts[i];
index = i;
}
}
return index;
}
int findIndexOfLeast(int counts[], int totalWords) {
int least, index = 0, i;
least = counts[index];
for (i = 0; i < totalWords; i++)
{
if (counts[i] < least) {
least = counts[i];
index = i;
}
}
return index;
}
I agree with the comments on your post, but I did find your error rather quickly. I highly suggest you try the debugger in the future to follow the variables you care about and see what is happening and how they are updating, when they're not updating as you think they would. Even simply printing your array words would show you the problem.
You're only adding words to the words array when they haven't been found yet, so when you search through words, you're searching through the unique words.
if (result == NOT_FOUND) {
words[totalWords] = lowerCase; // lowerCase is a new word, so add it to the array,
counts[totalWords] = 1; // and set it's count to 1.
totalWords++;
}
else {
counts[result]++; // The word was found, so increment the times we've seen it.
}
For the file
one two one one three five
your variable words would hold
one two three five
so if you searched for 'three' in words you would get the index 2, even though it's the fifth word in your file, so you want the index 4.

How do I count words and lines that were input as a cstring array

This program should read a paragraph from a text file provided by the user and then store each line in a ragged char array and count the total number of words and lines of the paragraph then display the result.
I can't figure out why does the number of lines keep giving me the result of 3
and why the number of words is always missing 2 words.
please help and keep in mind that I'm no professional just started learning c++ recently.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
ifstream infile;//declarations
char filename[45];
char **data = 0;
char **temp = 0;
char *str = 0;
char buffer[500], c;
int numoflines = 0, numofwords = 0;
cout << "Please enter filename: ";//prompt user to enter filename
cin >> filename;
infile.open(filename);//open file
if (!infile)//check if file was successfully opened
{
cout << "File was not successfully opened" << endl << endl;//display error message
return 0;
} //end of if
data = new char*[numoflines];
while (!infile.eof())
{
temp = new char*[numoflines + 1];
for (int i = 0; i < numoflines; i++)
{
infile.getline(buffer, 500);//read line
for (int i = 0; i < strlen(buffer); i++)//count number of words in line
{
c = buffer[i];
if (isspace(c))
numofwords++;
}
str = new char[strlen(buffer) + 1];//allocate a dynamic array
strcpy(str, buffer);
data[i] = str;
temp[i] = data[i];
}//end of for
infile.getline(buffer, 500);
for (int i = 0; i < strlen(buffer); i++)//count number of words in line
{
c = buffer[i];
if (isspace(c))
numofwords++;
}
temp[numoflines] = new char[strlen(buffer) + 1];
strcpy(temp[numoflines], buffer);
delete[] data;
data = temp;
numoflines++;
}
cout << "Number of words: " << numofwords << endl;
cout << "Number of lines: " << numoflines << endl;
return 0;
}
The concept of number of lines is a viewing concept only. It's not encoded into the file. The following single paragraph can be displayed on one line or 16 lines depending upon the size of the editor window:
If you wanted to specify a char width of the window, lines could be calculated from that, but as is, paragraphs and wordcount are as good as you will do. And given a successfully opened ifstream infile that is fairly simple to obtain:
auto numoflines = 0;
auto numofwords = 0;
string paragraph;
while(getline(infile, paragraph)) {
numofwords += distance(istream_iterator<string>(istringstream(paragraph)), istream_iterator<string>());
++numoflines;
}
cout << "Number of words: " << numofwords << "\nNumber of lines: " << numoflines << endl;
NOTE:
Visual Studio supports inline construction of an istringstream so if you're not using that you'll need to construct on a separate line.

Unexpected abort in C++

I have a piece of code I'm running in Cygwin in C++ I'm compiling using
g++ -o program program.cpp
And it is returning an error that reads 'Aborted (core dumped)'. It is intended to take a file name as input through a command line argument, count all the unique words and total words in the file, and prompts the user to input a word and counts how many times the word that they input occurs. It's only intended to use C++ streams for input/output.
#include <fstream>
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main(int argc, char *argv[])
{
string filename;
for( int i = 1; i < argc; i++){
filename+=argv[i];
}
ifstream file;
file.open(filename.c_str());
if (!file)
{
std::cerr << "Error: Cannot open file" << filename << std::endl;
return 1;
}
string* words;
int* wordCount;
int wordLength = 0;
string curWord = "";
bool isWord;
int total = 0;
char curChar;
string input;
while(!file.eof())
{
file.get(curChar);
if (isalnum(curChar)) {
curWord+=tolower(curChar);
}
else if (!curWord.empty() && curChar==' ')
{
isWord = false;
for (int i = 0; i < wordLength; i++) {
if (words[i]==curWord) {
wordCount[i]++;
isWord = true;
total++;
}
}
if (!isWord) {
words[wordLength]=curWord;
wordLength++;
total++;
}
curWord="";
}
}
file.close();
// end
cout << "The number of words found in the file was " << total << endl;
cout << "The number of unique words found in the file was " << wordLength << endl;
cout << "Please enter a word: " << endl;
cin >> input;
while (input!="C^") {
for (int i = 0; i < wordLength; i++) {
if (words[i]==input) {
cout << wordCount[i];
}
}
}
}
You never allocated any space for words and wordCount to point to. It should be:
#define MAXWORDS 1000
string *words = new string[MAXWORDS];
int *wordCount = new int[MAXWORDS];
and then at the end of the program you should do:
delete[] wordCount;
delete[] words;
or you can allocate a local array:
string words[MAXWORDS];
int wordCount[MAXWORDS];
But you could do it more simply by using std::map to map the string to a count. This will automatically grow as needed.

How to take input file, reverse word order, write to output file in C++

Take the contents of an input text file and write them in reverse order of words to an output file. Your program can ignore line breaks. You will need to use arrays.
(unnecessary crap removed) Aaaaah, panic, please help!
EDIT: What I have so far. Still lost on how to reverse word order now.
//Kristen Korz
//CIS 22A
//This program reads an input file and writes the words in reverse order to an output file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//create and link input...
ifstream inputFile;
inputFile.open("input.txt");
//...and output files
ofstream outputFile;
outputFile.open("output.txt");
//error message for file open fail
if (inputFile.fail())
cout << "Error opening the file.\n";
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str;
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
}
inputFile.close();
//for showing if read correctly
cout << endl;
for (int i = 0; i < MAXSIZE; ++i)
cout << words[i] << endl;
system("pause");
return 0;
}
What I've got successfully reads the input file word for word. I can figure out everything except how to reverse the word order for then writing to output.txt
This is our first program reversing the order of things, yes.
EDIT 2:
Okay, so the best I can guess is this:
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str; //note: variables will be used for output loops too
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
}
inputFile.close();
//for showing if read correctly
cout << endl;
for (int i = 0; i < MAXSIZE; ++i)
cout << words[i] << endl;
//for writing in reverse word order to output file
for (int i = MAXSIZE-1; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;
}
outputFile.close();
//for showing if written correctly
for (int i= MAXSIZE-1; i >= 0; --i)
{
cout << words[i] << endl;
}
The input section works fine. Output just repeats last word of input for each iteration.
EDIT 3:
Just kidding, everything except actual writing of output file works. Output in the terminal is corrects by getting rid of the "-1" after MAXSIZE in the initialization. Adjusting the code that writes the file in a similar way does not solve the repeating "works." (final word of input file) written to output.txt
EDIT 4:
Relevant code is now:
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str; //note: variables will be used for output loops too
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
}
inputFile.close();
//for showing if read correctly
cout << endl;
for (int i = 0; i < MAXSIZE; ++i)
cout << words[i] << " ";
//for writing in reverse word order to output file
for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i)
{
words[i] = str;
}
outputFile.close();
//for showing if written correctly
for (int i = MAXSIZE; i >= 0; --i)
{
cout << words[i] << " ";
}
If I change i>=0 to i=0 (which I mistakenly typed first try) in for (int i = MAXSIZE; (outputFile << str) && (i >= 0); --i), then cout in terminal is perfect. Can't figure out how to get output file to not be repeated "works." Why is it doing that? Note: output to terminal optional, so I don't really care why that wants i assigned to 0 in previous for loop in terms of being able to finish the assignment
Another algorithm:
Map the file into memory or read it into std::vector<char> or std::string.
Reverse each word individually with std::reverse.
Reverse the entire file with std::reverse.
Write the file back if it was read into a container.
This is how I ended up doing it:
//Kristen Korz
//CIS 22A
//This program reads an input file and writes the words in reverse order to an output file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//create and link input...
ifstream inputFile;
inputFile.open("input.txt");
//...and output files
ofstream outputFile;
outputFile.open("output.txt");
//error message for file open fail
if (inputFile.fail())
cout << "Error opening the file.\n";
//constant for max size
const int MAXSIZE = 1024;
//string array and temporary-use string
string words[MAXSIZE];
string str; //note: variables will be used for output loops too
//read words from input file
for (int i = 0; (inputFile >> str) && (i < MAXSIZE); ++i)
{
words[i] = str;
//for showing in terminal if read correctly
cout << words[i] << " " << i << " ";
}
inputFile.close();
cout << endl;
//something wrong with for loop resulting in i apparently not updating
for (int i = MAXSIZE - 1; (outputFile << str) && (i >= 0); --i)
{
if (str.size() < MAXSIZE)
{
//for showing in terminal if written correctly
cout << words[i] << " " << i << " ";
}
}
outputFile.close();
cout << endl;
system("pause");
return 0;
}
So, let me try to help you the best way I can.
Maybe, it will be helpful.
Take the contents of an input text file and write them in reverse order of words to an output file. Your program can ignore line breaks. You will need to use arrays.
inputFile.open (" input.txt ");
outputFile.open (" output.txt ");
if (inputFile.fail()) {
cout << "input.txt not found" << endl;
return -1;
}
if (outputFile.fail()) {
cout << "not able to open output.txt" << endl;
return -1;
}
int i = 0;
int count = 0;
string words[1000];
while (inputFile >> words[i]) {
count++;
i++;
}
for (int j = count; j >= 0; j--) {
outputFile << words[j] << " ";
}
inputFile.close();
outputFile.close();
return 0; }

Count words in each line of text file in c++

I open a txt file using argc, argv, and getline. I did that properly, but now I have to get the number of words per line (the number of lines is not known before) and I must output them in reverse. Meaning from the bottom line to the top line. Any help is appreciated. This code outputs the number of words in the file:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main(int argc, char *argv[])
{
if(argc < 1){
cerr << "Usage: " << argv[0] << "filename.txt" << endl;
}
ifstream ifile(argv[1]);
if(ifile.fail()){
cerr << "Could not open file." << endl;
return 1;
}
int n;
ifile >> n;
cout << n;
int numberOfWords = 0;
string line;
for(int i = 0; i <= n; i++){
getline(ifile, line);
cout << line << endl;
}
size_t i;
if (isalpha(line[0])) {
numberOfWords++;
}
for (i = 1; i < line.length(); i++) {
if ((isalpha(line[i])) && (!isalpha(line[i-1]))) {
numberOfWords++;
}
}
cout<<"The number of words in the line is : "<<numberOfWords<<endl;
return 0;
}
To find the number of words per line you would use std::getline() to iterate over each line and use std::stringstream to extract each chunk of whitespace-separated input. Then you would iterate over each chunk of input and check to see if each character is alphabetic:
int numberOfWords = 0;
for (std::string line, word; std::getline(ifile, line); )
{
std::istringstream iss(line);
while (iss >> word)
{
bool alpha = true;
for (char c : word)
if (!std::isalpha(c)) alpha = false;
if (alpha) ++numberOfWords;
}
std::cout << "Number of words on this line: " << numberOfWords << std::endl;
numberOfWords = 0;
}