How to check for file extention

hello, i need to check if a file has .txt or .dat extension. i have this code so far, but for some reason its not working, but works if i specify only one type of extension.When i add the second condition the logic does not work.
can someone help with this
thanks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
   string a = "f.dat" ;
   if( (a.size()<5) || (a.substr(a.find_last_of(".")+1) != "dat") || (a.substr(a.find_last_of(".")+1) != "txt"))  {


    cout << "incorrect" << endl;
   }

   else {

    cout << "correct"<< endl;
   }


}

Last edited on
De Morgan's law:
(NOT aa) OR (NOT bb)
is same as
NOT (aa AND bb)

Word cannot end both "dat" and "txt" simultaneosly.
Therefore, at most one of the (aa, bb) two is true. Thus (aa AND bb) is always false.

Put other way, at least one of (NOT aa) and (NOT bb) is always true foo you and that is why
(NOT aa) OR (NOT bb) is always true.

Think about:
NOT (aa OR bb)
It appears that you're using the wrong logical operator in the second part of that if statement. Be careful with the negation operator when using the OR operator.

See this link for more information.
https://en.wikipedia.org/wiki/De_Morgan%27s_laws

Edit: Actually if you only want to the extension to be either "dat" or "txt" you probably don't want the negation at all.

Last edited on
Hello LuffyD,


PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button.

You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.


The only thing I would add to what keskiverto and jlb have said is that over time I have when using the "!=" that "&&" is needed most often.

On the other hand this may work better for you:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
	std::string a = "f.txt";

	//if ((a.size() < 5) || (a.substr(a.find_last_of(".") + 1) != "dat") || (a.substr(a.find_last_of(".") + 1) != "txt"))

	if (a.size() > 4 && (a.substr(a.size() - 3) == "dat" || a.substr(a.size() - 3) == "txt"))
	{
		std::cout << "correct" << std::endl;
	}

	else
	{
		std::cout << "incorrect" << std::endl;
	}

	return 0;  // <--- Not required, but makes a good break point for testing.
}

I am not sure why you need this: a.size() > 4

Andy

Edit
Last edited on
I am not sure why you need this:

One might not want to compute a.substr(-2)
Consider this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

using namespace std;

int main()
{
  string a = "f.dat" ;

  bool correct_ending = false;
  const std::string::size_type pos = a.find_last_of(".");
  if(pos != std::string::npos)
  {
    const std::string ending = a.substr(pos+1);
    correct_ending = ((ending == "dat") || (ending == "txt"));
  }
  if(correct_ending) {

    cout << "correct"<< endl;
  }

  else {

    cout << "incorrect" << endl;

  }


}
A more robust solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <vector>
#include <algorithm> // std::any_of, std::for_each

bool correctExtension(const std::string &filename, const std::vector<std::string>& extensions){
    
    auto dotPos = filename.find_last_of(".");
    
    if(dotPos != std::string::npos){
        const std::string extension = filename.substr(dotPos);
        return any_of(extensions.begin(), extensions.end(), [&](const std::string &ext){
            return ext==extension;
        });
    }
    return false;  
}
    

int main()
{
  
  std::vector<std::string> extensions {".dat", ".txt", /*Add others if you want*/".md"};
  std::vector<std::string> filenames {"myfile.dat", "myfile.txt", "myfile.xml", "myfile.md"};
  
  std::for_each(filenames.begin(), filenames.end(), [&](const std::string &fn){
      if(correctExtension(fn, extensions)){
          std::cout << fn << " has correct extension\n";
      }else{
          std::cout << fn << " does not have correct extension\n";
      }
  });
 }

/*
Good reads
 http://www.cplusplus.com/reference/algorithm/any_of/
 http://www.cplusplus.com/reference/algorithm/for_each/
 https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=vs-2019
*/


Hope that helps
Last edited on
this could have been diagnosed getting pen and paper and just following your program.
1
2
3
4
5
6
string a = "f.dat" ;
if(
   (a.size()<5) //5<5, false
   || (a.substr(a.find_last_of(".")+1) != "dat") //dat not_eq dat, false
   || (a.substr(a.find_last_of(".")+1) != "txt") //dat not_eq txt, true
)

really, learn to read what you write
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>
using namespace std;

string extension( const string &filename )
{
   int pos = filename.find_last_of( '.' );
   return pos == string::npos ? "" : filename.substr( pos + 1 );
}


int main()
{
   for ( string f : { "myfile.dat", "myfile.txt", "myfile.md", "myfile" } ) cout << f << " has extension " << extension( f ) << '\n';
   
   string fn;
   cout << "Enter a filename: ";   cin >> fn;
   string ext = extension( fn );
   cout << fn << ( ext == "dat" || ext == "txt" ? " has " : " does not have " ) << "a required extension\n";
}
Last edited on
Thanks for the help!!!!!!!!!!!!!!!!!!!!!!!!!
@keskiverto,

Thanks. I was not thinking in that direction.

Andy
Topic archived. No new replies allowed.