2013-03-20 3 views
1

나는 내 프로그램에서 다음과 같은 두 개의 문자열을 구문 분석 할 수 있어야합니다 :문자 배열을 delimeter로 나눈 다음 결과를 저장 하시겠습니까?

cat myfile || sort 
more myfile || grep DeKalb 

문자열은 문자 버퍼 [1024]에 저장되고있다. 내가 왼쪽에 char 배열을 가리키는 포인터와 오른쪽에 char 배열을 가리키는 포인터를두면 다음과 같이 호출 할 수 있습니다.

int execvp(const char *file, char *const argv[]); 

위의 두 문자열을 문자 버퍼 char 버퍼 [1024]에 저장하면 execvp 명령에 대한 올바른 인수를 얻을 수있는 방법에 대한 아이디어가 있습니다. ?

왼쪽의 첫 번째 단어를 저장하려면 char * left가 필요하고 왼쪽에는 두 단어를 모두 포함하도록 char * const leftArgv []가 필요합니다. 그렇다면 나는 똑같은 것이 필요하다. 나는 지금 2 시간 동안 strtok와 함께 어지럽히고 있었다. 그리고 나는 벽을 치고있다. 누구든지 아이디어가 있습니까?

답변

0

이 내가 문제를 해결하는 방법입니다 : 이제

//variables for the input and arguments 
char *command[2]; 
char *ptr; 
char *LeftArg[3]; 
char *RightArg[3]; 

char buf[1024]; //input buffer 

//parse left and right of the || 
number = 0; 
command[0] = strtok(buf, "||"); 

//split left and right 
while((ptr=strtok(NULL, "||")) != NULL) 
{ 
    number++; 
    command[number]=ptr; 
} 

//parse the spaces out of the left side 
number = 0; 
LeftArg[0] = strtok(command[0], " "); 

//split the arguments 
while((ptr=strtok(NULL, " ")) != NULL) 
{ 
    number++; 
    LeftArg[number]=ptr; 
} 

//put null at the end of the array 
number++; 
LeftArg[number] = NULL; 

//parse the spaces out of the right side 
number = 0; 
RightArg[0] = strtok(command[1], " "); 

//split the arguments 
while((ptr=strtok(NULL, " ")) != NULL) 
{ 
     number++; 
     RightArg[number]=ptr; 
} 

//put null at the end of the array 
number++; 
RightArg[number] = NULL; 

당신이 배관을 얻을 후, 명령에 LeftArg 및 RightArg을 사용할 수 있습니다를 마우스 오른쪽

execvp(LeftArg[0], LeftArg);//execute left side of the command 

그런 다음 파이프를 명령의 오른쪽으로 연결하고 수행하십시오.

execvp(RightArg[0], RightArg);//execute right side of command 
+0

이것은 내 progra의 전체 작동 코드가 아닙니다. 엠. 이것은 단지 내 질문에 그 부분을 어떻게하는지 보여주기위한 것입니다. – KateMak

+0

일부 실험 과정에서이 과제가 있습니까? –

+0

그 중 일부는 그렇습니다. 다른 부분은 호기심이었습니다. – KateMak

1

regular expressions에 대해 자세히 알아볼 것을 권합니다. 그리고 고통없이 문제를 해결하기 위해 강력한 정규 표현 엔진을 제공하는 Boost.Regex 라이브러리를 활용할 수 있습니다. 솔루션은 몇 줄의 코드 일 뿐이지 만 여러분이 직접 해보는 것이 좋습니다. 좋은 연습이 될 것입니다. 여전히 문제가 있다면, 몇 가지 결과로 돌아와 당신이 갇혀있는 곳을 분명히 말하십시오.

1

std :: getline (stream, stringToReadInto, delimeter)을 사용할 수 있습니다.

'StringList는' 표준의 형식 정의 : 벡터
StringList Seperate(const std::string &str, char divider, SeperationFlags seperationFlags, CharValidatorFunc whitespaceFunc) 
{ 
    return Seperate(str, CV_IS(divider), seperationFlags, whitespaceFunc); 
} 

StringList Seperate(const std::string &str, CharValidatorFunc isDividerFunc, SeperationFlags seperationFlags, CharValidatorFunc whitespaceFunc) 
{ 
    bool keepEmptySegments  = (seperationFlags & String::KeepEmptySegments); 
    bool keepWhitespacePadding = (seperationFlags & String::KeepWhitespacePadding); 

    StringList stringList; 

    size_t startOfSegment = 0; 
    for(size_t pos = 0; pos < str.size(); pos++) 
    { 
     if(isDividerFunc(str[pos])) 
     { 
      //Grab the past segment. 
      std::string segment = str.substr(startOfSegment, (pos - startOfSegment)); 
      if(!keepWhitespacePadding) 
      { 
       segment = String::RemovePadding(segment); 
      } 

      if(keepEmptySegments || !segment.empty()) 
      { 
       stringList.push_back(segment); 
      } 

      //If we aren't keeping empty segments, speedily check for multiple seperators in a row. 
      if(!keepEmptySegments) 
      { 
       //Keep looping until we don't find a divider. 
       do 
       { 
        //Increment and mark this as the (potential) beginning of a new segment. 
        startOfSegment = ++pos; 

        //Check if we've reached the end of the string. 
        if(pos >= str.size()) 
        { 
         break; 
        } 
       } 
       while(isDividerFunc(str[pos])); 
      } 
      else 
      { 
       //Mark the beginning of a new segment. 
       startOfSegment = (pos + 1); 
      } 
     } 
    } 

    //The final segment. 
    std::string lastSegment = str.substr(startOfSegment, (str.size() - startOfSegment)); 
    if(keepEmptySegments || !lastSegment.empty()) 
    { 
     stringList.push_back(lastSegment); 
    } 

    return stringList; 
} 

및 :

나는 개인적으로 다음과 같습니다 그것으로 구운 몇 가지 추가 기능을 가지고 내 자신의 함수를 사용 CharValidatorFunc는 하나의 char을 취하고 bool을 반환하는 함수에 대한 함수 포인터 (실제로는 펑터와 람다 지원을 허용하는 std :: function)입니다. 그렇게처럼 사용할 수 있습니다 :

StringList results = String::Seperate(" Meow meow , Green, \t\t\nblue\n \n, Kitties!", ',' /* delimeter */, DefaultFlags, is_whitespace); 

그리고 결과를 반환합니다 : { "야옹 야옹", "녹색", "블루", "고양이 한테는!"}

'의 내부 공백을 보존 야옹 야옹 '하지만 변수를 둘러싼 공백과 탭 및 개행 문자를 제거하고 쉼표로 분리하십시오.

(CV_IS 특정 문자 또는 문자열 리터로한다 문자의 특정 컬렉션과 일치하는 펑 객체이다. I는 숯 검증 기능을 결합하는 CV_AND 및 CV_OR가) 리터럴 문자열을

를 I은 극한의 성능이 요구되지 않는 한 std :: string()에 던져서 함수에 넘겨 준다. delimeters를 깨는 것은 자신 만의 롤을 만드는 것이 매우 쉽습니다. 위의 기능은 프로젝트의 일반적인 사용법과 요구 사항에 맞게 사용자 정의되었지만 직접 수정하고 직접 청구하십시오.

이 다른 사람의 슬픔을주는 경우