【问题标题】:Copying a part of a string (substring) in C在C中复制字符串(子字符串)的一部分
【发布时间】:2011-01-08 00:48:51
【问题描述】:

我有一个字符串:

char * someString;

如果我想要这个字符串的前五个字母并想将其设置为otherString,我该怎么做?

【问题讨论】:

  • someString 不是字符串,它是指向字符串的指针。此外,字符不一定是字母。在移动字母之前,您需要知道字符串是什么。
  • 根据您的需要,最好为其他字符串声明一个大小为 6 的 char 数组(5 + '\0' 的一个字节)。这样您就不必担心内存泄漏,以防您在使用后忘记释放 otherstring。
  • 我投票结束这个问题,因为它教会了新用户错误的提问方式,甚至应该禁用投票。

标签: c


【解决方案1】:
char* someString = "abcdedgh";
char* otherString = 0;

otherString = (char*)malloc(5+1);
memcpy(otherString,someString,5);
otherString[5] = 0;

更新
提示:理解定义的好方法称为左右规则(末尾有一些链接):

从标识符开始阅读并大声说 =>“someString is...”
现在转到 someString 的右侧(语句以分号结束,没什么好说的)。
现在走到标识符的左边(遇到*)=> 所以说“...指向...的指针”。
现在转到“*”的左侧(找到关键字char)=> 说“..char”。
完成!

所以char* someString; => “someString 是一个指向 char 的指针”。

由于指针只是指向某个内存地址,它也可以作为字符“数组”的“起点”。

这适用于任何东西..试一试:

char* s[2]; //=> s is an array of two pointers to char
char** someThing; //=> someThing is a pointer to a pointer to char.
//Note: We look in the brackets first, and then move outward
char (* s)[2]; //=> s is a pointer to an array of two char

一些链接: How to interpret complex C/C++ declarationsHow To Read C Declarations

【讨论】:

  • 我认为你应该尝试编译char *[] someThing;char []* someThing;。你分别想要char *someThing[];char (*someThing)[];。这会破坏你的算法来理解定义。
  • //谢谢,你说的语法错误是对的。修复了代码。但是,该算法仍然有效,请参阅更新。
  • 别忘了在 malloc 之后释放
【解决方案2】:
#include <string.h>
...
char otherString[6]; // note 6, not 5, there's one there for the null terminator
...
strncpy(otherString, someString, 5);
otherString[5] = '\0'; // place the null terminator

【讨论】:

  • 或者otherString[5] = (char)0;如果你想挑剔的话。 Char 是一个整数类型,所以编译器不会(或不应该)抱怨只为它分配一个原始整数。
  • 感谢您提醒我将终止字符放在双引号的单引号中。
  • @pib 不清楚comment。在 C 中,otherString[5] = '\0';otherString[5] = 0; 都将值为 0 的 int 分配给 char。那么(char)otherString[5] = (char)0; 有何帮助?
【解决方案3】:
strncpy(otherString, someString, 5);

别忘了为 otherString 分配内存。

【讨论】:

  • 请注意,这可能会导致未终止的字符串(如果 someString 包含五个或更多字符)。
【解决方案4】:

您需要为新字符串 otherString 分配内存。一般来说,对于长度为 n 的子字符串,这样的事情可能对你有用(不要忘记做边界检查......)

char *subString(char *someString, int n) 
{
   char *new = malloc(sizeof(char)*n+1);
   strncpy(new, someString, n);
   new[n] = '\0';
   return new;
}

这将返回 someString 的前 n 个字符的子字符串。确保在使用 free() 完成后释放内存。

【讨论】:

  • 请检查malloc返回值
  • ...或者全新的东西...char *new=new char[n+1] :-)
  • sizeof(char)*n+1 在概念上是错误的。可以使用sizeof(char)*(n+1) 或简单地将n + 1 用作sizeof(char)==1
【解决方案5】:
#include <stdio.h>
#include <string.h>

int main ()
{
        char someString[]="abcdedgh";
        char otherString[]="00000";
        memcpy (otherString, someString, 5);
        printf ("someString: %s\notherString: %s\n", someString, otherString);
        return 0;
}

如果您不使用 printf 语句并将常量放入所有程序中,那么您将不需要 stdio.h,但最小的程序是不好的形式,应该避免。

【讨论】:

  • 还需要设置 otherString[5] = '\0'
  • memcpy 之后的其他字符串不是有效的 C 字符串,因为它不是以 null 结尾的。在 memcpy 之后你需要添加 otherstring[5] = '\0';
  • 或者你可以 memset(otherstring,'\0',sizeof(otherstring));在使用它之前。
  • 确实如此,这说明了一个好问题。代码灵活性不应以牺牲简单性为代价。它可以像 char otherString[]="00000"; 一样简单。因此空终止字符不是问题。使用 '0' 而不是 '\0' 是我首先做出反应的原因,然后我自己去忘记了......
