2012-07-01 3 views
3

프로그래밍 문제를 연습하고 인기있는 "문자열의 역 단어"문제를 코딩하려고했습니다.문자열의 단어를 뒤집어 쓰는 C 코드의 버그

나는 C로 자신 만의 코드를 만들려고 노력했다. 나는 부분적으로 올바르게 할 수 있었다. 즉, "안녕하세요 세상"은 "세상 올레"가됩니다. 그 버그가 여기에 무엇이 있는지 궁금합니다. 나는 어딘가에 1 버그로 벗어나고 있다고 생각한다.

라이브러리 기능을 사용하지 않고 가능한 한 많이하고 싶었습니다. 여기이 문제를 찾으려고 & 많은 솔루션을 찾았지만 왜 내 솔루션이 작동하지 않는지 알고 싶습니다.

#include <stdio.h> 
#include <string.h> 

void reverse(char*, int); 

int main(int argc, char **argv) 
{ 
    char st[]= "hello world"; 
    int len = strlen(st); 
    int i=0,j=0; 

    reverse(st,len-1); // Reverse the entire string. hello world => dlrow olleh 

    while(st[j]){ //Loop till end of the string 
     if (*(st+j) == ' ' || *(st+j) == '\0') { //if you hit a blank space or the end of the string 
      reverse(st+i,j-1); // reverse the string starting at position i till position before the blank space i.e j-1 
      i=++j; //new i & j are 1 position to the right of old j 
     } 
     else { 
      j++; //if a chacacter is found, move to next position 
     }    
    }  

    printf("%s",st); 
    return 0; 
} 

void reverse(char *s, int n) 
{ 
    char *end = s+n; //end is a pointer to an address which is n addresses from the starting address 
    char tmp; 
    while (end>s) //perform swap 
    { 
     tmp = *end; 
     *end = *s; 
     *s = tmp; 
     end--; 
     s++; 
    } 
} 

감사합니다 : 여기

코드입니다!

UPDATE : http://ideone.com/TYw1k

+4

이 학습 사례를 감안할 때 논리적으로 코드와 효과 (아마도 종이와 펜을 사용하여)를 추적 해 보았습니까?또는 디버거를 사용하여 실제 런타임을 추적하려고 했습니까? – reuben

+0

예 디버거를 사용했습니다. j의 값이 11이면 루프가 종료됩니다. 문자열의 11 번 위치에있는 문자는 '\ 0'입니다. 문제가 무엇인지 생각해 볼 수 있습니다. 내가 생각한 것을 시험해보고 질문을 업데이트 할 것입니다. – Bharat

+0

잠깐, 문자열을 뒤집은 다음 그 안의 모든 단어를 뒤집을 수 있습니까? 원래의 문자열을 제공하면 안됩니까? – Shahbaz

답변

3

문제는

while(st[j]){ //Loop till end of the string 
    if (*(st+j) == ' ' || *(st+j) == '\0') 

while 조건이의 끝에서 입력되는 루프를 방지한다는 것입니다 : @Daniel 피셔의 답변에 따라, 여기에 올바른 구현 문자열이므로 마지막 단어가 다시 반대로되지 않습니다.

귀하는 무한 루프를 만들고, 반전 후

if (st[j] == '\0') break; 

을 추가하거나 while 루프가 왼쪽 된 후 마지막 단어를 반전 할 수 있습니다.

+0

@Daniel Fischer 감사합니다. 이제 마지막 단어가 반전되도록 루프가 종료 된 후 역 호출을 수행했습니다. 이제 단어가 바뀐 것입니다. 루프가 종료 된 후 빈 공간 & j가 문자열의 끝에있을 때 i는 위치에 있습니다. 나는'reverse (st + i, j-i-1);을하고 마지막 단어를 뒤집습니다. – Bharat

+0

이 팁을 사용하여 코드를 수정했을 때이 대답을 수락합니다 :) – Bharat

3

당신은 하나의 오류 참으로 오프가 : 전화

reverse(st+i,j-1); 

당신의 코드의 위치에 문자열의 시작 부분까지의 길이입니다 j-1를 전달

reverse(st+i,j-i-1); 

해야한다 마지막 공간; 마지막 단어의 길이 여야하므로 첫 번째 문자 (예 : i)의 색인을 뺄 필요가 있습니다.

