Analyzing a string for file name format [duplicate] - c++

This question already has answers here:
How to check if string ends with .txt
(12 answers)
Closed 8 years ago.
A file name is being passed down into a function. The string needs to be checked to make sure it ends with ".bmp"
How do i check for that to later open the file?
For example: if a string contains "picture.txt" it will tell the user the string is not in the correct format. If a string contain "picture.bmp" it should accept it for later use of opening the file.
Thanks in advance!

What OS are you using? If it's Windows / Visual C++, you have functions that properly give you the extension given a file name (for example _spiitpath). If you want something portable, you have boost::filesystem to parse out the name.
The reason why you should use these functions instead of trying to cook something up yourself is that there could be corner or edge cases that you didn't consider, thus causing your code to give wrong results.

You can do something like this:
bool hasExtension(const string& filename, const string& extension)
{
size_t fnlen = filename.length();
size_t exlen = extension.length();
if (fnlen < exlen)
return false;
return memcmp(filename.c_str() + fnlen - exlen, extension.c_str(), exlen) == 0;
}
int main()
{
cout << hasExtension("file.txt", ".txt") << endl;
}

Related

trying to give a variable to ifstream in c++ [duplicate]

This question already has answers here:
Put A String In A ifstream Method [duplicate]
(2 answers)
No matching function - ifstream open()
(1 answer)
Closed 3 years ago.
im new to c++ and trying to put a variable in this line : ifstream studentPaper(paper);
ill pass paper to this function and want to use it there. string paper has my files location (/name/file.txt)
if i put my file name there i dont get any errors = ifstream studentPaper("/name/file.txt");
but when i save my files location in to a string and give string to it ill get error = ifstream studentPaper(paper);
how can i do that without getting errors
void matchGrades(string paper) {
string aa= "asd";
ifstream studentPaper(paper);
ifstream base("base.txt");
int grade=3;
while ((!studentPaper.eof()) && (!base.eof())) {
string l1,l2;
getline(studentPaper,l1);
getline(base,l2);
if(l1==l2){
grade += 3;
} else {
grade -= 3;
}
}
studentPaper.close();
base.close();
cout << grade;
I think that You have to use removed string parameter "/name/file.txt" because parameter split space.
Try doing ifstream studentPaper(paper.c_str()).
Also if your file is located where your main.cpp is you won't need to specify the path. Something like this:
string studentFile = "student_file.txt";
Based on the information provided. If you are still getting an error please post it so that I can adjust my answer.

Clear CSV-file from non-specified symbols using C++ [duplicate]

This question already has answers here:
Why can Windows not read beyond the 0x1A (EOF) character but Unix can? [duplicate]
(2 answers)
Closed 3 years ago.
I'm trying to convert CSV-file to TXT-file using simple C++-code like this:
std::ofstream txtFile(strFileName, std::ofstream::out | std::ofstream::app);
std::string strLine;
std::ifstream csvFile(strCSVDir);
while (std::getline(csvFile, strLine))
{
std::string subString;
std::stringstream s(strLine);
while (std::getline(s, subString, ';'))
{
txtFile << subString << "\t";
}
txtFile << "\n";
}
txtFile.close();
csvFile.close();
It works fine, but only if the CSV-file doesn't contain any non-specified symbols, like arrow on this picture:
In this case my code can read only part of CSV-file until it meet this arrow symbol. How can I get around this situation?
Update: if I look at this CSV-file in byte-representation (for example in Far Hex-view), than I see code of arrow-symbol is "1A". The table of Unicode-characters points that it is Substitute symbol. How does it get in this CSV-file I don't know.
It might be easier to just read the entire file - then replacing and finally saving.
Going from your snippet:
std::stringstream sstr;
sstr << csvFile.rdbuf();
std::string buffer = sstr.str();
boost::replace_all(buffer, ";", "");
txtFile << buffer;
Update: if you don't have boost it should be easy to replace with something else like a for loop (since it is just a single char replacement)
Update 2: The reason why reading might not read the entire file in this case is because it is being read as a text file and probably contains a terminating character somewhere due to the way it is being read - see https://en.cppreference.com/w/cpp/io/c#Binary_and_text_modes for explaination.

Check input is a valid integer [duplicate]

This question already has answers here:
How to determine if a string is a number with C++?
(36 answers)
Closed 10 months ago.
Hi Can anyone help me please. I need to check that my input only contains integers. Im guessing from looking it up that I use the isDigit function but I am not sure how to use this to check the whole number.
I'm using C++ to interact with MSI so i'm getting the integer as follows:
hr = WcaGetProperty(L"LOCKTYPE",&szLockType);
ExitOnFailure(hr, "failed to get the Lock Type");
I think i have to change szLockType to a char and then use isdigit to scan through each character but i am not sure how to implement this. Any help would be greatly appreciated. P.s im a beginner so please excuse if this is a really trivial question..:)
Use std::stoi(). You'll get an exception if the string is not an integer value.
What's the type of szLockType?
Is it a a null-terminated char-string?
Then you can use the array syntax to get individual characters.
for(int i = 0; i < std::strlen(szLockType); i++) {
if(!std::isDigit(szLockType[i])) {
// it contains a non-digit - do what you have to do and then...
break; // ...to exit the for-loop
}
}
Or is it a std::string? Then the syntax is slightly different:
for(int i = 0; i < szLockType.length(); i++) {
if(!std::isDigit(szLockType.at(i)) {
// it contains a non-digit - do what you have to do and then...
break; // ...to exit the for-loop
}
}
Even better, with modern C++ you can do this:
#include <algorithm>
#include <cctype>
auto lambda = [](auto elem)
{
return std::isdigit(elem);
};
return std::all_of(szLockType, szLockType + strlen(szLockType), lambda);
Your choice as to whether you prefer a named lambda or regular, anonymous lambda.
FYI it is std::isdigit rather than isDigit.
https://en.cppreference.com/w/cpp/string/byte/isdigit

stream .pdf error [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
convert a file (.txt,.pdf..) into a stream file
std::string fil= "/home/sensor.pdf";
std::ifstream t(fil.c_str());
if (t)
{
string res;
string line;
while (getline(t, line, '\n'))
{
res=res+line;
}
std::string p;
p=(((reinterpret_cast<const unsigned char *> (res.c_str())),res.size()));
std::string f_data=p;
char *token = strtok( const_cast<char*>(fil.c_str() ), "/" );
std::string name;
std::vector<int> values;
while ( token != NULL )
{
name=token;
token = strtok( NULL, "/" );
}
std::strig f_name=name;
}
When I try to load the .pdf file I have an error "unable to read. PDF IS DAMAGED". WHY? This code works for .txt files and .cpp files. I've tested it. I am currently working in ubuntu c++ code. I've also used the base_64 encode/decode because this was the request.
Try this: http://sourceforge.net/projects/libharu/
I saw it recommended in a few different places, including a couple different SO questions - but all they gave was the link.
It's a free, open-souce library for PDF reading. It probably isn't as easy as you want, but I think its as easy as you're gonna get and its free.
It's also multi-platform so should work on UNIX and windows.
Try opening with:
ifstream file ("/home/sensor.pdf", ios::in|ios::binary);

What is the easiest way to parse an INI File in C++? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm trying to parse an INI file using C++. Any tips on what is the best way to achieve this? Should I use the Windows API tools for INI file processing (with which I am totally unfamiliar), an open-source solution or attempt to parse it manually?
You can use the Windows API functions, such as GetPrivateProfileString() and GetPrivateProfileInt().
If you need a cross-platform solution, try Boost's Program Options library.
I have never parsed ini files, so I can't be too specific on this issue.
But i have one advice:
Don't reinvent the wheel as long as an existing one meets your requirements
http://en.wikipedia.org/wiki/INI_file#Accessing_INI_files
http://sdl-cfg.sourceforge.net/
http://sourceforge.net/projects/libini/
http://www.codeproject.com/KB/files/config-file-parser.aspx
Good luck :)
If you are already using Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);
Then read a value
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()
There are a bunch of other converter that convert your INI values into both standard types and Qt types. See Qt documentation on QSettings for more information.
I use SimpleIni. It's cross-platform.
this question is a bit old, but I will post my answer. I have tested various INI classes (you can see them on my website) and I also use simpleIni because I want to work with INI files on both windows and winCE.
Window's GetPrivateProfileString() works only with the registry on winCE.
It is very easy to read with simpleIni. Here is an example:
#include "SimpleIni\SimpleIni.h"
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(FileName);
const char * pVal = ini.GetValue(section, entry, DefaultStr);
inih is a simple ini parser written in C, it comes with a C++ wrapper too. Example usage:
#include "INIReader.h"
INIReader reader("test.ini");
std::cout << "version="
<< reader.GetInteger("protocol", "version", -1) << ", name="
<< reader.Get("user", "name", "UNKNOWN") << ", active="
<< reader.GetBoolean("user", "active", true) << "\n";
The author has also a list of existing libraries here.
Have you tried libconfig; very JSON-like syntax. I prefer it over XML configuration files.
I ended up using inipp which is not mentioned in this thread.
https://github.com/mcmtroffaes/inipp
Was a MIT licensed header only implementation which was simple enough to add to a project and 4 lines to use.
If you are interested in platform portability, you can also try Boost.PropertyTree. It supports ini as persistancy format, though the property tree my be 1 level deep only.
Unless you plan on making the app cross-platform, using the Windows API calls would be the best way to go. Just ignore the note in the API documentation about being provided only for 16-bit app compatibility.
I know this question is very old, but I came upon it because I needed something cross platform for linux, win32... I wrote the function below, it is a single function that can parse INI files, hopefully others will find it useful.
rules & caveats:
buf to parse must be a NULL terminated string. Load your ini file into a char array string and call this function to parse it.
section names must have [] brackets around them, such as this [MySection], also values and sections must begin on a line without leading spaces. It will parse files with Windows \r\n or with Linux \n line endings. Comments should use # or // and begin at the top of the file, no comments should be mixed with INI entry data. Quotes and ticks are trimmed from both ends of the return string. Spaces are only trimmed if they are outside of the quote. Strings are not required to have quotes, and whitespaces are trimmed if quotes are missing. You can also extract numbers or other data, for example if you have a float just perform a atof(ret) on the ret buffer.
// -----note: no escape is nessesary for inner quotes or ticks-----
// -----------------------------example----------------------------
// [Entry2]
// Alignment = 1
// LightLvl=128
// Library = 5555
// StrValA = Inner "quoted" or 'quoted' strings are ok to use
// StrValB = "This a "quoted" or 'quoted' String Value"
// StrValC = 'This a "tick" or 'tick' String Value'
// StrValD = "Missing quote at end will still work
// StrValE = This is another "quote" example
// StrValF = " Spaces inside the quote are preserved "
// StrValG = This works too and spaces are trimmed away
// StrValH =
// ----------------------------------------------------------------
//12oClocker super lean and mean INI file parser (with section support)
//set section to 0 to disable section support
//returns TRUE if we were able to extract a string into ret value
//NextSection is a char* pointer, will be set to zero if no next section is found
//will be set to pointer of next section if it was found.
//use it like this... char* NextSection = 0; GrabIniValue(X,X,X,X,X,&NextSection);
//buf is data to parse, ret is the user supplied return buffer
BOOL GrabIniValue(char* buf, const char* section, const char* valname, char* ret, int retbuflen, char** NextSection)
{
if(!buf){*ret=0; return FALSE;}
char* s = buf; //search starts at "s" pointer
char* e = 0; //end of section pointer
//find section
if(section)
{
int L = strlen(section);
SearchAgain1:
s = strstr(s,section); if(!s){*ret=0; return FALSE;} //find section
if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain1;} //section must be at begining of a line!
s+=L; //found section, skip past section name
while(*s!='\n'){s++;} s++; //spin until next line, s is now begining of section data
e = strstr(s,"\n["); //find begining of next section or end of file
if(e){*e=0;} //if we found begining of next section, null the \n so we don't search past section
if(NextSection) //user passed in a NextSection pointer
{ if(e){*NextSection=(e+1);}else{*NextSection=0;} } //set pointer to next section
}
//restore char at end of section, ret=empty_string, return FALSE
#define RESTORE_E if(e){*e='\n';}
#define SAFE_RETURN RESTORE_E; (*ret)=0; return FALSE
//find valname
int L = strlen(valname);
SearchAgain2:
s = strstr(s,valname); if(!s){SAFE_RETURN;} //find valname
if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain2;} //valname must be at begining of a line!
s+=L; //found valname match, skip past it
while(*s==' ' || *s == '\t'){s++;} //skip spaces and tabs
if(!(*s)){SAFE_RETURN;} //if NULL encounted do safe return
if(*s != '='){goto SearchAgain2;} //no equal sign found after valname, search again
s++; //skip past the equal sign
while(*s==' ' || *s=='\t'){s++;} //skip spaces and tabs
while(*s=='\"' || *s=='\''){s++;} //skip past quotes and ticks
if(!(*s)){SAFE_RETURN;} //if NULL encounted do safe return
char* E = s; //s is now the begining of the valname data
while(*E!='\r' && *E!='\n' && *E!=0){E++;} E--; //find end of line or end of string, then backup 1 char
while(E > s && (*E==' ' || *E=='\t')){E--;} //move backwards past spaces and tabs
while(E > s && (*E=='\"' || *E=='\'')){E--;} //move backwards past quotes and ticks
L = E-s+1; //length of string to extract NOT including NULL
if(L<1 || L+1 > retbuflen){SAFE_RETURN;} //empty string or buffer size too small
strncpy(ret,s,L); //copy the string
ret[L]=0; //null last char on return buffer
RESTORE_E;
return TRUE;
#undef RESTORE_E
#undef SAFE_RETURN
}
How to use... example....
char sFileData[] = "[MySection]\r\n"
"MyValue1 = 123\r\n"
"MyValue2 = 456\r\n"
"MyValue3 = 789\r\n"
"\r\n"
"[MySection]\r\n"
"MyValue1 = Hello1\r\n"
"MyValue2 = Hello2\r\n"
"MyValue3 = Hello3\r\n"
"\r\n";
char str[256];
char* sSec = sFileData;
char secName[] = "[MySection]"; //we support sections with same name
while(sSec)//while we have a valid sNextSec
{
//print values of the sections
char* next=0;//in case we dont have any sucessful grabs
if(GrabIniValue(sSec,secName,"MyValue1",str,sizeof(str),&next)) { printf("MyValue1 = [%s]\n",str); }
if(GrabIniValue(sSec,secName,"MyValue2",str,sizeof(str),0)) { printf("MyValue2 = [%s]\n",str); }
if(GrabIniValue(sSec,secName,"MyValue3",str,sizeof(str),0)) { printf("MyValue3 = [%s]\n",str); }
printf("\n");
sSec = next; //parse next section, next will be null if no more sections to parse
}
Maybe a late answer..But, worth knowing options..If you need a cross-platform solution , definitely you can try GLIB,, its interesting.. (https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html)