【问题标题】:How to add string elements successively in C?如何在C中连续添加字符串元素?
【发布时间】:2017-12-18 21:33:41
【问题描述】:

我想连续添加字符串元素,例如st[]="morty",我想重复它的元素例如七次。应该是st[]="mortymo"。我写了一个函数,它在下面。 (长度函数为strlen)。

    void repeat(char* st,int n){
         int i,k=0,l=length(st);
         char* ptr;
         ptr=(char*)malloc((n+1)*sizeof(char));
         for (i=0;i<n;i++){
              *(ptr+i)=*(st+k);
              k++;
              if(k==l)k=0;
         }
    }

【问题讨论】:

  • 您分配内存并将其地址存储在ptr 中,但随后您在函数结束时丢弃了ptr。这不仅会泄漏内存,还会丢弃您的操作结果。你不应该返回ptr吗?
  • 你也想用空终止你分配的字符串。
  • 它现在做什么与它应该做什么?
  • @Zusaetlich "...例如 st[]="morty",我想重复它的元素,例如七次。它应该是 st[]="mortymo"。" - 哪些元素重复了 7 次?

标签: c string function repeat


【解决方案1】:

下面的程序重复原始字符串中的字符。 代码中的注释:

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

 char* repeat(const char* st, size_t n){
         // use `const` to note that pointer `st` will not be modified
         // for purity you may want to use type `size_t` since returning type of strlen is `size_t` 

         size_t i, k=0;
         size_t l = strlen(st);

         // do not use (char *) cast
         char* ptr = malloc((n+1)*sizeof(char)); // allocate enough room for characters + NULL

         for (i=0; i< n; i++)
         {
              ptr[i] = st[k]; // use index for readability
              k++;

            if (k == l)
                k=0;
         }

         ptr[i] = 0; // terminate the string


    return ptr;
 }

int main( )
{
    char *str = "12345";

    str = repeat(str, 15);

    printf("%s\n",str);

    free (str); // free the allocated memory inside the repeat function

    return 0;
}

输出:

123451234512345 

【讨论】:

    【解决方案2】:

    在您的repeat 函数中,您分配了ptr 来保存重复的字符串,但您没有返回或将其分配给st。你可以修改你的repeat函数如下:

        char* repeat(char* st,int n){
             int i,k=0,l=strlen(st);
             char* ptr;
             ptr=(char*)malloc((n+1)*sizeof(char));
             for (i=0;i<n;i++){
                  *(ptr+i)=*(st+k);
                  k++;
                  if(k==l)k=0;
             }
            *(ptr+n) = '\0';
            return ptr;
        }
    
        /* some code*/
        char *st = "morty";
        st = repeat(st, 7);
    

    这样你将重复字符串的结果存储在st之后。

    【讨论】:

    • 你从未添加尾随的空值。
    【解决方案3】:

    如果我正确理解了分配,那么您需要一个类似于演示程序中所示的函数。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    char * repeat( const char *s, size_t n )
    {
        char *p = NULL;
    
        size_t len = strlen( s );
    
        if ( len == 0 ) n = 0;
    
        p = ( char * )malloc( n + 1 );
    
        if ( p )
        {
            size_t i = 0;
    
            for ( size_t j = 0; i < n; i++ )
            {
                p[i] = s[j];
                if ( ++j == len ) j = 0;
            }
    
            p[i] = '\0';
        }
    
    
        return p;
    }
    
    int main(void) 
    {
        char *s = "Hi, Zusaetlich.";
    
        char *p = repeat( s, 2 * strlen( s ) );
    
        puts( p );
    
        free( p );
    
        return 0;
    }
    

    程序输出是

    Hi, Zusaetlich.Hi, Zusaetlich.
    

    注意这个函数是这样设计的,如果原始字符串是空的,那么结果字符串也是空的,因为没有什么可重复的。

    至于你的函数,它至少有内存泄漏,因为函数中分配的内存没有被释放。

    由于原始字符串未更改,因此相应的参数应使用const 说明符进行限定。第二个参数的类型应该是size_t,因为至少函数strlen的返回类型是size_t

    所以函数应该像演示程序中所示那样声明。

    【讨论】:

    • 不要只是发布代码,解释他的版本有什么问题以及你是如何修复它的。
    【解决方案4】:

    由于您不打算修改st 的内容,请继续将其声明为const。由于您打算在函数中分配一个新字符串,因此应将其返回给调用者。

    char *repeat(const char* st,int n){
    

    k 对您的问题来说是不必要的。调用标准函数。

         int i,l=strlen(st);
         char* ptr;
    

    不要转换 malloc 的结果,因为这会掩盖 C 中的致命错误。sizeof(char) 始终为 1。检查 malloc 调用的结果是否成功。

         ptr=malloc(n+1);
         if (ptr == NULL) return NULL;
    
         for (i=0;i<n;i++){
    

    惯用地使用[] 访问数组。请注意,每当i 执行时,k 都会递增,但您正在应用 k 的模运算。但是,C 有一个模运算符,您可以直接在 i 上使用它。

              ptr[i]=st[i%l];
         }
    

    确保新字符串以NUL 终止。你的函数被声明为返回一个结果,但你的实现没有这样做。

         ptr[n] = '\0';
         return ptr;
    }
    

    C 有很多你可以调用的函数来为你进行复制,而不是你编写的逐字节循环。您的实现很简单,但下面是另一种选择,它还包括您的解决方案中缺少的额外错误检查。

    (有些人可能会拒绝使用sprintf,但它被正确使用了。)

    char *
    repeat (const char *st, int n) {
        int l = st ? strlen(st) : 0;
        char *ret = (st && n > 0 ? malloc(n+1) : 0), *p = ret;
        while (ret && n > 0) {
            p += sprintf(p, "%.*s", (l < n ? l : n), st);
            n -= l;
        }
        return ret ? ret : "(nil)";
    }
    

    Try it online!

    【讨论】:

    • 我不清楚 OP 请求的 POV 的答案有什么问题,但我已经加强了错误检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2011-02-23
    • 2020-03-08
    相关资源
    最近更新 更多