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;
}
Related
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.
I'm trying to create a program that reads in numbers from a file into an array, reverse the order of the numbers in the array and then outputs those reversed numbers into a different file. I was able to get the program to work when I already knew how many numbers were in the file but I am having difficulty when I switch my loop to trying to detect the EOF(End of file). When I run this code it will print two of the numbers from the file and the rest are garbage values. Any Help?
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int NUMS = 5;
void reverseArray(int number[], int first, int last)
{
int temp;
if (first >= last)
{
return;
}
temp = number[first];
number[first] = number[last];
number[last] = temp;
reverseArray(number, first + 1, last - 1);
}
int main()
{
//Create file objects
ifstream inputFile;
ofstream outputFile;
string inputName;
string outputName;
//Prompt user for file names
cout << "What is the name of the input file?" << endl;
getline(cin, inputName);
cout << "What would you like the output file to be called?" << endl;
getline(cin, outputName);
//open user named files
inputFile.open(inputName);
outputFile.open(outputName);
int numsFromFile;
int numbers[NUMS];
int fileCount = 0;
/*
//read in numbers from a file ********THIS WORKS BUT WHEN I CHANGE IT BELOW IT DOES NOT******
for (int count = 0; count < NUMS; count++)
{
inputFile >> number[count];
}
*/
//Try to read numbers in detecting the EOF
while (inputFile >> numsFromFile)
{
inputFile >> numbers[fileCount];
fileCount++;
}
//print numbers to screen
for (int count = 0; count < fileCount; count++)
{
cout << numbers[count] << endl;
}
//reverse array
reverseArray(numbers, 0, 4);
cout << "Reversed is: " << endl;
//print reversed array
for (int count = 0; count < NUMS; count++)
{
cout << numbers[count] << endl;
}
//output numbers to a file
for (int count = 0; count < NUMS; count++)
{
outputFile << numbers[count] << endl;
}
outputFile.close();
inputFile.close();
return 0;
}
There is a bug in the lines:
while (inputFile >> numsFromFile)
{
inputFile >> numbers[fileCount];
fileCount++;
}
You end up reading and discarding the 1st number, the 3rd number, the 5th number, etc. Change it to:
while (inputFile >> numsFromFile)
{
numbers[fileCount] = numsFromFile;
fileCount++;
}
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.
I've been working on this program for a very long time now and I think I'm close to being done. However, my code is outputting something strange and I cannot find the issue.
Expected output:
This is a happy tESt to check if my reader works!
An happy alligator was AT tHe happy park and a happy a cow blew its nose in a happy scarf. are you an happy Octagon THe
Actual output:
This is a tE happySt to check if my reader works!
a happy
THe Happy
How can I make the following code behave as I expect?
#include <iostream>
#include <string>
#include <cctype>
#include <fstream>
#include <sstream>
#include <locale>
using namespace std;
void
usage(char *progname, string msg){
cerr << "Error: " << msg << endl;
cerr << "Usage is: " << progname << " [filename]" << endl;
cerr << " specifying filename reads from that file; no filename reads standard input" << endl;
}
string capitalization(string word,string adj){
for(int i = 0; i <= word.length(); i++){
if(isupper(word[i])){
for(int j = 0; j <= adj.length(); j++){
adj[j] = toupper(adj[j]);
return adj;
}
}
else if(isupper(word[0])){
for(int j = 0; j <= adj.length(); j++){
adj[j] = tolower(adj[j]);
return adj;
}
}
else{
for(int j = 0; j <= adj.length(); j++){
adj[j] = tolower(adj[j]);
return adj;
}
}
}
}
int main(int argc, char *argv[]){
string adj;
string file;
cin >> adj;
cin >> file;
string line;
string articles[14] = {"a","A","an","aN","An","AN","the","The","tHe","thE","THe","tHE","ThE","THE"};
ifstream rfile;
rfile.open(file.c_str());
if(rfile.fail()){
cerr << "Error while attempting to open the file." << endl;
return 0;
}
string::size_type pos;
string word;
string words[1024];
while(getline(rfile,line)){
istringstream iss(line);
for(int i = 0; i <= line.length(); i++){
iss >> word;
words[i] = word;
for(int j = 0; j <= 14; j++){
if(word == articles[j]){
string article = word;
iss >> word;
pos = line.find(article);
//cout << pos << endl;
string adjec = capitalization(word,adj);
int position = (pos + word.length());
line.insert(position, " " + adjec);
continue;
}
}
}
cout << line << "\n";
}
}
This may not fix any of your problems, but...
The logic in these lines is wrong.
istringstream iss(line);
for(int i = 0; i <= line.length(); i++){
iss >> word;
Let's say your line is
This is a test.
For this line, line.length() is 15 but there aren't 15 words. What you need is
istringstream iss(line);
while ( iss >> word ) {
I'm taking a users input like so:
algo_type "pattern" filename
ex.
bf "inging" input_file.txt
As of now I separate the users input into three different variables, one for the algo_type, one for the pattern I'm looking for, and one for the filename. Once I get the pattern and filename I'm trying to take the pattern into the Bruteforce algo and search each line and print the position that pattern occurs in the line of the .txt file. Right now though every time I enter the input into the algo it returns -1 meaning the BruteForce isn't running? What exactly am I doing wrong here?
int BruteForce(const string& line, const string& pattern){
int n , m;
n = line.length();
m = pattern.length();
for(int i = 0 ; i < n - m ; i++){
int j = 0;
while( j < m && line[i + j] == pattern[j]){
j = j+1;
if( j == m){
return i;
}
}
}
return -1;
}
int main(){
string text, algo_type , pattern , fname, line;
getline(cin ,text);
istringstream iss(text);
if(iss >> algo_type >> pattern >> fname){
cout << algo_type << pattern << fname << "'\n'";
}
int i = 0;
ifstream ifs;
ifs.open(fname.c_str());
while(getline(ifs, line) && fname != ""){
if( algo_type == "bf"){
cout << "Line " << i++ << ":" << BruteForce(line,pattern) << endl;
}
}
return 0;
}
I suppose you wanted return -1 at the end of BruteForce, rather then at the end of the first iteration.
Also, the first loop condition needs to have <= instead of <, or matches ending in the very position won't be found.
Here's a complete, fixed version: EDIT as per the edit, list multiple matches within lines:
#include <string>
using namespace std;
int BruteForce(const string& line, size_t start, const string& pattern) {
const size_t n = line.length();
const size_t m = pattern.length();
if (n<m) return -1;
for(size_t i = start; i <= (n - m); i++) {
for(size_t j=0; j < m && (line[i + j] == pattern[j]); ++j) {
if(j == m-1) {
return i;
}
}
}
return -1;
}
#include <iostream>
#include <fstream>
#include <sstream>
int main() {
string text, algo_type, pattern, fname, line;
getline(cin ,text);
istringstream iss(text);
if(iss >> algo_type >> pattern >> fname) {
cout << " " << algo_type << " " << pattern << " " <<fname << "\n";
}
int i = 1;
ifstream ifs;
ifs.open(fname.c_str());
while(getline(ifs, line) && fname != "") {
if(algo_type == "bf") {
int pos = -1;
while (-1 != (pos = BruteForce(line, pos+1, pattern)))
cout << "Line " << i << ":" << pos << " " << line << endl;
}
i++;
}
return 0;
}
See it Live on Coliru: http://coliru.stacked-crooked.com/a/f1a7693d7d3bd7c5
I've tested it with
./test <<< "bf iss /etc/dictionaries-common/words" | grep Miss
Which printed
Line 10241:1 Miss
Line 10242:1 Mississauga
Line 10242:4 Mississauga
Line 10243:1 Mississippi
Line 10243:4 Mississippi
Line 10244:1 Mississippi's
Line 10244:4 Mississippi's
Line 10245:1 Mississippian
Line 10245:4 Mississippian
Line 10246:1 Mississippian's
Line 10246:4 Mississippian's
Line 10247:1 Mississippians
Line 10247:4 Mississippians
Line 10248:1 Missouri
Line 10249:1 Missouri's
Line 10250:1 Missourian
Line 10251:1 Missourian's
Line 10252:1 Missourians
Line 10253:1 Missy
Line 10254:1 Missy's