마지막 단어를 역전하지 않습니다 (자세한 내용은 the other answer 참조).

+0

나는 이것을 깨닫고 j-1을 i-j-1로 변경했습니다. 교훈 - 디버거로 건너 뛰기 전에 종이에 코드를 사용해보십시오! 시작 주소에서 i-j 위치를 계산해야하므로 i-j-1이어야합니다. – Bharat

+0

strlen과 co가없는 단순하고 우아한 솔루션이 있습니다. 내 대답을 보라. –

+0

@RBK 디버그 인쇄도 도움이됩니다. 잘못된 길이를 전달한다는 사실이 당신에게 뛰어 올랐을 것입니다. – dasblinkenlight

0

문자열에서 단어를 뒤집고 전체 문자열을 뒤집지 않고 한 단어를 역방향으로 바꾸고 싶다고 생각합니다. 따라서 첫 번째 역방향을 삭제 한 다음 위의 제안 된 변경 사항을 적용하십시오.

#include <stdio.h> 
#include <string.h> 

void reverse(char*, int); 

int main(int argc, char **argv) 
{ 
    char st[]= "hello world"; 
    int i=0, j=0; 

    while(st[j]){ //Loop till end of the string 
    if (st[j] == ' ') { //if you hit a blank space or the end of the string 
     reverse(&st[i], j - i - 1); // reverse the string starting at position i till position before the blank space i.e j-1 
     i = ++j; //new i & j are 1 position to the right of old j 
    } 
    else { 
     j++; //if a chacacter is found, move to next position 
    }    
    } 
    reverse(&st[i], j - i - 1); 


    printf("%s\n",st); 
    return 0; 
} 

void reverse(char *s, int n) 
{ 
    char *end = s + n; //end is a pointer to an address which is n addresses from the starting address 
    char tmp; 

    while (end > s) //perform swap 
    { 
    tmp = *end; 
    *end = *s; 
    *s = tmp; 
    end--; 
    s++; 
    } 
} 

입력 문자열이 '\ 0'이거나 'Hello world'와 같은 경우주의하십시오. 위의 코드는 이러한 상황을 관리하지 않습니다. 그것에 대해 생각 해봐!

+0

코드가 어떻게 작동하는지 알 수 없습니다. 나는 "안녕하세요 세상"을 "세계 안녕하세요"가되기를 원했고 "dlrow olleh"가 아니라고 원했습니다. 귀하의 코드는 개별 단어를 뒤집습니다 : http://ideone.com/edomq. 또한 내가 왜 당신이하고 싶어하는지 모르겠다. 'st + i' 그 자체가 그것을 더 우아하게 보인다. – Bharat

+0

앱 괜찮습니다. 나는 undestand 안녕하세요 세계 -> olleh dlrow! (역 단어). 죄송합니다! – saxi

+0

아, 좋아. 내 질문에 대한 편집을 확인하십시오. 나는 작동하는 구현과 링크를 포함시켰다. – Bharat

0

@RBK : 먼저 문자열을 가져 와서 거꾸로 한 다음 특정 단어를 기반으로 다시 되돌립니다. 나는 이렇게하는 약간 다른 접근법을 따랐다. 나는 필요하다면 그 문자열을 그대로 사용하고, 그렇지 않으면 같은 단어를 그대로 복사한다.

int main(int argc, char*argv[]) 
{ 
    char *p,st[]= "hello world"; 
    char buf[12]={0}; 
    char fstr[12]={0}; 
    int i=0,j=0,k=0,l=0; 

    for(p=st;*p!='\0';p++){ 

     //Get the Word 
     buf[i++] = *p; 

     //Parse the Word  
     if(*p == ' ' || *(p+1) == '\0'){ 

      buf[i]='\0'; 
      j=i-1; 
      i=0;  //reset counter 

      if(k){  //reverse word and copy 

       while(j>=i){ 

        fstr[l++]=buf[j--]; 

       }    

       k=0;   

      } 
      else{  //copy same word 

       while(i<=j){ 

        fstr[l++]=buf[i++];      

       } 

       i=0; //reset counter 
       k=1; 

      } 

     } 

    } 

    fstr[l]='\0'; 
    printf("%s\n",fstr); 
    return 0; 
} 
관련 문제