簡體   English   中英

比較文本文件的元素

[英]Comparing elements of text file

我正在嘗試將四個數字的塊相互比較,以制作一個新的輸出文件,其中只有那些滿足:四位數字,所有數字都相同。

這是我的輸入文件代碼:

int main() { ofstream outfile ("text.txt"); outfile << "1111 1212 4444 \\n 2222 \\n \\n 8888 4567" <<endl;

我想把它分成四個塊,比如“1111”、“1212”等等,以便能夠只在新的輸出文件中寫入滿足要求的那些。 我決定將整個文件轉換成一個整數向量,以便能夠比較它們。

   char digit;
   ifstream file("text.txt");
   vector <int> digits;

   while(file>>digit)
   {
      digits.push_back(digit - '0');
   }

我想比較它們的方法看起來像這樣:

bool IsValid(vector<int> digits){

   for (int i=0; i<digits.size() i++)
   {
      if(digits[0] == digits[1] == digits[2] == digits [3])
         return true; 

      else 
      {
         return false;
      }
   }
}

然而,這只會比較第一個塊,你會以不同的方式做嗎? 或者我應該繼續做矢量的想法。

嗯,我看到的都是比較復雜的。

顯然您想檢查字符串中的模式。 並且模式通常與正則表達式匹配。

這將為您提供一個非常簡短的解決方案。 使用std::regex 正則表達式是 C++ 標准庫的一部分。 而且它們也很容易使用。 對於您的情況,您的正則表達式為(\\d)\\1{3} 因此,一個數字后跟 3 個相同的數字。

然后程序可以歸結為一個語句:

#include <sstream>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <regex>

std::istringstream testData{R"(1111 1212 444414 555
2222

8888 4567)"};

int main()
{
    std::copy_if(
        std::istream_iterator<std::string>(testData), 
        {},
        std::ostream_iterator<std::string>(std::cout,"\n"),
        [](const std::string& s){
            return std::regex_match(s,std::regex(R"((\d)\1{3})"));
        }
    );

    return 0;
}

當然,您可以使用任何std::fstream而不是std::istringstream

當然,這只是眾多可能的解決方案之一,也許不是最好的解決方案。 . .

我決定將整個文件轉換成一個整數向量,以便能夠比較它們。

然后您可以直接從流中提取int s( file >> int_variable )並檢查它們是否是 1111 的倍數。

代碼中的建議:

#include <fstream>
#include <iomanip>
#include <iostream>
#include <vector>

bool IsValid(int number) {
    // Check that number is in the valid range and that it's a multiple of 1111.
    return number >= 0 && number <= 9999 && (number / 1111) * 1111 == number;
}

// A function to process the values in a stream
std::vector<int> process_stream(std::istream& is) {
    std::vector<int> digits;
    int number;

    while(is >> number) {
        if(IsValid(number)) // Only save valid numbers
            digits.push_back(number);
    }
    return digits;
}

int main() {
    std::vector<int> digits;

    // Check that opening the file succeeds before using it
    if(std::ifstream file = std::ifstream("text.txt")) {
        digits = process_stream(file);
    }

    // Print the collected int:s
    for(int x : digits) {
        std::cout << std::setw(4) << std::setfill('0') << x << '\n';
    }
}

另一種方法是簡單地將每個輸入作為一個字符串處理,並在字符串中的每個字符上循環驗證它是一個數字並且等於前一個字符。 如果任一測試失敗,則讀取的不是所有數字都相等的整數。

例如你可以這樣做:

#include <iostream>
#include <sstream>
#include <string>
#include <cctype>

int main (void) {

int main (void) {

    std::string s;
    std::stringstream ss { "1 11 1111 foo 2222\nbar 1212\n4444\n8888\n4567\n"
                            "3433333 a8\n9999999999999999999\n" };

    while (ss >> s) {                               /* read each string */
        bool equaldigits = true;                    /* flags equal digits */
        for (size_t i = 1; i < s.length(); i++)     /* loop 1 - length */
            /* validate previous & current digits & equal */
            if (!isdigit(s[i-1]) || !isdigit(s[i]) || s[i-1] != s[i]) {
                equaldigits = false;                /* if not set flag false */
                break;                              /* break loop */
            }
        /* handle empty-string or single char case */
        if (!s.length() || (s.length() == 1 && !isdigit(s[0])))
            equaldigits = false;
        if (equaldigits)                            /* if all digits & equal */
            std::cout << s << '\n';                 /* output string */
    }
}

上面的std::stringstream只是為程序提供模擬輸入。

注意:如果願意,您可以使用std::string::iterator for循環,或者使用基於范圍的for循環和prev字符來存儲最后看到的內容。在這里,迭代索引同樣容易)

使用 std::string find_first_not_of

使用現有的字符串函數提供了另一種方法。 在比較第一個字符是數字之后,您可以使用std::basic_string::find_first_not_of掃描字符串的其余部分以查找與第一個不同的字符——如果結果不是std::string::npos ,那么你的字符串不都是同一個數字。

#include <iostream>
#include <sstream>
#include <string>
#include <cctype>

int main (void) {

    std::string s;
    std::stringstream ss { "1 11 1111 foo 2222\nbar 1212\n4444\n8888\n4567\n"
                            "3433333 a8\n9999999999999999999\n" };

    while (ss >> s) {                               /* read each string */
        if (!isdigit(s.at(0)))                      /* 1st char digit? */
            continue;
        /* if remainder of chars not equal 1st char - not equal digits */
        if (s.find_first_not_of(s.at(0)) != std::string::npos)
            continue;
        std::cout << s << '\n';
    }
}

兩種方法產生相同的輸出。

示例使用/輸出

$ ./bin/intdigitssame
1
11
1111
2222
4444
8888
9999999999999999999

如其他好的答案所示,還有許多其他方法可以做到這一點。 每種方法都值得理解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM