I'm building a simple interpreter of a language that i'm developing, but how i can do a cout of something that is after a word and in rounded by "", like this:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main( int argc, char* argv[] )
{
if(argc != 2)
{
cout << "Error syntax is incorrect!\nSyntax: " << argv[ 0 ] << " <file>\n";
return 0;
}
ifstream file(argv[ 1 ]);
if (!file.good()) {
cout << "File " << argv[1] << " does not exist.\n";
return 0;
}
string linha;
while(!file.eof())
{
getline(file, linha);
if(linha == "print")
{
cout << text after print;
}
}
return 0;
}
And how i can remove the "" when printing the text. Here is the file example:
print "Hello, World"
Read my post in the middle of the answers!
Thanks
I hope this simple example would help.
std::string code = " print \" hi \" ";
std::string::size_type beg = code.find("\"");
std::string::size_type end = code.find("\"", beg+1);
// end-beg-1 = the length of the string between ""
std::cout << code.substr(beg+1, end-beg-1);
This code finds the first occurnce of ". Then finds the next occurrence of it after the first one. Finally, it extracts the desired string between "" and prints it.
I'm assuming what you want is to identify quoted strings in the file, and print them without the quotes. If so, the below snippet should do the trick.
This goes in your while(!file.eof()) loop:
string linha;
while(!file.eof())
{
getline(file, linha);
string::size_type idx = linha.find("\""); //find the first quote on the line
while ( idx != string::npos ) {
string::size_type idx_end = linha.find("\"",idx+1); //end of quote
string quotes;
quotes.assign(linha,idx,idx_end-idx+1);
// do not print the start and end " strings
cout << "quotes:" << quotes.substr(1,quotes.length()-2) << endl;
//check for another quote on the same line
idx = linha.find("\"",idx_end+1);
}
}
I don't understand your problem. On input of
print "Hello, World"
your test of linha == "print" will never be true (as linha contains the rest of the line so the equalitry is never true).
Are you looking for help on string processing, i.e. splitting of the input line?
Or are you looking for regular expression help? There are libraries you can use for the latter.
Related
I've read the lines from a textfile and i want to check if that line contains the $ sign.
That's what i got so far:
int main() {
ifstream data_store;
string line;
data_store.open("c:\\test.txt");
while (!data_store.eof())
{
getline(data_store, line);
if (line.find("$"))
cout << "1: " << line << endl;
}
data_store.close();
system("PAUSE");
return 0;
}
Furthermore how can i output them to a file ?
To check if a line contains something using std::string::find to need to check the returned value from find to make sure it is a valid return. To do that we compare it against std::string::npos as that is what find() will return if it does not find anything. This is the reason it finds every line as std::string::npos is still considered true when evaluated as a bool. So refactoring your code you would have:
while (getline(data_store, line))
{
if (line.find("$") != std::string::npos)
cout << "1: " << line << endl;
}
I also changed the while loop as using eof is not how to control a while loop. for more information on that see Why is “while ( !feof (file) )” always wrong?
As far as outputting the string to a file see: How to write std::string to file?
It's a minor thing, but a variant of #NathanOliver's solution, is to use a for loop:
ifstream data_store("c:\\test.txt");
for ( string line; getline(data_store, line); ) {
if ( line.find("$") != string::npos )
cout << "1: " << line << endl;
}
// ...
The benefit here is that line is now local only to the loop, which is what it should be since that is the only place it is used.
I did it yesterday forgot to update.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool contains_number(const string &c);
int main()
{
int count = 0;
{
string line1[100];
ifstream myfile("D:/Users/Jarvan/Desktop/test.txt");
int a = 0;
if (!myfile)
{
cout << "Error opening output file" << endl;
system("pause");
return -1;
}
while (!myfile.eof())
{
getline(myfile, line1[a], '\n');
if (contains_number(line1[a]))
{
count += 1;
cout << line1[a] << "\n";
}
else cout << "\n";
}
}
cout << count <<endl;
system("pause");
return 0;
}
bool contains_number(const string &c)
{
return (c.find_first_of("$") != string::npos);
}
I want to read data from stream, which has specific format, such as:
"number:name_that_can_contain_spaces:string,string,string..." without quotes where ... means that I dont know how many strings are there separated with commas and strings can have spaces before and after it but not in the middle of string, I want to stop reading at new line
I only come up with using getline() and store each line into string, but I dont know how to continue, if there is something like strtok(line, ":",":",",","\n") which would parse it for me or I have to parse it myself character by character
example of valid line format is:
54485965:abc abc abc: some string, next string , third string\n
parsed result would be:
int 54485965
string "abc abc abc"
string "some string"
string "next string"
string "third string"
You can read line with std::getline and then split it with std::string::find and std::string::substr. In the code below we read line from file data, then find : (so everything before it becomes number which we parse into int with std::stoi) and throw away first part. Similar we do it with name. And in the end we fill std::list with strings separated by ,.
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <exception>
#include <stdexcept>
struct entry {
std::string name;
int number;
std::list<std::string> others;
};
int main(int argc, char** argv) {
std::ifstream input("data");
std::list<entry> list;
std::string line;
while(std::getline(input, line)) {
entry e;
std::string::size_type i = 0;
/* get number from line */
i = line.find(":");
if(i != std::string::npos) {
e.number = stoi(line.substr(0, i));
line = line.substr(i + 1);
} else {
throw std::runtime_error("error reading file");
}
/* get name from line */
i = line.find(":");
if(i != std::string::npos) {
e.name = line.substr(0, i);
line = line.substr(i + 1);
} else {
throw std::runtime_error("error reading file");
}
/* get other strings */
do {
i = line.find(",");
e.others.push_back(line.substr(0, i));
line = line.substr(i + 1);
} while(i != std::string::npos);
list.push_back(e);
}
/* output data */
for(entry& e : list) {
std::cout << "name: " << e.name << std::endl;
std::cout << "number: " << e.number << std::endl;
std::cout << "others: ";
for(std::string& s : e.others) {
std::cout << s << ",";
}
std::cout << std::endl;
}
return 0;
}
I'm reading in information from a file. I need a counter that counts how many text filled lines there are. I need that counter to stop if there is any blank line (even if there are text filled lines after that blank line).
How would I do this? Because I'm not exactly sure how to identify a blank line to stop the counter there.
If you are using std::getline then you can just detect an empty line by checking if the std::string you have just read is empty.
std::ifstream stream;
stream.open("file.txt");
std::string text;
while(std::getline(stream,text))
if(!text.size())
std::cout << "empty" << std::endl;
I'd suggest using std::getline for it:
#include <string>
#include <iostream>
int main()
{
unsigned counter = 0;
std::string line;
while (std::getline(std::cin, line) && line != "")
++counter;
std::cout << counter << std::endl;
return 0;
}
Since #Edward made a comment about handling whitespace and it might be important. When lines with only whitespaces are considered as "empty lines" too I'd suggest changing it to:
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
int main()
{
unsigned counter = 0;
std::string line;
while (std::getline(std::cin, line) &&
std::find_if_not( line.begin(), line.end(), std::isspace != line.end()) {
++counter;
}
std::cout << counter << std::endl;
return 0;
}
It's quite verbose, but the advantage is that it uses std::isspace to handle all different kind of spaces (e.g. ' ', '\t', '\v', etc...) and you don't have to worry if you handle them correctly.
In C++ 11 you can use,
std::isblank
In a loop, read all lines, one-by-one, into a single string variable. You can use a std::getline function for that.
Each time after reading a line into that variable, check its length. If it's zero, then the line is empty, and in that case break the loop.
However, checking for empty lines like is not always really right thing. If you are sure that the lines will be empty, then it's OK. But if your "empty" lines can contain whitespaces,
123 2 312 3213
12 3123 123
// <--- Here are SPACEs. Is it "empty"?
123 123 213
123 21312 3
then you might need to not check for "zero-length", but rather whether "all characters are whitespaces".
No error checking, no protection, just a simple example... It is not tested, but you get the gist.
#incldue <iostream>
#include <string>
using namespace std;
int main()
{
string str = "";
int blank = 0, text = 0;
ifstream myfile;
myfile.open("pathToFile");
while(getline(myfile,str))
{
if(str == "")
{
++blank;
}
else
{
++text;
}
}
cout << "Blank: " << blank << "\t" << "With text: " << text;
return 0;
}
Simply check the string length and use a line counter. When the string length is zero (i.e., the string is blank) print the line counter. Sample code is provided for your reference:
// Reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
int i = 0;
if (myfile.is_open())
{
while (getline (myfile, line))
{
i++;
// cout << line << '\n';
if (line.length() == 0)
break;
}
cout << "blank line found at line no. " << i << "\n";
myfile.close();
}
else
cout << "Unable to open file";
return 0;
}
I'm creating a program that will open a file and search for a desired word within the text.
I created the following word bank...
Lawyer
Smith Janes
Doctor
Michael Zane
Teacher
Maria Omaha
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;
int main ()
{
// Declarations
string reply;
string inputFileName;
ifstream inputFile;
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;
}
Now that I save the whole file into a string how could I search inside that string
for a specific word I'm looking for...
I'm learning C++ from this Website http://www.cprogramming.com/tutorial/lesson10.html
I think you use string::find but I couldn't find much reference on how to search beside this wesite..
http://www.cplusplus.com/reference/string/string/find/
This section will display the whole file.
string original;
getline(inputFile, original, '\0');
cout << original << endl;
cout << "\nEnd of file reached\n" << endl;
// Close the input file stream
inputFile.close();
cout << "Press enter to continue...";
return 0;
}
This is how I think the program should act...
Please enter a word: Smith Janes
Smith Janes Lawyer
another example....
Please enter a word: Doctor
Michael Zane Doctor
find returns the position (zero based offset) in the string where the word is found. If the word is not found it returns npos.
#include <string>
#include <iostream>
int main()
{
std::string haystack("some string with words in it");
std::string::size_type pos = haystack.find("words");
if(pos != std::string::npos)
{
std::cout << "found \"words\" at position " << pos << std::endl;
}
else
{
std::cout << "\"words\" not found" << std::endl;
}
}
#include <string>
#include <iostream>
#include <cstdlib>
int main() {
std::string haystack = "Lawyer\nSmith Janes\nDoctor\nMichael Zane\nTeacher\nMaria Omaha\n";
std::string needle = "Janes";
auto res = haystack.find(needle);
if (std::string::npos == res) {
std::cout << "Not found\n";
std::exit(EXIT_FAILURE);
}
std::cout << res << '\n';
}
res is an index into the string at the point where "Janes" is (Should be 13).
The functionality you appear to be asking for is more complex than just finding some content in a string. The output you show has a user input either a name or a profession and the output is the related profession or name.
It's simple to write a program that shows the line the 'needle' is on, or to show always show the previous line, or always show the next line. But what you're asking for is to show one or the other depending on what was searched for.
One simple way we could implement this is to find if the needle is on an even or odd line and base what we show on that.
First we get the line number.
auto line_num = std::count(std::begin(haystack), std::begin(haystack) + res, '\n');
Based on the content you showed, professions are on even lines and names are on odd lines. We can easily get the line numbers we want:
auto profession_line_num = line_num/2*2;
auto name_line_num = line_num/2*2 + 1;
Next, we can split the text up into lines since we need to work with whole lines and get lines by index. The method I show below makes a copy of the text and is inefficient, but it's easy.
Here's a split function:
std::vector<std::string> split(std::string const &s, std::string const &delims) {
std::vector<std::string> res;
std::string::size_type i = 0;
auto found = s.find_first_of(delims, i);
while (std::string::npos != found) {
res.emplace_back(s, i, found-i);
i = found+1;
found = s.find_first_of(delims, i);
}
res.emplace_back(s, i);
return res;
}
And we use the split function like so:
auto lines = split(haystack, '\n');
Now, we can show the lines we want.
std::cout << lines[name_line_num] << ' ' << lines[profession_line_num] << '\n';
Which once you put the program together prints:
Smith Janes Lawyer
I think this has all the information you need.
http://www.cplusplus.com/reference/string/string/find/
vector<string> wordstocheck;
in.open("readin.txt");
string line;
string word = "";
int linecount = 0;
while (getline(in, line))
{
//cout << line << endl;
for (int i = 0; i < line.size(); i++)
{
if(isalpha(line[i]))
{
word.push_back(tolower(line[i]));
}
else if (line[i] == ' ' || ispunct(line[i]) || line[i] == '\n')
{
wordstocheck.push_back(word);
word = "";
}
}
linecount++;
}
for (int i = 0; i < wordstocheck.size(); i++)
{
cout << wordstocheck[i] << endl;
}
system("pause");
}
The code above reads in the following from a .txt file:
If debugging is the
process of removing bugs.
Then programming must be the
process of putting them in.
I'm trying to get the program to recognize each word, and save that individual word into a vector, and then print that vector of words out. It does pretty well with the exception of the two 'the's on the first and third lines.
Output:
if
debugging
is
theprocess
of
removing
bugs
then
programming
must
be
theprocess
of
putting
them
in
Press any key to continue . . .
It doesn't split up "theprocess" as I had hoped.
getline won't read the newline. However, in this case it's relatively simple to work around this problem.
Where you currently have linecount++;, add these lines before it:
if (word != "")
{
wordstocheck.push_back(word);
word = "";
}
You may want to use the same if (word != "") on the first place where you push the word onto wordstocheck since if the text has "A Word", you'd add the word "A" followed by an empty word for as the seconds space triggers the word to be added to the list.
As an alternative, you could get rid of getline, and just use int ch = in.get() to read a character at a time from the input. Then instead of counting lines inside the while()..., and use ch instead of line[i] al through the loop, and then add a second if inside the else if section, which checks for newline and counts up linecount. This would probably make for shorter code.
I believe the problem is that you're expecting the newline character to be included in the result from getline(), which it isn't. It seems like if you take the two lines you already have in that block:
wordstocheck.push_back(word);
word = "";
And add them alongside the line:
linecount++;
Then it should work as you expect.
If you want to read a word at a time, why use std::getline in the first place?
// read the words into a vector of strings:
std::vector<std::string> words{std::istream_iterator<std::string(in),
std::istream_iterator<std::string()};
You can use std::for_each or std::transform to convert everything to lower case, and finally print them out with for (auto const &w : words) std::cout << w << "\n";
So far i know, getline reads a whole line and does not recognize a carriage return. The only way i know is to read the file, by read it char by char.
Here is a example that gives the correct result:
#include <iostream> // std::cin, std::cout
#include <fstream> // std::ifstream
int main ()
{
char str[256];
int line = 1;
int charcount = 0;
std::cout << "Enter the name of an existing text file: ";
std::cin.get (str,256);
std::ifstream is(str);
if (!is)
{
std::cerr << "Error opening file!" << std::endl;
return -1;
}
char c;
while ((c = is.get()) && is.good()) // loop while extraction from file if possible
{
if (c == 10 || c == 13 || c == 32) // if it is a line break or carriage return or space
{
std::cout << std::endl;
line++;
}
else // everything else
{
std::cout << c;
charcount++;
}
}
is.close();
std::cout << std::endl; // close file
std::cout << line << " lines" << std::endl;
std::cout << charcount << " chars" << std::endl;
return 0;
}