【问题标题】:Pointer retaining string指针保持字符串
【发布时间】:2018-10-23 14:21:26
【问题描述】:

所以我写了一个代码,输入一个单词,把它的第一个字母放在单词的末尾(例如,“egg”将是“gge”,如果我们再次执行相同的过程,它将是“ geg”,然后最后回到“egg”) 我只想执行此过程 1 次。而我想用一个指针来记忆单词的初值,也就是egg,然后字符串要记忆“gge”。

这是代码:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    char s[100],aux,*P;
    int p=1,i,n,k,j;
    cin.get(s,100);
    i=0;
    while(i>=0)
    {
        P=s; //this is the pointer that SHOULD memorize "egg"
        aux=s[0]; 
        for(j=1; j<=n; j++) s[j-1]=s[j];
        s[n]=aux;//until here it does the letter thing
        break;
    }
     cout<<P<<endl<<s;//now here the pointer P should be "egg" and the string s should be "gge"
     //but the program prints out "gge" and "gge".

    return 0;
}

我做错了什么,我应该如何做我想做的事?

【问题讨论】:

  • 我比较容易理解。但是如果你知道如何在没有指针的情况下解决这个问题,那还是可以的。
  • 显然你更难理解,因为它是错误的;)
  • P 除了你指向的 char 之外什么都不记得。它指向s。它不保留当时的s 的值,它始终指向当前的s
  • @PaulP1 在标准库中有一个旋转算法。
  • 不要忘记将n 设置为实际值。

标签: c++ string algorithm pointers


【解决方案1】:

我做错了什么,我应该如何做我想做的事?

您似乎误解了指针是什么。 指针是一个指向别的东西的变量。在这种情况下

char s[100];
char *P = s;

P 指向s 的第一个字符元素。这与s 在许多情况下衰减到的指针相同。

您仍然只有一个数组来存储 100 个字符。该数组只有两个标识符,因为您可以通过sP 访问它。

如果您将该数组从“egg”更改为“gge”或其他任何内容,P 仍然只是指向它最初所做的相同数组。除了位置(地址)之外,它没有保存任何内容的副本,而这并没有改变。

如果我可以走两条路到你的蓝房子,而你把房子重新粉刷成绿色,那么其中一条路还不能通向原来的蓝房子。这不是道路的运作方式,房屋的运作方式或指针的运作方式。

您想在某个地方存储原始的 3 或 4 个字符,这意味着您需要另一个 char 数组,或者更好的是 std::string。这将在您更改它们之前复制您关心的字符。

最小的工作变化可能是

// P = s <-- just stores the location
P = strdup(s); // <- copies the contents

但请注意,您应该在完成后的某个时间点 free(P)。切换到std::string 确实容易得多。


使用std::string 值语义进行复制的简单示例:

#include <string>
#include <algorithm>
#include <iostream>

// source is a copy of the string passed
std::string rotate_left(std::string source, size_t offset = 1)
{
    std::rotate(source.begin(), source.begin()+offset, source.end());
    return source;
}

int main()
{
    std::string original{"eggsoup"};
    // for interactive use: getline(std::cin, original);

    std::string rotated = rotate_left(original);

    std::cout << original << '\n' << rotated << '\n';
}

【讨论】:

  • 我喜欢道路类比
  • 谢谢!我特此将其授权给任何需要解释指针并且不想用方框和箭头绘制图片的人。
  • 唉,你不能。这现在处于 Stack Exchange 设置的限制之下。
  • 好点。它在CC attribution share-alike 3.0 许可证 AFAICS 下,已经足够好了。
  • 公平地说,除非直接引用,否则我认为类比的概念本身属于合理使用范围。
【解决方案2】:

这称为旋转字符串。

尚不清楚您为什么决定为此使用指针。指针不是字符串。指针不“包含”它自己的信息*。一个指针指向一些信息。在这里,您正在创建一个指向原始字符串的指针,然后更改该字符串……但您的指针仍然只是指向相同的更改后的字符串。指针不知道字符串过去采用什么形式,只知道它在哪里

如果您想存储原始字符串的副本,则必须按字面意思执行此操作,方法是将其元素复制到第二个 char 数组中,或者切换到 std::string,因为现在是 2018 年。?

* 好吧,显然是这样;它包含它所指向的东西的地址,它本身就是“信息”。但这不是你想要的信息。

如果您真的想要使用指针,您实际上可以使用它们获得预期的结果,但不是以您期望的方式(即不是通过存储字符串的副本) .因为你知道你已经旋转了字符串 n 次,并且你知道它从哪里开始(那是P!)并且你知道它有多长(那是n,虽然你现在不是设置它,这是一个错误),您可以做一些数学运算来输出字符串的原始形式,只需以不同的顺序导航其 current 形式。

const char* startOfString = &s[0];
const size_t lengthOfString = strlen(s);
const size_t numberOfRotations = 1;

// ... do your rotation here

// Now we can still print the original form, char by char, using MATHS!
for (size_t index = 0; index < lengthOfString; index++)
{
   const size_t adjustedIndex = (index + lengthOfString - numberOfRotations) % lengthOfString;
   std::cout << startOfString[adjustedIndex];
}

(live demo)

但是,那么,你也可以一开始就以这种方式“执行”(或假装执行)实际的旋转。

或者在你得到字符串时打印它,然后再旋转它。

【讨论】:

  • 那我该如何实现呢?(第一种使用char数组的方法)
  • @PaulP1 花一些时间来试验它并做一些研究——我只是在一分钟前提出的!您的关键字肯定是“字符串”、“复制”和“C++”。
  • @PaulP1:不,它不能。再次参考我的回答,我解释说指针根本不是你对待它们的方式。
  • @PaulP1 实际上,我会添加一些注释,说明它是如何实现的,但不会像你想象的那样
  • 我是通过使用 strcpy 并将 s 复制到 P 中来实现的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-26
相关资源
最近更新 更多