【问题标题】:Can you change the size of what a pointer point to你能改变指针指向的大小吗
【发布时间】:2012-04-16 19:31:52
【问题描述】:

例如,如果一个指针指向一个字符数组,上面写着“你好,你好吗?”而您只希望指针指向 Hello。我传入一个 char 指针,当我计算它时,它会读取整个数组。我尝试使用一个 for 循环来减小大小,该循环在遇到“”时会中断。但我没有运气弄清楚。有任何想法吗?

const char *infile(char * file )
{
    cout<<file<<endl;  //this prints out the entire array
    int j;
    for(j=0;j<500; j++)
    {
        if(file[j]==' ')
           break;
    }
    strncpy(file, file,  j);
    cout<<file<<endl;  //how to get this to print out only the first word
}

【问题讨论】:

    标签: c++ pointers strncpy


    【解决方案1】:

    如果源字符串的第一个 j 字节中没有空终止符,则strncpy() 不会附加空终止符。而你的情况,没有。

    我认为您想要做的是将第一个空格手动更改为\0

    for (j = 0; j < 500; j++) {
      if (file[j] == ' ') {
        file[j] = '\0';
        break;
      }
    }
    

    【讨论】:

    • 谢谢,好简单的解决方案
    • 然后看着它在有人尝试时崩溃和燃烧:infile("This is a string");
    • @JerryCoffin 但是您的编译器至少会警告您丢失constness,不是吗? (我不提倡这种解决方案,事实上,我很想投反对票)
    • @Prætorian 输入参数必须是const。 (另一个问题是,尽管声称返回 const char*,但 OP 的代码实际上并没有返回任何内容。)
    • @JerryCoffin 你是对的。我不确定 OP 的用例是什么。
    【解决方案2】:

    首先,避免 strtok(就像瘟疫一样)。这令人不快,但有时在 C 中是合理的。不过,我还没有看到我称之为在 C++ 中使用它的理由。

    其次,处理这个问题的最简单方法(假设您使用的是 C++)可能是使用字符串流:

    void infile(char const *file) 
    {
        std::strinstream buffer(file);
        std::string word;
        buffer >> word;
        std::cout << word;
    }
    

    另一种可能性是使用 std::string 中内置的一些函数:

    void infile(char const *file) {
        std::string f(file);
        std::cout << std::string(f, 0, f.find(" "));
    }
    

    ...现在我想起来,它可能比stringstream 版本的东西简单一些。

    【讨论】:

      【解决方案3】:

      char* 指针实际上只指向一个 char 对象。如果该对象恰好是字符串的第一个(或任何)元素,您可以使用指针算法来访问该字符串的其他元素——这就是字符串(C 风格的字符串,而不是 C++ 风格的 std::string 对象) 一般都可以访问。

      (C 风格)字符串只是一个以空字符('\0')结尾的字符序列。 ('\0' 终止符之后的任何内容都不是字符串的一部分。)因此,字符串 "foo bar" 由以下字符序列组成:

      { 'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0' }
      

      如果您想将字符串从 "foo bar" 更改为 "foo",一种方法是简单地将空格字符替换为空字符:

      { 'f', 'o', 'o', '\0', ... }
      

      ... 不是语法的一部分;它表示仍然存在的字符('b''a''r''\0'),但不再是字符串的一部分。

      由于您使用的是 C++,因此使用std::string 可能会更好;它更加强大和灵活,让您不必担心终结符、内存分配和其他细节。 (当然,除非这个练习的目的是学习 C 风格的字符串是如何工作的。)

      请注意,此修改file 指向的字符串,并且该更改将对调用者可见。您可以通过制作字符串的本地副本来避免这种情况(这需要为其分配空间,然后释放该空间)。同样,std::string 让这种事情变得更容易

      最后是这样的:

      strncpy(file, file,  j);
      

      在几个层面上都很糟糕。像这样使用重叠的源和目标调用strncpy() 具有未定义的行为;从字面上看,任何事情都可能发生。而strncpy() 不一定在目的地提供适当的 NUL 终止符。从某种意义上说,strncpy() 并不是真正的字符串函数。你最好假装它不存在。

      See my rant on the topic.

      【讨论】:

        【解决方案4】:

        这样做会容易得多

         if(file[j]==' ') {
           file[j] = 0;
           break;
           ..
        
          // strncpy(file, file,  j);
        

        【讨论】:

        • 简单,但危险——例如,如果用户将字符串文字传递给函数,通常会失败。
        • 对,但在这种情况下,原始的 strncpy(file, file, j) 也失败了。一个好的编译器会发出警告。在这种情况下,最好只传递一个const char*
        【解决方案5】:

        使用strtok 可能会让您的生活更轻松。
        用 ' ' 作为分隔符拆分字符串,然后打印从 strtok 获得的第一个元素。

        【讨论】:

          【解决方案6】:

          【讨论】:

            【解决方案7】:

            如果您要问的是“我可以动态调整此指针指向的内存块的大小”那么...不是真的,不。 (您必须创建一个所需大小的新块,然后复制字节,删除第一个块等)

            如果您只想“打印第一个单词”,则将空格位置处的字符设置为 0。然后,当您输出 file* 指针时,您只会得到第一个单词(所有内容最多\0。)(阅读null terminated strings,了解更多关于为什么会这样工作的信息。)

            但这一切都取决于您正在做的事情有多少是一个示例来展示您要解决的问题。如果您真的“拆分字符串”,那么您至少要查看使用strtok

            【讨论】:

              【解决方案8】:

              为什么不一次输出每个字符,然后在点击空格时中断。

              const char *infile(char * file )
              {
                cout<<file<<endl;  //this prints out the entire array
                int j;
              
                for(j=0;j<500; j++)
                {
                  if(file[j]==' ')
                     break;
                  cout<<file[j];
                }
              
                cout<<endl;
              }
              

              【讨论】:

                【解决方案9】:

                这与指针的大小无关。 对于特定类型,指针始终具有相同的大小。

                Strtok 可能是最好的解决方案(使用 strtok 的这段代码每次遇到空格、“、”、点或“-”时都会将字符串分解为子字符串。

                char str[] ="- This, a sample string.";
                  char * pch;
                  printf ("Splitting string \"%s\" into tokens:\n",str);
                  pch = strtok (str," ,.-");
                  while (pch != NULL)
                  {
                    printf ("%s\n",pch);
                    pch = strtok (NULL, " ,.-");
                  }
                

                来源:CPP STRTOK

                【讨论】:

                  【解决方案10】:
                  std::copy(file, std::find(file, file+500, ' '),
                            std::ostream_iterator<char>(std::cout, ""));
                  

                  【讨论】:

                    【解决方案11】:

                    如果您使用 malloc 分配了 char * 指向的空间,则可以使用 realloc 更改大小。

                    char * pzFile = malloc(sizeof("Hello how are you?" + 1));
                    strcpy(pzFile, "Hello how are you?");
                    realloc(pzFile, 6);
                    pzFile[6] = '\0';
                    

                    注意,如果不设置空指针,使用字符串会出问题。

                    如果您只是想缩短字符串,您所要做的就是在位置 6 处设置空终止符。分配的空间比需要的大,但只要不短就可以。

                    我强烈建议您主要是将字符串复制到空格。

                    char * pzInput = malloc(sizeof("Hello how are you?" + 1));
                    strcpy(pzInput, "Hello how are you?");
                    char * pzBuffer = malloc(BUFFER_SIZE);
                    
                    char * pzSrc = pzInput;
                    char * pzDst = pzBuffer;
                    while (*pzSrc && ' ' != *pzSrc)
                      *(pzDst++) = *(pzSrc++);
                    *pzDst = '\0';
                    

                    这也会导致 pzSrc 指向字符串的其余部分以供以后使用!

                    【讨论】:

                      猜你喜欢
                      • 2014-07-22
                      • 2015-09-12
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-03-07
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多