2013-05-02 3 views
1

의 마지막 단어 뒤에 내가는 fgets를 사용하여 파일에서 다음 라인을 읽고있다 동안 종료 :루프 즉시 라인

#C one two three four five six seven eight nine ten eleven

(#C 제외) 각 단어는 열 제목이다. 따라서 내 파일에는 열이 11 개 있습니다.

제 목표는이 줄을 각 단어의 토큰으로 나누는 것입니다. 또한, 나는 열 머리글이 11 개 있다고 계산할 필요가있다. (열 머리글은 11보다 많거나 적을 수 있습니다.)

제 문제는이 줄 끝의 공백입니다. 여기 내가 사용하고있는 코드입니다.

while(1){ 
fgets(buffer,1024,filename); 
if (buffer[1] == 'C'){ 
    char* str = buffer+2; 
    char* pch; 
    pch = strtok(str," "); 
    while(pch != NULL){ 
     pch = strtok (NULL, " "); 
     if (pch == NULL)break; //without this, ncol contains +1 the 
           //amount of columns. 
      ncol++; 
    } 
    break; 
} 
} 

이 코드에는 NcoI = 11 나에게주고 잘 작동 그러나

(선 내가 읽고있다 끝에 하나의 공간이 있습니다) , 줄 끝 부분에 공간이 없다면 ncol = 10을주고 마지막 열을 읽지 않습니다.

내 목적은 끝 부분에 공백이 있는지 여부에 관계없이 ncol = 11을 얻는 것입니다. 나는 그저 마지막 단어를 읽고 더 많은 단어가 있는지 확인하고 그렇지 않다면 종료한다.

답변

0

이 루프를 변경하는 경우 :

while(pch != NULL){ 
    pch = strtok (NULL, " "); 
    if (pch == NULL)break; //without this, ncol contains +1 the 
          //amount of columns. 
     ncol++; 
} 

에 : 문자열에 남아있는 무언가가있는 경우, pch이 NULL 때, 당신은 다른 문자열을, 그래서 increement

while(pch != NULL){ 
    char *keep = pch; 
    pch = strtok (NULL, " "); 
    if (pch == NULL) 
    { 
     if (strlen(keep)) 
     { 
      ncol++; 
     } 
     break; //without this, ncol contains +1 the 
    } 
    //amount of columns. 
    ncol++; 
} 

그래서를 if에서 ncol. 토큰이 설정되어있는 경우

0

당신은 확인할 수 있습니다 [당신은 입력 파일이 "wellformed"되지 않을 경우 if (strlen(keep)) 요구가 더 철저 할 것을 알 수 있습니다,하지만 난 당신의 입력을 가정하고있어 "좋은"입니다] :

if (pch == NULL || *pch == '\0') break; 
+0

NULL과 \ 0의 차이점은 무엇입니까? @Philip – detraveller

+1

@detraveller : 'NULL'은 포인터 값이고, '\ 0'은 문자입니다. 사실 컴파일러는 양쪽 모두에서 int를 '0'으로 만든다. 그래서 그것은 단지 설명을위한 것이다. '* pch == '\ 0''은 문자열의 길이가 0인지를 확인하는 가장 빠른 방법입니다. – Philip

0

다른 솔루션보다 유연, 필요 C++ 11 지원

#include <iostream> 
#include <string> 
#include <vector> 

template <typename Result, typename StringType> 
void split(StringType const& contents, Result &result, StringType const& delimiters = "\n") 
{ 
    typedef typename Result::value_type value_type; 

    static_assert(std::is_same<value_type, StringType>::value, "std::is_same<value_type, StringType>::value == false,\n" 
        "The value_type of Result should be the same as StringType"); 

    typename StringType::size_type pos, last_pos = 0; 
    while(true) 
    { 
     pos = contents.find_first_of(delimiters, last_pos); 
     if(pos == StringType::npos) 
     { 
      pos = contents.length(); 

      if(pos != last_pos) 
       result.emplace_back(contents.data() + last_pos, pos - last_pos); 

      break; 
     } 
     else 
     { 
      if(pos != last_pos) 
       result.emplace_back(contents.data() + last_pos, pos - last_pos); 
     } 

     last_pos = pos + 1; 
    } 
} 

int main() 
{    
    std::string const input = "#C one two three four five six seven eight nine ten eleven"; 
    std::vector<std::string> results; 
    split(input, results, std::string(" ")); 
    for(auto const &data : results){ 
     std::cout<<data<<std::endl; 
    }  

    return 0; 
} 
0

기능 fgets가이 파일에서 읽은 개행 문자가 포함되어 있기 때문에 당신이하고 마지막에 공백없이 다른 수를 얻고있다 .

그래서 줄 끝 부분에 공백이 있으면 줄 바꿈 문자는 별도의 토큰으로 간주됩니다.

strtok 기능, 원격 if (pch == NULL)break; 라인에 제공되는 토큰으로 '\ n'은 줄 바꿈 문자 '\ r에'&을 포함해야이 문제를 극복하기 위해.

코드는 다음과 같습니다.

while(1){ 
    fgets(buffer,1024,filename); 
    if (buffer[1] == 'C'){ 
     char* str = buffer+2; 
     char* pch; 
     pch = strtok(str," \r\n"); 
     while(pch != NULL){ 
      pch = strtok (NULL, " \r\n"); 
      //amount of columns. 
      ncol++; 
     } 
     break; 
    } 
}