【解决方案6】:

广义的:

char* subString (const char* input, int offset, int len, char* dest)
{
  int input_len = strlen (input);

  if (offset + len > input_len)
  {
     return NULL;
  }

  strncpy (dest, input + offset, len);
  return dest;
}

char dest[80];
const char* source = "hello world";

if (subString (source, 0, 5, dest))
{
  printf ("%s\n", dest);
}

【讨论】:

  • 在dest[len+1] no处加'\0'会更好?
  • 这里有一个微妙的错误;您需要将 if(offset + len) 更改为 if(offset) 否则将永远不会读取字符串的最后一个字符;例如:cpp.sh/955ib
【解决方案7】:

一举两得:

char *otherString = strncpy((char*)malloc(6), someString);
otherString[5] = 0;

【讨论】:

  • @pm100 我碰巧同意,但没有其他人同意,所以我认为这是暗示的。
【解决方案8】:
char largeSrt[] = "123456789-123";  // original string

char * substr;
substr = strchr(largeSrt, '-');     // we save the new string "-123"
int substringLength = strlen(largeSrt) - strlen(substr); // 13-4=9 (bigger string size) - (new string size) 

char *newStr = malloc(sizeof(char) * substringLength + 1);// keep memory free to new string
strcpy(newStr, largeSrt, substringLength);  // copy only 9 characters 
newStr[substringLength] = '\0'; // close the new string with final character

printf("newStr=%s\n", newStr);

free(newStr);   // you free the memory 

【讨论】:

  • 用strncpy替换strcpy,否则会出现参数过多的错误。
【解决方案9】:

我认为这很简单……但我不知道如何直接传递结果变量,然后创建一个本地 char 数组作为 temp 并返回它。

char* substr(char *buff, uint8_t start,uint8_t len, char* substr)
{
    strncpy(substr, buff+start, len);
    substr[len] = 0;
    return substr;
}

【讨论】:

    【解决方案10】:

    您可以使用 snprintf 精确获取 char 数组的子字符串。这是一个名为“substring.c”的文件示例:

    #include <stdio.h>
    
    int main()
    {
        const char source[] = "This is a string array";
        char dest[17];
    
        // get first 16 characters using precision
        snprintf(dest, sizeof(dest), "%.16s", source);
    
        // print substring
        puts(dest);
    } // end main
    

    输出:

    这是一个字符串

    注意:

    有关详细信息,请参阅 printf 手册页。

    【讨论】:

    • 不知道这样做的成本是多少,但实际上只使用一个标准的 Lib 来执行此操作,这有点了不起
    【解决方案11】:

    此代码是 substr 函数,它模仿其他语言中存在的同名函数,只需解析:字符串、开头和字符数,例如:

    #include <stdio.h>
    
    printf( "SUBSTR: %s", substr("HELLO WORLD!",2,5) );
    

    上面将打印 HELLO。如果你在字符串长度上传递一个值,它会被忽略,因为循环只会迭代字符串的长度。

    #include <stdlib.h>
    
    char *substr(char *s, int a, int b) {
        char *r = (char*)malloc(b);
        strcpy(r, "");
        int m=0, n=0;
        while(s[n]!='\0')
        {
            if ( n>=a && m<b ){
                r[m] = s[n];
                m++;
            }   
            n++;
        }
        r[m]='\0';
        return r;
    }
    

    【讨论】:

    • 有一些惯用的方法可以完成同样的任务。我可以明确地说,每个人都应该学习在 C 中执行此操作的方法,而不是使用 stackoverflow 中类似于他们其他语言使用的随机函数。
    【解决方案12】:

    您可以将 C 字符串视为指针。所以当你声明:

    char str[10];
    

    str 可以用作指针。因此,如果您只想复制字符串的一部分,您可以使用:

    char str1[24] = "This is a simple string.";
    char str2[6];
    strncpy(str1 + 10, str2,6);
    

    这会将 str1 数组中的 6 个字符复制到 str2 中,从第 11 个元素开始。

    【讨论】:

    • 还是需要加上空终止符吧?
    • 你可以,但如果你确切地知道你想用这种方式复制哪些字节是有效的。它不是动态的,但它可以工作。
    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 2018-05-23
    • 2014-05-26
    • 2012-08-16
    • 2015-02-02
    • 2019-03-01
    • 1970-01-01
    • 2017-01-11
    相关资源
    最近更新 更多