2017-05-10 6 views
4

그래서 .txt 파일의 숫자를 정수로 읽고 싶습니다.C++ ifstream 읽기 전용 단어 수

file.txt를 :

hello 123-abc 
world 456-def 

현재 코드 :

int number; 
ifstream file("file.txt"); 
while (!file.eof()) 
{ 
    file >> number; //123, 456 
} 

지금이 분명히 나던 작업과는 "동안"하지만 난 그냥이 문제를 해결 얻을 수없는이를 해결하기 위해 노력하고 살아야 .

std::string currentLine = ""; 
std::string numbers = ""; 
ifstream file("file.txt"); 
if(file.is_open()) 
{ 
    while(std::getline(file, currentLine)) 
    { 
     int index = currentLine.find_first_of(' '); // look for the first space 
     numbers = currentLine.substr(index + 1, xyz); 
    } 
} 

XYZ이 경우 경우의 수의 길이 (3 : 파일이 열려있는 경우

+0

그래서 당신이 수하지 않을 수 있습니다 아무것도 무시하고 싶어? 문자열을 읽으십시오. 그런 다음 정규식을 사용하여 문자열을 일치시키고 정규 표현식의 일치 그룹 중 하나에서 숫자를 가져옵니다. 아직 혼란스러워? :-) 정규 표현식은'123' 같은 일련의 연속 된 문자 때문에 다른 종류의 읽기보다 더 간단합니다. 그러나'stoi'는 일반적으로 문자열 앞에있는 많은 정수를 풀 수 있습니다. YMMV – AndyG

+1

while (! file.eof()) do does do what think do – pm100

답변

1

이렇게 할 수있는 방법에는 여러 가지가 있습니다. 스트림의 읽기 위치에 숫자 같은 것이 없기 때문에 시도한 메서드가 작동하지 않습니다. 따라서 입력이 실패하고 스트림 페일 비트이 설정됩니다. eof에 대해서만 테스트 중이므로 계속 반복됩니다. 자세한 내용은 Read this을 참조하십시오.

간단한 방법은 한 번에 한 줄을 읽고 std::strtol 내지 제 인수를 이용하여 상기 제 번호를 검색하는 것이다

#include <iostream> 
#include <string> 
#include <experimental/optional> 

std::experimental::optional<int> find_int_strtol(const std::string & s) 
{ 
    for(const char *p = s.c_str(); *p != '\0'; p++) 
    { 
     char *next; 
     int value = std::strtol(p, &next, 10); 
     if(next != p) { 
      return value; 
     } 
    } 
    return {}; 
} 

int main() 
{ 
    for(std::string line; std::getline(std::cin, line);) 
    { 
     auto n = find_int_strtol(line); 
     if(n) 
     { 
      std::cout << "Got " << n.value() << " in " << line << std::endl; 
     } 
    } 
    return 0; 
} 

이 조금 투박하고 또한 네거티브 감지 할 너는 원하지 않을지도 모른다. 그러나 간단한 접근 방법입니다. 문자가 추출 된 경우 next 포인터는 p과 다릅니다. 그렇지 않으면 함수가 실패합니다. 그런 다음 p을 1 씩 증가시키고 다시 검색하십시오. 그것은 다항식 검색처럼 보이지만 그것은 선형입니다.

저는 C++ 17에서 std::optional을 사용했지만 C++ 14 컴파일러에서 테스트했습니다. 편의를위한 것입니다. 그것없이 함수를 작성할 수 있습니다.

라이브 예 is here.

이와 같은 문제를 해결하는 더 유연한 방법은 정규 표현식을 사용하는 것입니다. 이 경우 간단한 정규 표현식 검색 만 있으면됩니다. 다음은 양의 정수 만 찾을 수 있지만이 유형의 패턴을 사용하여 복잡한 데이터를 찾을 수도 있습니다.

std::experimental::optional<int> find_int_regex(const std::string & s) 
{ 
    static const std::regex r("(\\d+)"); 
    std::smatch match; 
    if(std::regex_search(s.begin(), s.end(), match, r)) 
    { 
     return std::stoi(match[1]); 
    } 
    return {}; 
} 

라이브 예를 is here : 헤더 <regex>을 포함하는 것을 잊지 마십시오.

0

당신은, 다음 다음 첫 번째 번호를 해당 현재 행을 구문 분석, 현재 행을 얻을 확인해야 항상 상수) 또는 부분 문자열을 가져 와서 다음 빈 공간을 찾을 수 있습니다. (index, currentLine.back() - index);

나머지 행운을 찾아 낼 수있을 것입니다.

+0

숫자 앞에 항상 공백이 있는지 어떻게 알 수 있습니까? – paddy

+0

두 개의 동일한 라인을 보여주기 때문에이 예제에서는 표준이라고 가정하지는 않지만, 파일의 앞뒤에 공백이있는 한 개념은 동일합니다. 서브 스트링을 취득 해, int로 캐스트 할 수 있는지 보아주세요. 그렇지 않은 경우는 다음의 substr를 시도해주세요. –

0

한 줄 한 줄을 읽고 숫자가 아닌 모든 문자를 제거하십시오. std::vector으로 푸시하기 전에 std::stoi으로 끝내세요.

std::ifstream file{"file.txt"}; 
std::vector<int> numbers; 

for (std::string s; std::getline(file, s);) { 
    s.erase(std::remove_if(std::begin(s), std::end(s), 
     [] (char c) { return !::isdigit(c); }), std::end(s)); 
    numbers.push_back(std::stoi(s)); 
} 

또는 숫자가 아닌 문자를 제거하는 std::regex_replace를 사용

auto tmp = std::regex_replace(s, std::regex{R"raw([^\d]+(\d+).+)raw"}, "$1"); 
numbers.push_back(std::stoi(tmp)); 

Live example