C++ How do i check for delimiter in this text file - c++

i am new to C++. I would like to know how do i create a function to check for delimiter.
such as the case below
AD,Andorra,AN,AD,AND,20.00,Andorra la Vella,Europe,Euro,EUR,67627.00
AE,United Arab Emirates,AE,AE,ARE,784.00,Abu Dhabi,Middle East,UAE Dirham,AED,2407460.00
AF,Afghanistan,AF,AF,AFG,4.00,Kabul,Asia,Afghani,AFA,26813057.00
If the delimiter become $ or # instead of comma , how do i create a function to check for it and say , wrong format of text file.
Thanks!
Below is my readData code
void readData ()
{
FILE * pFile;
NoOfRecordsRead = 0;
char buffer [Line_Char_Buffer_Size];
pFile = fopen (INPUT_FILE_NAME , "r");
if (pFile == NULL)
perror ("Error opening file 'Countries.txt' !");
else
{
while ( !feof (pFile) )
{
char* aLine = get_line (buffer, Line_Char_Buffer_Size, pFile);
if (aLine != NULL)
{
// printf ("%d] aLine => %s\n", NoOfRecordsRead, aLine);
globalCountryDataArray [NoOfRecordsRead++] = createCountryRecord (aLine);
}
}
fclose (pFile);
}
}

#include <string>
#include <fstream>
#include <algorithm>
bool detect_comma(std::string file_name)
{
// open C++ stream to file
std::ifstream file(file_name.c_str());
// file not opened, return false
if(!file.is_open()) return false;
// read a line from the file
std::string wtf;
std::istream &in= std::getline(file, wtf);
// unable to read the line, return false
if(!in) return false;
// try to find a comma, return true if comma is found within the string
return std::find(wtf.begin(), wtf.end(), ',')!= wtf.end();
}
#include <iostream>
#include <cstdlib>
int main()
{
if(!detect_comma("yourfile.dat"))
{
std::cerr<< "File is not comma delimited!\n";
return EXIT_FAILURE;
}
// file is OK, open it and start reading
}
Edit: Added comments & example code

You would need a reliable way to find a location that you always expect the delimiter to be. If the first field is always 2 characters wide, you can check to see if the 3rd character is a ,. Otherwise, you can scan backwards on the first line of text to see if the first non-currency related character is a ,.
Edit: Your readData routine is very C-centric, as has been pointed out in comments. You can simplify it considerably by using C++ features.
std::string aLine;
std::ifstream pfile(INPUT_FILE_NAME);
while (pfile) {
std::getline(pfile, aLine);
if (aLine.size()) {
globalCountryDataArray.push_back(createCountryRecord(aLine));
}
}

A good way to perform your check is using the Boost.Regex library. You only have to define your regular expression and perform a check if your input matches the expression.
Sample code:
#include <string>
#include <boost/regex.hpp>
using namespace std;
int main()
{
const string input("AD,Andorra,AN,AD,AND,20.00,Andorra la Vella,Europe,Euro,EUR,67627.00");
const boost::regex ex("(?:(?!,)(\\d+\\.\\d*)|(\\w|\\s)*)(,(?:(?!,)(\\d+\\.\\d*)|(\\w|\\s)*))*");
cout << boost::regex_match(input.c_str(), ex) << endl;
return 0;
}
By the way: I'm not a regex expert so validate the expression :-)

Related

How to skip blank line when reading file in C++?

I want to skip blank line when readhing a file.
I've tried if(buffer == "\n") and if(buffer.empty()), but it not work. I did like this:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream file_pointer;
file_pointer.open("rules.txt", ios::in);
if(!file_pointer.is_open())
{
cout << "failed to read rule file." << endl;
return 0;
}
string buffer;
while(getline(file_pointer, buffer))
{
if(buffer.empty())
{
continue;
}
if(buffer == "\n")
{
continue;
}
cout << buffer << endl;
}
file_pointer.close();
return 0;
}
The problem is that a “blank” line need not be “empty”.
#include <algorithm> // std::any_of
#include <cctype> // std::isspace
#include <fstream>
#include <iostream>
//using namespace std;
bool is_blank( const std::string & s )
{
return std::all_of( s.begin(), s.end(), []( unsigned char c )
{
return std::isspace( c );
} );
}
int main()
{
std::ifstream rules_file("rules.txt");
if(!rules_file)
{
std::cerr << "failed to read rule file." << endl;
return 1;
}
std::string line;
while(getline(rules_file, line))
{
if(is_blank(line))
{
continue;
}
std::cout << line << "\n";
}
return 0;
}
A few notes.
Get used to writing std:: infront of things from the Standard Library. Importing everything en masse with using namespace std is almost always a bad idea.
C++ file streams are not pointers. Moreover, be descriptive with your names! It makes reading your code easier for your future self. Honest!
Open a file at the file stream object creation. Let it close at object destruction (which you did).
Report errors to standard error and signal program failure by returning 1 from main().
Print normal output to standard output and signal program success by returing 0 from main().
It is likely that std::any_of() and lambdas are probably not something you have studied yet. There are all kinds of ways that is_blank() could have been written:
bool is_blank( const std::string & s )
{
for (char c : s)
if (!std::isspace( (unsigned char)c ))
return false;
return true;
}
Or:
bool is_blank( const std::string & s )
{
return s.find_first_not_of( " \f\n\r\t\v" ) == s.npos;
}
Etc.
The reason that the checking for newline didn’t work is that getline() removes the newline character(s) from the input stream but does not store it/them in the target string. (Unlike fgets(), which does store the newline so that you know that you got an entire line of text from the user.) C++ is much more convenient in this respect.
Overall, you look to be off to a good start. I really recommend you make yourself familiar with a good reference and look up the functions you wish to use. Even now, after 30+ years of this, I still look them up when I use them.
One way to find good stuff is to just type the name of the function in at Google: “cppreference.com getline” will take you to the ur-reference site.
https://en.cppreference.com — “the” C and C++ reference site
https://cplusplus.com/reference/ — also good, often an easier read for beginners than cppreference.com
https://www.learncpp.com/ — a good site to learn how to do things in C++
You can skip blank lines when reading a file in C++ by using the getline() function and checking the length of the resulting string. Here is an example of how you can do this:
#include <fstream>
#include <string>
int main() {
std::ifstream file("myfile.txt");
std::string line;
while (std::getline(file, line)) {
if (line.length() == 0) { // check if the line is empty
continue; // skip the iteration
}
// process the non-empty line
}
file.close();
return 0;
}
You can also use the std::stringstream class to skip blank lines, here is an example:
#include <fstream>
#include <sstream>
#include <string>
int main() {
std::ifstream file("myfile.txt");
std::string line;
while (std::getline(file, line)) {
std::stringstream ss(line);
if (ss >> line) { // check if the line is empty
// process the non-empty line
}
}
file.close();
return 0;
}
(1) Here's a solution using the ws manipulator in conjunction with the getline function to ignore leading white-space while reading lines of input from the stream. ws is a manipulator that skips whitespace characters (demo).
#include <iostream>
#include <string>
int main()
{
using namespace std;
string line;
while (getline(cin >> ws, line))
cout << "got: " << line << endl;
return 0;
}
Note that the spaces are removed even if the line is not empty (" abc " becomes "abc ".
(2) If this is a problem, you could use:
while (getline(cin, line))
if (line.find_first_not_of(" \t") != string::npos)
cout << "got: " << line << endl;

How can I read from a file and sort them by category

I'm trying to read a bunch of words from a file and sort them into what kind of words they are (Nouns, Adjective, Verbs ..etc). For example :
-Nouns;
zyrian
zymurgy
zymosis
zymometer
zymolysis
-Verbs_participle;
zoom in
zoom along
zoom
zonk out
zone
I'm using getline to read until the delimiter ';' but how can I know when it read in a type and when it read in a word?
The function below stop right after "-Nouns;"
int main()
{
map<string,string> data_base;
ifstream source ;
source.open("partitioned_data.txt");
char type [MAX];
char word [MAX];
if(source) //check to make sure we have opened the file
{
source.getline(type,MAX,';');
while( source && !source.eof())//make sure we're not at the end of file
{
source.getline(word,MAX);
cout<<type<<endl;
cout<<word<<endl;
source.getline(type,MAX,';');//read the next line
}
}
source.close();
source.clear();
return 0;
}
I am not fully sure about the format of your input file. But you seem to have a file with lines, and in that, items separated by a semicolon.
Reading this should be done differently.
Please see the following example:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
std::istringstream source{R"(noun;tree
noun;house
verb;build
verb;plant
)"};
int main()
{
std::string type{};
std::string word{};
//ifstream source{"partitioned_data.txt"};
if(source) //check to make sure we have opened the file
{
std::string line{};
while(getline(source,line))//make sure we're not at the end of file
{
size_t pos = line.find(';');
if (pos != std::string::npos) {
type = line.substr(0,pos);
word = line.substr(pos+1);
}
std::cout << type << " --> " << word << '\n';
}
}
return 0;
}
There is no need for open and close statements. The constructor and
destructor of the std::ifstream will do that for us.
Do not check eof in while statement
Do not, and never ever use C-Style arrays like char type [MAX];
Read a line in the while statement and check validity of operation in the while. Then work on the read line later.
Search the ';' in the string, and if found, take out the substrings.
If I would knwo the format of the input file, then I will write an even better example for you.
Since I do not have files on SO, I uses a std::istringstream instead. But there is NO difference compared to a file. Simply delete the std::istringstream and uncomment teh ifstream definition in the source code.

Why does replacing a string replace part of another string?

I wrote a small piece of code today about replacing a word from a text file.
Though it replaces the given word but it also removes some spaces and some part of other string.
I want it to replace given word only while keeping rest as it as.
I don't know what should I do. Any help would be appreciated!
Original Data of file:
Is anyone there?
Who survived?
Somebody new?
Anyone else but you
On a lonely night
Was a burning light
A hundred years, we'll be born again
Output when replaced "anyone" by "porter":
Is anyonportere?
Who survived?
Somebody new?
anporterlse but you
On a lonely night
Was a burning light
A hundred years, we'll be born again
Code:
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<cstring>
using namespace std;
int main(int argc , char* argv[])
{
string old_word,new_word;
int no=0;
old_word=argv[1];
new_word=argv[2];
if(argc<4)
{
cout<<"\nSome Arguments are missing";
return 0;
}
if(strlen(argv[1])!=strlen(argv[2]))
{
cout<<"\nReplacement is not possible as size of New wor dis not equal to old word";
return 0;
}
fstream obj;
obj.open(argv[3],ios::in|ios::out);
if(!obj)
{
cout<<"\nError in file creating";
return 0;
}
string fetch_word;
while(1)
{
if(obj.eof())
{
break;
}
else
{
int pos=obj.tellg();
obj>>fetch_word;
if(fetch_word==old_word)
{
no++;
obj.seekp(pos);
obj<<new_word;
}
}
}
if(no==0)
{
cout<<"\nNo Replacement Done . Zero Replacement Found";
}
else
{
cout<<"\nReplacement Done . Replacement Found ="<<no<<endl;
}
obj.close();
return 0;
}
If we take the string "Is anyone there?"
After read the word "Is" the read head is on the space after the "Is" so tellg will return 2.
Now you're reading the next word, you skip white spaces and begin reading untill next white space character, you are reading the "anyone" word and put its replacement in the taken position (2).
so it should give you the string: "Isportere there?"
Not what you ment for, but not the result you've got.
to fix it you should ignore white spaces before reading the position:
like this:
//#include <cwctype> for iswspace
//eat white spaces
while(iswspace(obj.peek()))
obj.ignore();
//now read head is on the beginning of a word, you can take position.
int pos=obj.tellg();
Edit
You'll have to debug and see if the tellg returns 3 in the first line before you read the word "anyone". I sugggest to add some debug print for each replacement with the possition.
like:
if(fetch_word==old_word)
{
no++;
cout<<"Replacing in pos "<< pos <<endl;
obj.seekp(pos);
obj<<new_word;
}
Now you can check:
Does the pos was correct? (you can try to seekg and read the word again)
Does the seekp was succes? (you can use tellp to check!)
What happen when you just do obj.seekp(3); obj<<"porter"; does it replace the string in the correct position?
#include <cctype>
#include <cstdlib>
#include <string>
#include <fstream>
#include <iostream>
int main()
{
std::string old_word{ "anyone" };
std::string new_word{ "porter" };
if (old_word.length() != new_word.length()) {
std::cerr << "Sorry, I can only replace words of equal length :(\n\n";
return EXIT_FAILURE;
}
char const *filename{ "test.txt" };
std::fstream obj{ "test.txt", std::ios::in | std::ios::out };
if (!obj.is_open()) {
std::cerr << "Couldn't open \"" << filename << "\" for reading and writing.\n\n";
return EXIT_FAILURE;
}
std::string word;
for (std::streampos pos; pos = obj.tellg(), obj >> word;) {
if (word == old_word) {
obj.seekg(pos); // set the "get" position to where it were before extracting word
while (std::isspace(obj.peek())) // for every whitespace we peek at
obj.get(); // discard it
obj.seekp(obj.tellg()); // set the "put" position to the current "get" position
obj << new_word; // overwirte word with new_word
obj.seekg(obj.tellp()); // set the "get" position to the current "put" position
}
}
}

fstream c ++ functions return full line fstream

C ++ language for the creation of a personal web, here I use C++ as cgi to output to a web server XAMP, with load fstream to separate manuscript with c ++ html, making htmlstream function as pieces that are not too complicated in notepad while coding c ++, the problem is when a function htmlstream made, only one line of text, it can not display all the text
#include <iostream>
#include <fstream>
using namespace std;
string htmlstream(const char* _filename){
string htmltext;
fstream open_html (_filename);
if(open_html.is_open()){
while(getline(open_html,htmltext)){
return htmltext;
}
}else{
cout<<"File: NO Reading"<<endl;
}
}
int main(){
string importhtml = htmlstream("body.html");
cout<<importhtml;
return 0;
}
The reason why one line of text is only display is because the function getline reads until it reaches the end of the current line. That is, every time a line is read, the value of the string variable is changed.
If storing the value of each line is what you want, then you will have to append every line as you read. There are multiple solutions, I decided to go with something simple.
See if this helps.
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
/// Simplify calls to the standard library
using namespace std;
string htmlStream( const char *fileName )
{
string text; /// Content of current file
ifstream inFile; /// Input file stream
inFile.open( fileName ); /// Open file to read
if ( inFile.is_open() ) {
/// File successfully open, so process it
string line; /// String being read
/// Read file, line by line
while ( getline( inFile, line ) ) {
text += line;
}
}
else {
/// Could not open file, so report error to the stderr
cerr << "Cannot open \"" << fileName << "\"" << endl;
exit( EXIT_FAILURE );
}
return text;
}
int main( int argc, const char * argv[] ) {
string str = htmlStream( "darkness.txt" );
cout << str << endl;
return EXIT_SUCCESS;
}

How to read the whole lines from a file (with spaces)?

I am using STL. I need to read lines from a text file. How to read lines till the first \n but not till the first ' ' (space)?
For example, my text file contains:
Hello world
Hey there
If I write like this:
ifstream file("FileWithGreetings.txt");
string str("");
file >> str;
then str will contain only "Hello" but I need "Hello world" (till the first \n).
I thought I could use the method getline() but it demands to specify the number of symbols to be read. In my case, I do not know how many symbols I should read.
You can use getline:
#include <string>
#include <iostream>
int main() {
std::string line;
if (getline(std::cin,line)) {
// line is the whole line
}
}
using getline function is one option.
or
getc to read each char with a do-while loop
if the file consists of numbers, this would be a better way to read.
do {
int item=0, pos=0;
c = getc(in);
while((c >= '0') && (c <= '9')) {
item *=10;
item += int(c)-int('0');
c = getc(in);
pos++;
}
if(pos) list.push_back(item);
}while(c != '\n' && !feof(in));
try by modifying this method if your file consists of strings..
Thanks to all of the people who answered me. I made new code for my program, which works:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
ifstream ifile(argv[1]);
// ...
while (!ifile.eof())
{
string line("");
if (getline(ifile, line))
{
// the line is a whole line
}
// ...
}
ifile.close();
return 0;
}
I suggest:
#include<fstream>
ifstream reader([filename], [ifstream::in or std::ios_base::in);
if(ifstream){ // confirm stream is in a good state
while(!reader.eof()){
reader.read(std::string, size_t how_long?);
// Then process the std::string as described below
}
}
For the std::string, any variable name will do, and for how long, whatever you feel appropriate or use std::getline as above.
To process the line, just use an iterator on the std::string:
std::string::iterator begin() & std::string::iterator end()
and process the iterator pointer character by character until you have the \n and ' ' you are looking for.