【问题标题】:C change string between characterC在字符之间更改字符串
【发布时间】:2020-11-03 12:33:19
【问题描述】:

假设我有一个字符串“hello_from_here”。我想更改“_”之间的子字符串,例如“hello_21223_here”。

我想我应该使用strtok,但到目前为止我还没有成功。

到目前为止,我正在尝试做:

char input[] = "this_is_name";
char* first_part = strtok(input, "_");
char* second_part = strtok(strtok(input, "_"), "_");
char output[64];
int pos = 44;
snprintf(output,sizeof(output),"%s%06d%s", first_part, pos, second_part);

我知道snprintf 是正确的,但是strtok 失败了。

输出是:

this000044this

我的目标输出是:

this000044name

【问题讨论】:

  • 因为替换的长度与要替换的部分的长度不同,所以您需要一个输出字符串来保存结果。你不能在同一个字符串中替换它。
  • 您的snprintf 是未定义的行为。你不能同时从同一个内存中读写——有些东西会被覆盖。 first_partsecond_part 指向 output 内存中。为snprintf 选择不同的目的地,或选择不同的复制方法。但是..你不是说strtok(input, ...吗?
  • “我失败了”不是问题描述。发生了什么?为什么错了?

标签: c string strtok string.h


【解决方案1】:

strtok返回值:

此函数返回一个指向字符串中第一个标记的指针。如果没有要检索的令牌,则返回空指针。

由于您将input 作为第二个strtok 的第一个参数传递,它会重置指针的位置。

解决它的一种方法是在随后的strtok 中传递一个 NULL 指针,在这种情况下是两次,因为您想跳过 is 标记:

//...
char *first_part = strtok(input, "_");
char *second_part = strtok(NULL, "_");
second_part = strtok(NULL, "_");
//...

Live demo

【讨论】:

    【解决方案2】:

    这是我的尝试

    #include <stdio.h>
    
    void replacemarks(char *dst, const char *src, char c, const char *r) {
        while (1) {
            while (*src && (*src != c)) *dst++ = *src++;
            if (*src == 0) break;
            *dst++ = *src++;
            if (*src == 0) break;
            const char *cc = strchr(src + 1, c);
            if (cc) {
                const char *rr = r;
                while (*rr) *dst++ = *rr++;
                src = cc;
                *dst++ = *src++;
            } else {
                while (*src) *dst++ = *src++;
                break;
            }
        }
        *dst = 0;
    }
    
    int main(void) {
        char line[100];
        while (fgets(line, sizeof line, stdin)) {
            char src[100], c, r[100], dst[100];
            sscanf(line, "%s %c%s", src, &c, r);
            replacemarks(dst, src, c, r);
            printf("replacemarks(..., \"%s\", '%c', \"%s\") ==> \"%s\"\n",
                  src, c, r, dst);
        }
        return 0;
    }
    

    https://ideone.com/LhJaaq

    使用输入运行示例

    hello_from_here _ 21223 this_is_name _ 000044 阿布拉卡达布拉 r foo *一二三* * - - *一二三四* * - - *一二三四 * - - 一二三四* * - - *一二三四五* * - - *一二三四五 * - - 一二三四五* * - -

    输出(针对 Stack Overflow 进行美化):

    替换标记(...,“hello_from_here”,“_”,“21223”)==>“hello_21223_here” 替换标记(...,“this_is_name”,“_”,“000044”)==>“this_000044_name” replacemarks(..., "abracadabra", 'r', "foo") ==> "abrfoora" replacemarks(..., "*one*two*three*", '*', "----") ==> "*----*two*----*" replacemarks(..., "*one*two*three*four*", '*', "----") ==> "*----*two*----*four*" replacemarks(..., "*one*two*three*four", '*', "----") ==> "*----*two*----*four" replacemarks(..., "一*二*三*四*", '*', "----") ==> "一*----*三*----*" replacemarks(..., "*一*二*三*四*五*", '*', "----") ==> "*----*二*----*四* ----*” replacemarks(..., "*一*二*三*四*五", '*', "----") ==> "*----*二*----*四*五" replacemarks(..., "一*二*三*四*五*", '*', "----") ==> "一*----*三*----*五* "

    【讨论】:

      【解决方案3】:

      简单(甚至“幼稚”)的功能:

      char *replaceDup(const char *haystack, const char *replace, int sep)
      {
          char *newstr = malloc(strlen(haystack) + strlen(replace));
          char *wrk = newstr;
      
          if(newstr)
          {
              while(*haystack && *haystack != sep)
              {
                  *wrk++ = *haystack++;
              }
              if(*haystack) haystack++;
              while(*haystack && *haystack != sep)
              {
                  haystack++;
              }
              if(*haystack) haystack++;
              while(*replace)
              {
                  *wrk++ = *replace++;
              }
              while(*haystack)
              {
                  *wrk++ = *haystack++;
              }
              *wrk = 0;
          }
          return newstr;
      }
      

      【讨论】:

        【解决方案4】:

        好吧,够了,但是:

        • 您需要在输入上运行strtok,而不是在输出上...​​
        • 我会在这里使用strchr
        • 您需要指定从first_part 复制多少个字符,否则将复制整个字符串。
        • 第一部分从头开始。第二部分从第一个_ 的位置开始。

        #include <string.h>
        #include <stdio.h>
        #include <assert.h>
        int main() {
            const char input[] = "this_is_name";
            const char *first_part = input;
            const char *second_part = strchr(first_part, '_');
            assert(second_part != NULL);
            size_t first_part_len = second_part - first_part ;
            second_part++; // advance over '_' character
            const char *third_part = strchr(second_part, '_');
            assert(third_part != NULL);
            third_part++;  // advance over '_' character
            char output[64];
            const int pos = 44;
            snprintf(output, sizeof(output), "%.*s_%06d_%s", (int)first_part_len, first_part, pos, third_part);
            printf("%s\n", output);
        }
        

        还有一个没有变量的简短版本,它使用strcspnstrrchr 来查找_,没有错误检查:

        snprintf(output, sizeof(output), 
                "%.*s_%06d%s",  (int)strcspn(input, "_"), input, pos, strrchr(input, '_'));
        

        【讨论】:

          【解决方案5】:

          你可以试试这个:

            char input[] = "this_is_name";
            char *token, *first_part,*second_part, *third_part;
            char output[64];
            int pos = 44;
            token = strtok (input, "_");
            first_part = token;
            token = strtok (NULL, "_");
            second_part = token;
            token = strtok (NULL, "_");
            third_part = token;
          
            snprintf (output, sizeof (output), "%s%06d%s", first_part, pos,
                  third_part);
          

          或类似的东西:

            char input[] = "this_is_name";
            char *part[3];
            char *token;
            char output[64];
            int pos = 44;
            
            token = strtok (input, "_");
            part[0] = token;
            
            int i = 1;
            while (token != NULL && i < 3) {
              token = strtok (NULL, "_");
              part[i] = token;
              i++;
            }
          
            snprintf (output, sizeof (output), "%s%06d%s", part[0], pos, part[2]);
          

          【讨论】:

            猜你喜欢
            • 2020-06-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多