【问题标题】:Some problem using pointers to enter a string使用指针输入字符串的一些问题
【发布时间】:2010-02-17 00:35:18
【问题描述】:

我是初学者,我需要问一个问题.. 我写了这个小代码,它接受来自用户的字符串并打印出来……非常简单。

#include <iostream>

using namespace std;

int main()
{
   int i;
   char *p = new char[1];

   for(i = 0 ; *(p+i) ; i++) 
     *(p+i) = getchar();

   *(p+i) = 0;

   for(i = 0 ; *(p+i) ; i++) 
     putchar(*(p+i));

   return 0;
}

当我输入任何字符串时......例如“堆栈溢出”......它将打印“sta”并删除字符串的其余部分。我知道这很容易解决,但是由于我刚刚开始,所以我不明白这里出了什么问题。提前致谢。

【问题讨论】:

  • 为什么是*(p+i) 而不是p[i]?当然还有其他问题。

标签: c++ string pointers


【解决方案1】:

这段代码有几个问题。首先,你有一个缓冲区溢出,因为char *p = new char[1] 只分配一个字符用于存储。当i &gt; 0 时超出此值。接下来,您的第一个循环将继续进行,直到它到达 unallocated 内存中的某个点(未定义的行为),该点的值为零。在您的情况下,这恰好发生在第三个值之后。您可能想要更像*(p+i-1) == 0 的东西来给出“读取的最后一个字符满足某些条件”。最后,您使用new[] 分配内存,而没有使用匹配的delete[] 正确释放内存。

考虑使用std::cinstd::string 以获得更安全和正确的代码:

#include <iostream>
#include <string>

int main(int, char**) {
   std::string s;

   std::cout << "Enter a string: ";
   std::cin >> s;

   std::cout << s << std::endl;
}

【讨论】:

  • 如果这是家庭作业,他的任务可能是不使用coutcin
【解决方案2】:

这里有一些似乎可以工作的代码。我确信有更好的(和更多的 C++-ish)方法来做到这一点......

#include <iostream>
using namespace std;

#define MAXLEN 80

int main()
{
    int i=0;
    char c;

    char *p = new char[MAXLEN + 1];  // 1 char will not be sufficient

    do  // Doing this with a for loop would be unreadable
    {
         c = getchar();
         *(p+i) = c;
         i++;
    } while( c != '\n' && i < MAXLEN ); // Check for a newline. How do you enter the zero with a keyboard?
    *(p+i) = 0; // Ensure that the last character is zero

    for(i = 0 ; *(p+i) ; i++) putchar(*(p+i));  // This is OK but difficult to read

    delete [] p;  // Don't forget this

    return 0;
 }

【讨论】:

  • ...更好的方法,就像在赛斯约翰逊的回答中一样。你应该接受它而不是这个。
  • 完成...好吧,如果可以的话,我本可以接受您的两个答案。你们俩的信息量都绰绰有余。但由于我还没有了解 std::string 我不能很好地判断。
【解决方案3】:

你的程序做任何事情都是运气。是什么阻止了*(p+i) 从成为\0 开始?奇怪的是,您也在 C++ 程序中使用了 getchar()putchar()。这个计划背后的故事是什么?

【讨论】:

  • 我不能称它为“程序”.. 你可以说这是我写的一段代码来弄清楚动态内存分配是如何工作的。
  • 好吧,在那种情况下,正如其他人提到的那样,您没有分配足够的空间,完成后也没有释放它。
【解决方案4】:

如果你读入内存,请确保你分配了足够的内存。 new char[1] 创建一个仅包含一个字符的数组,但您阅读的内容远不止这些。一个简单的临时解决办法是简单地分配更多,比如new char[255]

其他说明:

  • 你永远不会删除你分配的内存:delete[] p;
  • 您应该检查您读取的字符是否与缓冲区可以容纳的字符一样多:for(..;.. &amp;&amp; i&lt;bufferSize;..)
  • 第一个循环中的条件始终检查下一个字符,而不是您刚刚读取的内容
  • *(p+i)等价于p[i],可读性更强
  • 为什么一次只能读写一个字符?
  • 为什么不使用iostreamsstd::instd::out)和std::string,因为您正在使用C++?

【讨论】:

  • 如果p被分配为一个数组,它必须是delete[] p
【解决方案5】:

您只为一个字符分配空间,但您尝试在其中放置许多字符。

这是作业吗?如果是这样,请将其标记为这样。你可以使用 STL 吗?

如果是这样,则在 new char[1] 上使用 std::vector;

编辑:无需任何繁琐的位或 STL 即可完成

  const int MAX = 100;
  char *p=new char[MAX];
  for(i = 0 ; *(p+i) && i < MAX ; i++) 
      *(p+i) = getchar();

可能有一些 - 留作练习

【讨论】:

  • 嗯,我刚开始,所以我什至没有接触 STL 或向量或 std::string。我试图让这段代码使用我所知道的。
  • 立即学习 std::string 和 STL。当你表面上试图学习 C++ 时,没有理由强迫自己用 C 编程。
  • 是和不,你必须使用 STL 和字符串。同时,要成为一名优秀的 C++ 程序员,您需要了解堆、指针等。这取决于您在写什么以及为什么写。您确实需要了解为什么此代码会爆炸,修复它然后丢弃它并使用 stl/string 重做
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多