C++ multiple strings inside an if statement

前端 未结 5 810
北恋
北恋 2020-12-02 02:26

I\'m having an issue trying to check against multiple possibilities in an if statement.

The user inputs a string, and then I check that string against multiple possi

相关标签:
5条回答
  • 2020-12-02 02:37

    Sometimes, data can be a better solution than code.

    std::map<std::string, int> values;
    values["Seven"]=7;
    values["seven"]=7;
    values["7"]=7;
    values["Six"]=6;
    values["six"]=6;
    values["6"]=6;
    
    std::string input;
    std::cin >> input;
    std::cout << values[input];
    

    As Vlad noted, you might be better of converting to lowercase first. This answer is just the straightforward conversion of your code to data. Note that this answer will use a default value of 0 for missing strings; your code left out such a default.

    0 讨论(0)
  • 2020-12-02 02:42

    You cannot compare a variable against multiple values like that in C++. You should be doing:

    if (theString == "Seven" || theString == "seven" || theString ==  "7")
     {
       theInt = 7;
       cout << "You chose: " << theInt << endl;
     }
    else if (theString == "Six" || theString == "six" || theString == "6")
     {
       theInt = 6;
       cout << "You chose: " << theInt << endl;
     }
    
    0 讨论(0)
  • 2020-12-02 02:44

    I suppose that the type of the variable theString is std::string. Otherwise at least this comparison

    theString == "Seven"
    

    does not make sense,

    The condition in the if statement

    if (theString == "Seven" || "seven" || "7")
    

    is equivalent to

    if ( ( theString == "Seven" ) || ( "seven" ) || ( "7" ) )
    

    and always yields true because at least the address of the string literal "seven" is not equal to zero. So this subexpression ( "seven" ) provides that the whole expression will be equal to true.

    You should write

    if (theString == "Seven" || theString == "seven" || theString == "7")
    

    But it would be better at first to convert the string to upper or lower case.

    For example

    #include <algorithm>
    #include <string>
    #include <cstring>
    
    //...
    
    std::transform(theString.begin(), theString.end(), theString.begin(),
        [](char c) { return std::toupper((unsigned char)c);  });
    
    if (theString == "SEVEN" || theString == "7")
    {
        theInt = 7;
        cout << "You chose: " << theInt << endl;
    }
    else if ( theString == "SIX" || theString == "6" )
    {
        theInt = 6;
        cout << "You chose: " << theInt << endl;
    }
    
    0 讨论(0)
  • 2020-12-02 02:50

    This is a classic example of identifying a derived requirement found during implementation. I suggest you consider writing a function to support it.

    change from

    if (theString == "Seven" || "seven" || "7")
    {
    //....
    

    (which is not valid c++ because the if condition is always true)

    change to

    if (0 == compare(theString, "Seven", "seven", "7")
    {
    //....
    

    and declare and implement something like

    // return 0 when theString matches at least one patX
    // else return -1
    int compare(const std::string& theString, 
                const char* pat0,  // no default, must provide
                const char* pat1 = nullptr, 
                const char* pat2 = nullptr, 
                const char* pat3 = nullptr, 
                const char* pat4 = nullptr
                /* add as many patX as you desire */)
    {
        if (0 == theString.compare(pat0)) return 0; // found a match
        //
        // ignore nullptr patterns 
        if (nullptr != pat1) && (0 == theString.compare(pat1)) {
           return(0);
        }
    
        if(nullptr != pat2) && (0 == theString.compare(pat2)) {
           return(0);
        }
        // ...
    
        // when get to end with no match
        return (-1); // indicate no match to any of patterns
    }
    

    I actually prefer the following. The above is somewhat like strstr(), where this uses more functionality of std::string

    int compare(const std::string& theString, // what you are given
                const std::string& patterns)  // concatenated list of search patterns
    {
    //.. 
    }
    

    This you invoke as

    if (0 == compare(theString, "Seven seven SEVEN 7") 
    {
    // 
    

    The implementation must tease apart space delimited patterns .. but this is not difficult, and can easily be implemented in a loop, so no limit to how many comparisons you wish to test.


    When should you consider creating a new function in support of a new derived rerquirement?

    It is my practice to create the new function when I can identify 3 or more uses. Good luck.


    Found some code I wrote a few years ago, fixed it up, added demos ...

    Code compiles and seems to run, but very little testing.

    • I created minimal packaging -- a dummy namepace (dtb - for d___'s tool box), and a dumy class (T471_t - test 471)

    dtb::T471_t provides private methods for your review.

    • size_t compare(const std::string s, std::string patterns)

    • size_t grep(const std::string pfn, const std::string patterns, std::ostream& an_ostream = std::cout)

      -- uses compare()

    • size_t cpuinfoGet()

      -- uses grep

      -- "wc < /proc/cpuinfo" (a 'well known file' on ubuntu) reports 54 lines on my 2 core machine, more cores, more lines

    • size_t coreCountGet()

      -- uses grep()

      -- creates nullDev to suppress grep normal output


    #include <chrono>
    #include <fstream>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <cassert>
    
    // 'compressed' chrono access --------------vvvvvvv
    typedef std::chrono::high_resolution_clock  HRClk_t; // std-chrono-hi-res-clk
    typedef HRClk_t::time_point                 Time_t;  // std-chrono-hi-res-clk-time-point
    typedef std::chrono::microseconds           US_t;    // std-chrono-microseconds
    using   namespace std::chrono_literals;   // support suffixes like 100ms
    
    // examples:
    //
    //   Time_t start_us = HRClk_t::now();
    //
    //   auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
    //   auto     count_us = duration_us.count();
    //   or
    //   std::cout << "  complete " << duration_us.count() << " us" << std::endl;
    
    namespace dtb
    {
       class T471_t
       {
          const std::string dashLine = ("  --------------------------------------------------------------");
       public:
    
          T471_t() = default;
          ~T471_t() = default;
    
          int exec()
             {
                std::cout << "\n  cpuinfoGet()\n" << dashLine << std::endl;
    
                (void)cpuinfoGet(); // uses grep which uses compare
    
                std::cout << dashLine << std::endl;
    
                // count of lines which contain "processor" in linux file "/proc/cpuinfo"
                std::cout << "\n\n  " << coreCountGet()
                          << " cores on this system. (coreCountGet())\n\n" << std::endl;
    
                return(0);
             }
    
    
       private: // methods
    
          // returns std::string::npos when none of the patterns found,
          // else returns index of earliest found patterns of space delimited substr in
          size_t compare (const std::string& s,
                          std::string        patterns) // pass by value
             {
                size_t    found = std::string::npos;
                size_t patCount = 0;
                std::stringstream ssPat(patterns + ' '); // load patterns into ram based stringstream
                //                            ^^^^^ -- getline() can cause eof() in this
                const char delim = ' '; // see getline()
    
                do
                {
                   if(0 == patterns.size()) break; // no patterns to search for, kick out
                   if(0 == s.size())     break; // no string in which to search, kick out
    
                   do {
                      std::string pat;
                      (void)std::getline(ssPat, pat, delim); // extract 1 space delimited pattern
    
                      if(false == ssPat.good())
                      {
                         if(ssPat.eof()) break; // quitely exit, a normal op
    
                         // let user know of patten problem
                         std::cerr << "\n  err pattern extract: " << patterns
                                   << "  (" << patCount << ')' << std::endl;
                         break;
                      }
                      patCount += 1;
    
                      //trimLeadingWhiteSpace(patterns);  // tbr
                      //trimTrailingWhiteSpace(patterns); // tbr
    
                      if(0 == patterns.size()) break; // no more patterns
    
                      // search s for pat
                      found = s.find(pat);
    
                      if(found != std::string::npos) break; // one of the patterns found in s
    
                   } while(1); // repeat until 1 found or all patterns tried
    
                }while(0);
    
                return(found);
             } // size_t compare (const std::string& s, std::string patterns)
    
    
    
          size_t grep(const std::string pfn,
                      const std::string patterns, // concatenated list of search patterns
                      std::ostream&     an_ostream = std::cout) // redirectable
             {
                size_t   foundCount = 0;
    
                an_ostream << "  grep (" << pfn << ", [" << patterns
                           << "] )" << std::endl;
                do
                {
                   std::ifstream infile(pfn);
    
                   if(!infile.is_open())
                   {
                      an_ostream << pfn << " not found.\n" << std::endl; // tbr - std::cerr?
                      break; // skip over file op's (no close needed)
                   }
    
                   do
                   {
                      if(infile.eof()) break;  // file empty?
    
                      std::string lineIn;
                      (void)getline(infile, lineIn); // default delimiter is \n
    
                      if (0 == lineIn.size()) continue; // empty line?
    
                      size_t found = compare(lineIn, patterns); // any of patterns in lineIn?
    
                      if(std::string::npos != found) // found at least one pattern
                      {
                         an_ostream << "  " << lineIn << std::endl; // found it, print it
                         foundCount += 1;
                      }
                      // else no pattern found - continue until eof of inFil
    
                   } while(1);
    
                   infile.close();
    
                }while(0);
    
                return(foundCount);
             } // size_t grep(const std::string pfn, const std::string patterns, std::ostream& an_ostream = std::cout)
          //                                space delimited list of ---^^^^^^^^
    
    
    
          size_t cpuinfoGet()
             {
                size_t count = grep("/proc/cpuinfo",  // pfn
                                    "bogomips model name processor"); // patterns to search for
                std::cout << "\n  info lines: " << count << std::endl;
                return(count);
             } // size_t cpuinfoGet(void)
    
    
    
          size_t coreCountGet()
             {
                // create a no-ouptput output
                std::ofstream nullDev; // and do not open
                nullDev.setstate(std::ios_base::badbit); // set error, ignore errors, do not close
    
                size_t retVal = grep(std::string("/proc/cpuinfo"),
                                     std::string("processor"),  // line count of "processor" is core count
                                     nullDev); // nullDev -- no output
                return(retVal);
             } // size_t coreCountGet()(void)
    
       }; // class T471_t
    } // namespace dtb
    
    
    int main(int /*argc*/, char** /*argv[]*/)
    {
      Time_t start_us = HRClk_t::now();
    
      int retVal = -1;
      {
         dtb::T471_t  t471;
         retVal = t471.exec();
      }
    
      auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
    
      std::cout << "  FINI   " << duration_us.count() << " us" << std::endl;
      return(retVal);
    }
    

    Output:

    cpuinfoGet()
    --------------------------------------------------------------
    grep (/proc/cpuinfo, [bogomips model name processor] )
    processor   : 0
    model       : 75
    model name  : AMD Athlon(tm) 64 X2 Dual Core Processor 5000+
    bogomips    : 4809.67
    processor   : 1
    model       : 75
    model name  : AMD Athlon(tm) 64 X2 Dual Core Processor 5000+
    bogomips    : 4809.67
    
    info lines: 8
    --------------------------------------------------------------
    
    
     2 cores on this system. (coreCountGet())
    
    
     FINI   829 us
    
    0 讨论(0)
  • 2020-12-02 02:53

    Using std::set and c++11 you can do one liner with similar syntax as your.

    check this:

    #include <iostream>
    #include <string>
    #include <set>
    
    int main()
    {
    
      if( (std::set<std::string>{"Seven", "seven", "7"}).count("seven") )
      {
          std::cout << "foo\n";
      }
    
      std::string theString("6");
    
      if( (std::set<std::string>{"Six", "six", "6"}).count(theString) )
      {
          std::cout << "bar\n";
      }
    }
    
    0 讨论(0)
提交回复
热议问题