How to avoid this nested if statement? - c++

I want to check if one file exists in two different paths. If the first one doesn't, check the second.
filepath1 = "/path1/file.txt"
filepath2 = "/path2/file.txt"
file_descriptor = open(filepath1)
if ( !file_descriptor.open() )
{
print("file 1 did not work");
//try file 2
file_descriptor = open(filepath2);
if( !file_descriptor.open() )
{
print("could not open file 2. exiting.");
return false;
}
}
//we get here and file_descriptor should point to a valid file
read_file(file_descriptor);
return true;
How can I avoid the nested if statement? Preferably, I'd like to not nest the if statements for readability.
The problem here is that if the first one does work, I don't want it to check the second if statement.
I thought about using:
goto (I want to avoid this)
boolean to check if one works (but now I'm introducing extra variables)

I guess this pattern is pretty general: you can try as many paths as you wish:
auto filepath1 = "/path1/file.txt";
auto filepath2 = "/path2/file.txt";
// We assume file_descriptor has been declared earlier
for (const auto fpath: {filepath1, filepath2})
{
file_descriptor = open(fpath)
if (file_descriptor.open())
break;
else
printf("file %s did not work\n", fpath);
}
if (!file_descriptor.open()) return false; // or throw
read_file(file_descriptor);
return true;

if you don't care about which file is open you can do
filepath1 = "/path1/file.txt"
filepath2 = "/path2/file.txt"
if (!(file_descriptor = open(filepath1)).open() &&
!(file_descriptor = open(filepath2)).open())
{
print("could not open file 1 nor 2. exiting.");
return false;
}
...
else if you really want only one if you can do
filepath1 = "/path1/file.txt"
filepath2 = "/path2/file.txt"
if (!(file_descriptor = open(filepath1)).open() &&
(print("file 1 did not work"),
!(file_descriptor = open(filepath2)).open()))
{
print("could not open file 2. exiting.");
return false;
}
...
but this makes the code less clear than with the two ifs
P.S. do not think about using goto

Related

CppUnitTestFramework: Test Method Fails, Stack Trace Lists Line Number at the End of Method, Debug Test Passes

I know, I know - that question title is very much all over the place. However, I am not sure what could be an issue here that is causing what I am witnessing.
I have the following method in class Project that is being unit tested:
bool Project::DetermineID(std::string configFile, std::string& ID)
{
std::ifstream config;
config.open(configFile);
if (!config.is_open()) {
WARNING << "Failed to open the configuration file for processing ID at: " << configFile;
return false;
}
std::string line = "";
ID = "";
bool isConfigurationSection = false;
bool isConfiguration = false;
std::string tempID = "";
while (std::getline(config, line))
{
std::transform(line.begin(), line.end(), line.begin(), ::toupper); // transform the line to all capital letters
boost::trim(line);
if ((line.find("IDENTIFICATIONS") != std::string::npos) && (!isConfigurationSection)) {
// remove the "IDENTIFICATIONS" part from the current line we're working with
std::size_t idStartPos = line.find("IDENTIFICATIONS");
line = line.substr(idStartPos + strlen("IDENTIFICATIONS"), line.length() - idStartPos - strlen("IDENTIFICATIONS"));
boost::trim(line);
isConfigurationSection = true;
}
if ((line.find('{') != std::string::npos) && isConfigurationSection) {
std::size_t bracketPos = line.find('{');
// we are working within the ids configuration section
// determine if this is the first character of the line, or if there is an ID that precedes the {
if (bracketPos == 0) {
// is the first char
// remove the bracket and keep processing
line = line.substr(1, line.length() - 1);
boost::trim(line);
}
else {
// the text before { is a temp ID
tempID = line.substr(0, bracketPos - 1);
isConfiguration = true;
line = line.substr(bracketPos, line.length() - bracketPos);
boost::trim(line);
}
}
if ((line.find("PORT") != std::string::npos) && isConfiguration) {
std::size_t indexOfEqualSign = line.find('=');
if (indexOfEqualSign == std::string::npos) {
WARNING << "Unable to determine the port # assigned to " << tempID;
}
else {
std::string portString = "";
portString = line.substr(indexOfEqualSign + 1, line.length() - indexOfEqualSign - 1);
boost::trim(portString);
// confirm that the obtained port string is not an empty value
if (portString.empty()) {
WARNING << "Failed to obtain the \"Port\" value that is set to " << tempID;
}
else {
// attempt to convert the string to int
int workingPortNum = 0;
try {
workingPortNum = std::stoi(portString);
}
catch (...) {
WARNING << "Failed to convert the obtained \"Port\" value that is set to " << tempID;
}
if (workingPortNum != 0) {
// check if this port # is the same port # we are publishing data on
if (workingPortNum == this->port) {
ID = tempID;
break;
}
}
}
}
}
}
config.close();
if (ID.empty())
return false;
else
return true;
}
The goal of this method is to parse any text file for the ID portion, based on matching the port # that the application is publishing data to.
Format of the file is like this:
Idenntifications {
ID {
port = 1001
}
}
In a separate Visual Studio project that unit tests various methods, including this Project::DetermineID method.
#define STRINGIFY(x) #x
#define EXPAND(x) STRINGIFY(x)
TEST_CLASS(ProjectUnitTests) {
Project* parser;
std::string projectDirectory;
TEST_METHOD_INITIALIZE(ProjectUnitTestInitialization) {
projectDirectory = EXPAND(UNITTESTPRJ);
projectDirectory.erase(0, 1);
projectDirectory.erase(projectDirectory.size() - 2);
parser = Project::getClass(); // singleton method getter/initializer
}
// Other test methods are present and pass/fail accordingly
TEST_METHOD(DetermineID) {
std::string ID = "";
bool x = parser ->DetermineAdapterID(projectDirectory + "normal.cfg", ID);
Assert::IsTrue(x);
}
};
Now, when I run the tests, DetermineID fails and the stack trace states:
DetermineID
Source: Project Tests.cpp line 86
Duration: 2 sec
Message:
Assert failed
Stack Trace:
ProjectUnitTests::DetermineID() line 91
Now, in my test .cpp file, TEST_METHOD(DetermineID) { is present on line 86. But that method's } is located on line 91, as the stack trace indicates.
And, when debugging, the unit test passes, because the return of x in the TEST_METHOD is true.
Only when running the test individually or running all tests does that test method fail.
Some notes that may be relevant:
This is a single-threaded application with no tasks scheduled (no race condition to worry about supposedly)
There is another method in the Project class that also processes a file with an std::ifstream same as this method does
That method has its own test method that has been written and passes without any problems
The test method also access the "normal.cfg" file
Yes, this->port has an assigned value
Thus, my questions are:
Why does the stack trace reference the closing bracket for the test method instead of the single Assert within the method that is supposedly failing?
How to get the unit test to pass when it is ran? (Since it currently only plasses during debugging where I can confirm that x is true).
If the issue is a race condition where perhaps the other test method is accessing the "normal.cfg" file, why does the test method fail even when the method is individually ran?
Any support/assistance here is very much appreciated. Thank you!

ifstream - monitor updates to file

I am using ifstream to open a file and read line by line and print to console.
Now, I also want to make sure that if the file gets updated, it reflects. My code should handle that.
I tried setting fseek to end of the file and then looking for new entries by using peek. However, that did not work.
Here's some code I used
bool ifRead = true;
while (1)
{
if (ifRead)
{
if (!file2read.eof())
{
//valid file. not end of file.
while (getline(file2read, line))
printf("Line: %s \n", line.c_str());
}
else
{
file2read.seekg(0, file2read.end);
ifRead = false;
}
}
else
{
//I thought this would check if new content is added.
//in which case, "peek" will return a non-EOF value. else it will always be EOF.
if (file2read.peek() != EOF)
ifRead = true;
}
}
}
Any suggestions on what could be wrong or how I could do this.

Java Loop not exiting properly when using boolean expression (JAVA) - Newbie

Everytime I run the my function SearchByID it won't return the necessary boolean operators that I needed. The method reads to the Employee.txt files and read files one after another. What I did is I created a String array to store the splitted strings, and doing the String.equalsIgnorCase() method to check if the corresponding matches w/ the data on the file. Here is the code for the method
Code: SearchByID
public static boolean SearchByID(String ID){
boolean bool = false;
int idLoc = 3;
try(BufferedReader bufr = new BufferedReader(new FileReader(EMPLOYEE_TXT))){
String line = bufr.readLine();
/*Split the records into an array*/
String[] lines;
while(line !=null){
//do the macthing of data here
lines = line.split(";");
if(lines[idLoc].equalsIgnoreCase(ID)){
bool = true;
break;
}else{
bool = false;
break;
}
}
bufr.close();
}catch(Exception ex){
ex.printStackTrace();
}
return bool;
}
Here is the implementation of the method SearchByID();
System.out.print("Search user by ID:");
String strID = sID.nextLine();
if(IOLibraries.SearchByID(strID)){
System.out.println("A match has been found");
}else{
System.out.println("No match found");
}
Content of the Employee.txt
kadi,bens;male;baliwasan grande;88-11;99111;arg11#gmail.com;400.0
doe,john;male;11311 asdd;99811;9911331;asdf#.sdfcom;500.0
What I really need to do is I need to read all the data on the file after that it should return the correct boolean values in order search for all the users on the Employee.txt file.
I could not retrieve if I search the values below the first entries. For example if i search for id 88-11 I could retrieve the data properly, however if I search below the first entry such as 99811 it would return false or "No match found" even if it is in the Employee.txt files.
The problem is you will always break out from the loop after reading the first line.
while(line !=null){
//do the macthing of data here
lines = line.split(";");
if(lines[idLoc].equalsIgnoreCase(ID)){
bool = true;
break;
}else{
bool = false;
break;
}
}
Note the else block. If first line does not match the ID, it will go into the else block, which declare that it is not found, and breaking out.
What you should do is
initialize bool (or better call it found) as false before the loop (for which you have done already)
Only break out of loop if you found the matching line
i.e. change the loop to something like
while(line !=null){
lines = line.split(";");
if(lines[idLoc].equalsIgnoreCase(id)){
found = true;
break;
}
}

switch case avoid loop

I have the following code:
int send_cmd( int sock, char * buffer, int lbuffer )
{
int err = 0;
//do_something part 1
while(1)
switch(check_status(buffer)){
case 1:
return 0;
break;
case 0:
if (err > 0)
break;
//do_something part 2
err = 1;
}
return -1;
}
I don't think this is well coded but I didn't know how to optimize it.
I wanna run the "part 2 code" only once and only if "part 1 code" gives an error.
Can you tell me how to make it run correctly? Cause right now doesn't return anything after part 2 is executed once.
I wanna run the "part 2 code" only once and only if "part 1 code" gives an error.
There's no need for a while loop or a switch statement.
// Do something part 1
if (check_status(buffer) == 1) {
return 0;
}
// Do something part 2
if (check_status(buffer) == 1) {
return 0;
}
else {
return -1;
}
If you don't need the loop, you can just use an if and return. Since you don't use err, you can omit it as well.
// first command
int status = check_status(buffer);
if (status == 1)
return 0;
// second command
status = check_status(buffer);
if (status == 1)
return 0;
return -1;
At least in this simple case, switch is not better or faster than if. There might be cases, where this is true, but I won't bet on it. Usually, the optimizer is good enough to emit optimal machine code, whether you use switch or if. So go for the simple, readable and maintainable code.
Looking at your, i think this is what you are trying to achieve using the err variable :
//Part 1
if ( check_status(buffer) ) return 0; //No error
//Part 2
if ( check_status(buffer) ) return 1; //One error
else return -1; //Two errors
You dont need any while loops to do this.

C++ array - uses only first line

i have problems with the array function.. -
i put my mac on fist line and then says me approved , but if is on 2st line rejected. my real one is B6 on end. /address down are not real../
in heder file settings >
#define CLIENTSNUMBER 2
BOOL Checking2(LPCSTR MacID);
cpp >
char ClientMacs[CLIENTSNUMBER*1][18] = {
"5A-77-77-97-87-B7",
"5A-77-77-97-87-B6"
};
BOOL Checking2(LPCSTR MacID)
{
for(int x=0;x<CLIENTSNUMBER;x++)
{
if(!strcmp(MacID,ClientMacs[x]))
{
MessageBoxA(NULL,MacID,"APPROVED!",MB_OK);
return false;
} else {
MessageBoxA(NULL,MacID,"REJECTED!",MB_OK);
return false;
}
}
return false;
}
Because you return from your function (breaking out of your loop) when something matches or doesn't match. It will never actually loop.
Edit because it's a slow morning:
You need to go through the entire array and look at every element for a match before declaring it's rejected:
BOOL Checking2(LPCSTR MacID)
{
for(int x=0;x<CLIENTSNUMBER;x++)
{
if(strcmp(MacID,ClientMacs[x]) == 0)
{
MessageBoxA(NULL,MacID,"APPROVED!",MB_OK);
return false;
}
}
MessageBoxA(NULL,MacID,"REJECTED!",MB_OK);
return false;
}
Also, do you really mean to return false in both cases? I would assume if you find a match it should return true