2016-10-04 42 views
1

所以我给出一个字符串作为这样的:意外的行为时,使用的strtok

Hello6World66ABC 

当我被告知更换字符的单个实例“6”是两个asteric字符"**"

并且6的多个实例是这些字符中的两个"^^"(连续数字6的任何组合都有资格

我试图通过传递char *中的每个字符来做到这一点,然后如果我找到6个字符,我检查下一个字符是否是6,如果不是我们有第一个情况,否则我们有第二个情况(多个6)。

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

int main(void) { 
    char * str; 
    int i; 
    str = malloc(17); 

    strcpy(str,"Hello6World66ABC"); 

    for(i=0; i < strlen(str); i++) { 
     if(str[i] == '6') { 
      if(str[i+1] != '6') { 
       char * token = strtok(str,"6"); 
       strcpy(str,token); 
       strcat(str,"**"); 
       printf("String is now %s\n",str); 

       token = strtok(NULL,""); /*get the rest of the string*/ /* should be World66ABC */ 
       printf("Rest of the string is %s\n",token); 
       str = (char *) realloc(str,strlen(str) + strlen(token) + 1); 
       strcat(str,token); 
       printf("String is now %s\n",str); 
       /* should be Hello**World66ABC */ 
      } 
      else { 
       /*if the next characters are also (multiple ones in a row) 6's, replace it with two ^^ characters*/ 
       char * token = strtok(str,"6"); 
       token = strtok(NULL,"6"); 
       printf("TOKEN IS %s\n",token); 

       strcpy(str,token); 
       strcat(str,"^^"); 

       token = strtok(NULL,""); /*get the rest of the string*/ /* should be World66ABC */ 
       printf("Rest of the string is %s\n",token); 
       str = (char *) realloc(str,strlen(str) + strlen(token) + 1); 
       strcat(str,token); 
       printf("String is now %s\n",str); 


      } 
     } 
    } 

    free(str); 
    return 0; 
} 

通过给出的字符串,我期待最终的字符串应该是:

Hello**World^^ABC 

然而,我的strtok调用不工作,我希望的方式。

在第二个if语句中,我检查if (str[i+1] != '6'),我检查是否只有一个单独的6,有。

然后我打电话的strtok和打印之前的一切吧: 它打印:Hello**

哪个是正确的 我strcat的新角色上它其中的作品,但是,我的第二个strtok的电话,得到休息的字符串,它只是不起作用。

相反,它打印:

"Rest of the string is *" 

所以很明显它没有得到字符串的休息,即使我设定的分隔符是一个空字符串。

我试图将分隔符更改为其他字符,但每个都会产生相同的输出。我也重新分配,因为字符串变长了,在第一种情况下。此外,其他声明似乎永远不会运行,即使我明确有一个情况,其中有多个6。

我不确定我在哪里出错了,有什么想法?

+4

我不那么肯定'strtok'甚至对于这里的工作的工具。 –

+0

既然你循环每个字符,我看不需要'strtok' - 你已经知道6s在哪里了。另外,更好的选择可能是创建第二个字符串缓冲区来创建一个新的字符串。 –

+0

那么,究竟是什么**是您的输入?为什么使用'strtok'呢?另外:如果我正确地阅读,你''strcat'两个'**'到原来的字符串。这段代码看起来不必要地被抛弃了,完成这个简单的任务。 @FredLarson是正确的'strtok'是错误的功能。 – Olaf

回答

1

这是未经测试的,但它显示了大体的想法。

strcpy(str,"Hello6World66ABC"); 

// New string will be at most 2x as long 
char *new_str = calloc(strlen(str) * 2 + 1, 1); 
int new_str_index = 0; 

for (int i = 0; 0 != str[i]; i++) { 
    // Check for 6 
    if ('6' == str[i]) { 
     // Check for 2nd 6 
     if ('6' == str[i+1]) { 
      // Add chars 
      new_str[new_str_index++] = '^'; 
      new_str[new_str_index++] = '^'; 
      // Consume remaining 6s - double check this for off-by-one 
      while ('6' == str[i+1]) i += 1; 
     } 
     else { 
      // Add chars 
      new_str[new_str_index++] = '*'; 
      new_str[new_str_index++] = '*'; 
     } 
    } 
    // No 6s, just append text 
    else { 
     new_str[new_str_index++] = str[i]; 
    } 
} 
+0

并且将new_str复制到原始str中,我必须重新分配,然后将memmove()避免重叠? – efoekfoe

+0

是的,或者我会:'free(str); str = strdup(new_str);'。 –

+1

当然,假设原始字符串是可重新分配的。如果它是一个指向字符串的指针(不是在任何发布的代码中都是这种情况),那么你不能期望成功地重新分配。最通用的解决方案是返回一个指向新字符串的指针。 –

1

OP问一个简单的方法来改变字符串中的'6'字符。如果您想要写入另一个字符串而不是直接打印,请留给您定义另一个(足够大的)字符串,然后将字符复制到该字符串,而不是stdout。但不要试图改变传递的字符串,它注定要失败。

#include <stdio.h> 

void sixer(char *str) 
{ 
    int i = 0, sixes; 
    while(str[i] != '\0') { 
     if(str[i] == '6') { 
      sixes = 0; 
      while(str[i] == '6') { 
       sixes++; 
       i++; 
      } 
      if(sixes == 1) { 
       printf("**"); 
      } 
      else { 
       printf("^^"); 
      } 
     } 
     else { 
      printf("%c", str[i]); 
      i++; 
     } 
    } 
    printf("\n"); 
} 

int main(void) 
{ 
    sixer("Hello6World66ABC"); 
    sixer("6"); 
    sixer("66666"); 
    return 0; 
} 

程序输出

Hello**World^^ABC 
** 
^^