Parsing out things surrounded by quotes in C++ - c++

I'm trying to make a parser that would only take text surrounded by quotes and place it in a new file I've already tried many times but can't figure it out it would have to take the original text out of a file by the way then place it in a new file I would like to do this in C++.
This is what I currently have:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char current_letter;
char quote_mark = '"';
int isquote = 0;
std::cin >> current_letter;
LOOP : do
{
if(current_letter == quote_mark) {++isquote;}
if(isquote == 1 && current_letter != quote_mark) {std::cout << current_letter;}
if(isquote == 1 && current_letter == quote_mark) {--isquote;}
if(isquote == 0) {goto LOOP;}
} while (cin >> current_letter);
if(cin != current_letter) {cout << "END" <<endl;}
return(0);
It doesn't print anything now but it used to print out random stuff or just quote marks.

You could just do something like this:
string str;
getline(cin, str);
string currStr = "";
for (int i = 0; i < str.length(); i++)
{
if (str[i] != '\"') currStr += str[i];
}
cout << currStr << "\n";
This won't work if there are double quotes within the text that you want to parse however.

Related

Creating program to find repeated words in a sentence

I'm having trouble with this project because when I put a sentence such as "cat is not a dog", it will not say "Didn't find repeated word" as intended. Instead, it will say "Found repeated word", as if I it was true. Also, each time it is run for the first time, the first letter is removed from the user input. Why?
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <time.h>
#include <stdio.h>
using namespace std;
int main()
{
int count = 0;
bool repeat = false;
char yn;
string input, newWord, firstword;
do
{
count = 0;
repeat = false;
cin.sync();
cout << "Please enter a sentence: ";
cin.ignore();
getline(cin, input);
while (input.at(count) != ' ')
count++;
firstword = input.substr(0, count);
input = input.substr(count++);
count = 0;
while(count < input.size() && repeat == false)
{
count++;
while (count < input.size() && input.at(count) != ' ')
count++;
newWord = input.substr(0, count);
if (firstword.compare(newWord) == 0)
input = input.substr(count++);
else
repeat = true;
}
if (repeat == true)
{
cout << "\nI found a repeated word!";
cout << "\nWould you like to try again? (y/n)";
cin >> yn;
}
else if(repeat == false)
{
cout << "\nI didn't find a repeated word.";
cout << "\nWould you like to try again? (y/n)";
cin >> yn;
}
} while (yn == 'y');
}
You program only checks if the first word is repeated annywhere else in the sentence...
Looking for a repeated word being: Each word must be checked against its immediate predecessor.
You're almost there. You forgot to reassign firstWord to newWord at te end of the parsing loop.
while(count < input.size() && repeat == false)
{
// ...
newWord = input.substr(0, count);
if (firstword.compare(newWord) == 0)
input = input.substr(count++);
else
repeat = true;
firstWord = newWord; // <-- Assign here.
}
Just an aside note, a trick of the trade, if you will.
if (repeat == true)
//...
else if(repeat == false) // <- Avoid doing that. Use plain else for booleans.
A bool can only have two values. And this kind of else if construct will bring unexpected surprises when plain ints are used for boolean equations. (if repeat was 3, which path does each cases of 0, 1, 3 follow?)
Have you tried removing the call to std::cin.sync() ?
Print your input after getline to be sure it's correctly saved. You probably don't need cin.ignore();. The first character is not saved.
An alternative sollution would be to use the following:
#include <iostream>
#include <string>
#include <fstream>
#include <map>
#include <sstream>
using namespace std;
int main()
{
int pos = 0;
string input;
cout << "Please enter a sentence: ";
getline(cin, input);
map<string, int> count_words;
stringstream ss(input);
string word;
while(getline(ss, word, ' '))
count_words[word]++;
map<string, int>::const_iterator it;
for(it = count_words.begin() ; it != count_words.end() ; ++it)
if( it->second == 2)
cout << "Found duplicate: " << it->first << endl;
return 0;
}
this answer(https://stackoverflow.com/a/236803/4388908) provides a good method to split your input.
The rest: Programming Pearls by Jon Bentley

I need to convert some code so that it works with an input and output file text

I have a program that reverses the letters in a sentence but keeps the words in the same order. I need to change the code from an iostream library to an fstream library where the user inputs a sentence into an input file("input.txt") and the program outputs the reverse into an output text file.
example of input:
This problem is too easy for me. I am an amazing programmer. Do you agree?
Example of output:
sihT melborp si oot ysae rof em. I ma na gnizama remmargorp. oD uoy eerga?
The code I already have:
int main()
{
int i=0, j=0, k=0, l=0;
char x[14] = "I LOVE CODING";
char y[14] = {'\0'};
for(i=0; i<=14; i++) {
if(x[i]==' ' || x[i]=='\0') {
for(j=i-1; j>=l; j--)
y[k++] = x[j];
y[k++] = ' ';
l=i+1;
}
}
cout << y;
return 0;
}
I would use std::string to store the string, and benefit from std::vector and const_iterator to make better use of C++ features:
#include <string>
#include <vector>
int main()
{
std::string s("This problem is too easy for me. I am an amazing programmer. Do you agree?");
const char delim = ' ';
std::vector<std::string> v;
std::string tmp;
for(std::string::const_iterator i = s.begin(); i <= s.end(); ++i)
{
if(*i != delim && i != s.end())
{
tmp += *i;
}else
{
v.push_back(tmp);
tmp = "";
}
}
for(std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it)
{
std::string str = *it,b;
for(int i=str.size()-1;i>=0;i--)
b+=str[i];
std::cout << b << " ";
}
std::cout << std::endl;
}
Output:
sihT melborp si oot ysae rof .em I ma na gnizama .remmargorp oD uoy ?eerga
The code that you submitted looks much more like something from C rather than from C++. Not sure if you are familiar std::string and function calls. As the code you wrote is pretty sophisticated, I will assume that you are.
Here is an example of how to use fstream. I almost always you getline for the input because I find that it gets me into fewer problems.
I then almost always use stringstream for parsing the line because it neatly splits the lines at each space.
Finally, I try to figure out a while() or do{}while(); loop that will trigger off of the input from the getline() call.
Note that if the word ends in a punctuation character, to keep the punctuation at the end, the reverse_word() function has to look for non-alpha characters at the end and then save that aside. This could be done by only reversing runs of alphas.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
///////////////////
/// return true if ch is alpha
/// return false for digits, punctuation, and all else
bool is_letter(char ch){
if((ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z')) {
return true;
} else {
return false;
}
}
////////
// Only reverse the letter portion of each word
//
std::string reverse_word(std::string str)
{
std::string output_str; // Probably have to create a copy for output
output_str.reserve(str.length()); // reserve size equal to input string
// iterate through each letter of the string, backwards,
// and copy the letters to the new string
char save_non_alpha = 0;
for (auto it = str.rbegin(); it != str.rend(); it++) {
/// If the last character is punctuation, then save it to paste on the end
if(it == str.rbegin() && !is_letter(*it)) {
save_non_alpha = *it;
} else {
output_str += *it;
}
}
if(save_non_alpha != 0) {
output_str += save_non_alpha;
}
return output_str; // send string back to caller
}
int main()
{
std::string input_file_name{"input.txt"};
std::string output_file_name{"output.txt"};
std::string input_line;
std::ifstream inFile;
std::ofstream outFile;
inFile.open(input_file_name, std::ios::in);
outFile.open(output_file_name, std::ios::out);
// if the file open failed, then exit
if (!inFile.is_open() || !outFile.is_open()) {
std::cout << "File " << input_file_name
<< " or file " << output_file_name
<< " could not be opened...exiting\n";
return -1;
}
while (std::getline(inFile, input_line)) {
std::string word;
std::string sentence;
std::stringstream stream(input_line);
// I just like stringstreams. Process the input_line
// as a series of words from stringstream. Stringstream
// will split on whitespace. Punctuation will be reversed with the
// word that it is touching
while (stream >> word) {
if(!sentence.empty()) // add a space before all but the first word
sentence += " ";
word = reverse_word(word);
sentence += word;
}
outFile << sentence << std::endl;
}
inFile.close();
outFile.close();
return 0;
}

print 2nd word in a string with its size in C++

I am trying to make a program in which a user enters a string and i will print out the second word in the string with its size.
The delimiter's are space( ), comma(,) and tab( ).
I have used a character array and fgets to read from user and a character pointer that points to the first element of the array.
source code:
#include"iostream"
#include<stdio.h>
#include<string>
using namespace std;
// extract the 2nd word from a string and print it with its size(the number of characters in 2nd word)
int main()
{
char arr[30], arr1[30];
char *str = &arr1[0];
cout<<"Enter a string: ";
fgets(str, 30, stdin);
int i = 0, j, count = 1, p = 0; // count is used to find the second word
// j points to the next index where the first delimiter is found.
// p is used to store the second word found in character array 'arr'
while(*(str+i) != '\n')
{
if(*(str+i) == ' ' || *(str+i) == ',' || *(str+i) == ' ')
{
count++;
if(count == 2)
{
// stroing 2nd word in arr character array
j = i+1;
while(*(str+j) != ' ' || *(str+j) != ',' || *(str+j) != ' ')
{
arr[p] = *(str+j);
cout<<arr[p];
p++;
i++;
j++;
}
break;
}
}
i++;
}
arr[p+1] = '\0'; // insert NULL at end
i = 0;
while(arr[i] != '\0')
{
cout<<arr[i];
i++;
}
cout<<"("<<i<<")"<<endl;
return 0;
}
Help me out with this.
To start, don't use std::cin for testing. Just set a value in your code for consistency and ease of development. Use this page for a reference.
#include <iostream>
#include <string>
int main() {
std::string str("this and_that are the tests");
auto start = str.find_first_of(" ,\n", 0);
auto end = str.find_first_of(" ,\n", start + 1);
std::cout << str.substr(start, end - start);
return 0;
}
And this is still somewhat of a hack, it just depends where you are going. For instance the Boost library is rich with extended string manipulation. If you are going to parse out more than just one word it can still be done with string manipulations, but ad-hoc parsers can get out of hand. There are other tools like Boost Spirit to keep code under control.
The delimiters used when extracting from a stream depends on the locale currently in effect. One (cumbersome) way to change the extraction behaviour is to create a new locale with a special facet in which you specify your own delimiters. In the below example the new locale is used to imbue a std::stringstream instead of std::cin directly. The facet creation part is mostly copy/paste from other answers here on SO, so you'll find plenty of other examples.
#include <iostream>
#include <locale> // std::locale, std::ctype<char>
// https://en.cppreference.com/w/cpp/locale/ctype_char
#include <sstream> // std::stringstream
#include <algorithm> // std::copy_n
#include <vector> // a container to store stuff in
// facet to create our own delimiters
class my_facet : public std::ctype<char> {
mask my_table[table_size];
public:
my_facet(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
// copy the "C" locales table to my_table
std::copy_n(classic_table(), table_size, my_table);
// and create our delimiter specification
my_table[' '] = (mask)space;
my_table['\t'] = (mask)space;
my_table[','] = (mask)space;
}
};
int main() {
std::stringstream ss;
// create a locale with our special facet
std::locale loc(std::locale(), new my_facet);
// imbue the new locale on the stringstream
ss.imbue(loc);
while(true) {
std::string line;
std::cout << "Enter sentence: ";
if(std::getline(std::cin, line)) {
ss.clear(); // clear the string stream from prior errors etc.
ss.str(line); // assign the line to the string stream
std::vector<std::string> words; // std::string container to store all words in
std::string word; // for extracting one word
while(ss>>word) { // extract one word at a time using the special facet
std::cout << " \"" << word << "\" is " << word.size() << " chars\n";
// put the word in our container
words.emplace_back(std::move(word));
}
if(words.size()>=2) {
std::cout << "The second word, \"" << words[1] << "\", is " << words[1].size() << " chars\n";
} else {
std::cout << "did not get 2 words or more...\n";
}
} else break;
}
}
#include"iostream"
#include<stdio.h>
#include<string>
#include <ctype.h>
using namespace std;
int main()
{
char c;
string str;
char emp = ' ';
cout<<"Enter a string: ";
getline (cin,str);
int j = 0, count = 1, counter = 0;
for (int i = 0; i < str.length() && count != 2; i++)
{
cout<< str[i] <<endl;
if( isspace(str[i]) || str[i] == ',' || str[i] == '\t' )
{
count++;
if(count == 2)
{
j = i+1;
while(j < str.length())
{
if (isspace(str[j]) || str[j] == ',' || str[j] == '\t')
{
break;
}
cout<<str[j];
counter++;
j++;
}
cout<<endl;
}
}
}
cout<<"size of the word: "<<counter<<endl;
return 0;
}
This is a simple answer to what you want, hope to help you.
// Paul Adrian P. Delos Santos - BS Electronics Engineering
// Exercise on Strings
#include <iostream>
#include <sstream>
using namespace std;
int main(){
// Opening Message
cout << "This program will display the second word and its length.\n\n";
// Ask for a string to the user.
string input;
cout << "Now, please enter a phrase or sentence: ";
getline(cin, input);
// Count the number of words to be used in making a string array.
int count = 0;
int i;
for (i=0; input[i] != '\0'; i++){
if (input[i] == ' ')
count++;
}
int finalCount = count + 1;
// Store each word in a string array.
string arr[finalCount];
int j = 0;
stringstream ssin(input);
while (ssin.good() && j < finalCount){
ssin >> arr[j];
j++;
}
// Display the second word and its length.
string secondWord = arr[1];
cout << "\nResult: " << arr[1] << " (" << secondWord.size() << ")";
return 0;
}

C++ program need lines words and characters count

I have an assignment where i need to count lines, words and characters from a file. I'm having a problem counting the right amount of characters and words since if it gets doubled space it counts like a character and a word.
the output should be
Example
lines words characters filename
3 5 29 testfile
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <iomanip>
using namespace std;
int main(int argc, const char * argv[]) {
string lines, words, chars, file1, file2;
ifstream infile;
ofstream outfile;
char c;
int countLines = 0;
int countChars = 0;
int countWords = 0;
cout<< "Enter the file name" << endl;
cin >> file1;
infile.open(file1.c_str());
while(!infile.eof())
{
if(infile.peek() == 1)
break;
c = infile.get();
if(c != '\n')
countChars++;
else
countLines++;
if(c == ' '|| c =='\n')
countWords++;
}
// countChars = countChars - countWords;
cout << setw(12) << countLines << setw(12) << countWords << setw(12) << countChars << endl;
infile.close();
return 0;
}
Use getline for reading file line by line
while(getline(file,str))
{
countLines++;
countChars += str.length();
countWords += CountWords(str);
}
Which file is an iofstream object and str is a string. And for counting number of words(CountWords), you have several ways. One of them is:
#include <vector>
#include <string>
#include <boost/algorithm/string/split.hpp>
int countWords(std::string str) {
vector< std::string > result;
boost::algorithm::split_regex(result, str, regex( "\\s+" ));
return result.size();
}
I believe OP's purpose to ask this question is to find out why his/her code is not working, therefore I will answer in this perspective.
counting the right amount of words
C++ define EOF(end of file) as -1, so include a check for EOF too, or you will miss a word count.
if it gets doubled space it counts like a character and a word.
You can use a boolean test to solve this, if you encountered a space, turn on the boolean, and skip if next char is a space, too.
I suppose your character count doesn't count in punctuation? so check for c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'. If your assignment count punctuation as character count too, ignore this point.
Below is a correct version code that is modified based on your code.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <iomanip>
using namespace std;
int main(int argc, const char * argv[]) {
string lines, words, chars, file1, file2;
ifstream infile;
ofstream outfile;
char c;
bool findNextString = false;
int countLines = 0;
int countChars = 0;
int countWords = 0;
cout << "Enter the file name" << endl;
cin >> file1;
infile.open(file1.c_str());
while (!infile.eof())
{
if (infile.peek() == 1)
break;
c = infile.get();
// use the boolean to find next valid string
if (findNextString && c == ' ')
continue;
else
findNextString = false;
// there is a structure issue with your code.
// you should think of the priority of checking
// do not check by rejection, because you will count in punctuation too.
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
{
countChars++;
}
else if (c == '\n')
{
countLines++;
countWords++; // <- add word too
}
else if (c == ' ' || c == EOF)
{
countWords++;
findNextString = true;
}
}
cout << setw(12) << countLines << setw(12) << countWords << setw(12) << countChars << endl;
infile.close();
return 0;
}

String subscript out of range error "C++"

This program takes a text file and changes each word into pig Latin. I have gotten everything to work but continue to get the error "subscript out of range". I have tried to change many things but cant get it to go away. Can someone explain why I am getting this error?
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
void piglatin ( string word[], string temp, ifstream & in, int num);
int main()
{
string word[300];
string original[300];
string temp;
ifstream in;
int i=0,
j=0,
x=0,
par=0,
length=0;
in.open("text.txt");
if (in.is_open()) { //Checks if file is open
cout << "\nFile is open....\n\n\n";
} else {
cout << "Error: Failed to open!\n";
cout << "Exiting program\n";
exit(-1);
}
cout<<"Original text\n\n";
do {//Continues while loop until no more input.
in >> original[x];
cout << original[x] << " ";
x++;
par = par + x;
} while (!in.eof());
cout<<"\n\n";
cout<<"Pig Latin\n\n";
piglatin(original,temp,in,par);
return 0;
}
void piglatin ( string word[], string temp, ifstream & in, int num)
{
int i=0, length, j=0,a=0;
for(j = 0; j < num; j++) {
string str (word[j]);
length = str.size();
temp[0] = word[j][0];
if ((temp[0] == 'a') ||
(temp[0] == 'e') ||
(temp[0] == 'i') ||
(temp[0] == 'o') ||
(temp[0] == 'u'))
{
word[j] += "way";
} else {
for(i = 0; i <= length-1; i++) {
word[j][i] = word[j][i+1];
}
word[j][length-1] = temp[0];
word[j] += "ay";
}
cout << word[j] << " ";
length = 0;
}
cout << "\n\n";
}
This statement
temp[0] = word[j][0];
is invalid because string temp is empty and you may not use the subscript operator with empty strings to store a character.
You could write before the for loop for example
temp.resize( 1 );
Also I do not see any sense in the parameter temp. Instead of string temp you could use in the function local variable char temp; because you are using temp only to store one character.
I believe you are missing a parameter to the ifstream: The ifstream object requires two parameters, a filename and a mode which describes the requested i/o mode for the file.
in.open("text.txt");
Should be:
in.open("text.txt", ifstream::in);
Here is a link to the API for ifstream.open:
http://www.cplusplus.com/reference/fstream/ifstream/open/