【问题标题】:Confusing char arrays and pointers in c++在 C++ 中混淆 char 数组和指针
【发布时间】:2011-03-14 18:31:01
【问题描述】:

大家好,感谢您抽出宝贵时间解决我的问题。在这一点上,我已经看了很多材料,以至于我开始变得越来越困惑。基本上,我正在编写一段简单的代码来解析字符串。请理解我的问题不是关于解析。我在使用C++,之前从未使用过C,并且有一点c++经验(入门经验,我还是个新手)。

struct parsedString{
char chunk1[50];
char chunk2[10];
char chunk3[50];
};

main(char* bigstring)
{
    parsedString ps;
    ps = parseMe(bigString)
    cout << ps.chunk1 << endl;
    cout << ps.chunk2 << endl;
    cout << ps.chunk3 << endl;
}

parsedString parseMe(char* stringToParse)
{ 
    char* parseStr = stringToParse; 
    parsedString ps; 
    ps.chunk1 = first x chars; 
    ps.chunk2 = next y chars;
    ps.chunk3 = last z chars; 
    return ps;
}

显然这不是工作代码,我不想扔掉所有额外的东西,因为它会更难阅读,我很确定我的问题是一个新手 c/c++ 问题和一些关于内存分配的问题或类似的东西......

基本上,当 main 函数开始打印 parsedString 中的字符串时,它会准确地打印出我想要的内容,以及垃圾字符。我正在使用

输入每个数组 ps.chunk 的值

ps.chunk1[i] = *parseStr

因为 parseStr 让我得到每个单独的字符。我不知道垃圾字符来自哪里,这与我访问大字符串的方式有关吗?最初我在结构中使用 char 而不是数组,当我从 parseMe() 函数中打印时,它们会很好,但是当我从主函数访问它时它们会变成乱码。任何帮助表示赞赏,非常感谢。

如果有不清楚的地方请告诉我,我会尽力详细说明。

【问题讨论】:

  • 如果你把原始代码放上去可能更容易看出问题是什么,我目前的猜测是你正在使用的内存没有清零,尝试使用 memset 清除块您正在使用的内存,以防它是有剩余东西的回收内存。还要确保你正确使用你的指针,因为如果你没有正确检查你的边界,这可能会导致很多问题。
  • 在 C++ 中,字符串作为std::string 类型的对象进行操作。 Char 数组在 C 中用于此目的,并且使用它们(在任何一种语言中)对于初学者来说确实是一个令人困惑的话题。字符串不能使用有什么原因吗?
  • 50、10 和 50 是实际尺寸吗?或者传入字符串中是否有内部分隔符字符?请显示输入和所需输出的示例。
  • 我想我明白了,每个人似乎都在指向我使用字符串来代替:) 是否有一种相对简单的方法可以通过分隔符解析 std::string (我认为它被称为标记化?)?
  • 我听从了耶稣拉莫斯的建议,并使用 memset 将我正在使用的内存归零,这解决了我遇到的问题。将来我将使用字符串,现在我已经准备好这样做,而无需进行太多的重新设计。谢谢大家。

标签: c++ arrays string pointers


【解决方案1】:

不清楚您为什么要尝试使用 '\0' 终止 字符串,当 C++ 有一个完全可用的字符串类时,但是 假设一些教学原因:你的字符串是'\0' 终止?你如何提取并复制第一个 x 字符到 ps.chunk1?你如何确保它有一个'\0'

如果你真的想得到正好 n 个字符,你必须:

assert(strlen(parseStr) >= n);

,将它们复制到目标中(必须包含至少 n+1 个字符),

memcpy(ps.chunk1, parseStr, n);

,并添加最后的'\0':

ps.chunk1[n] = '\0';

(当然,提前parseStr:parseStr += n;

或者你可以简单地在任何地方使用 std::string,然后写 类似:

ps.chunk1(stringToParse.substr(startPosition, length));

【讨论】:

  • 哦,我明白你在说什么。我将尝试使用字符串来代替,我没有意识到将命令行输入 char* 转换为字符串是如此容易。我试试看。
【解决方案2】:

正如其他人指出的那样,您应该使用std::string 来表示字符串,并为自己省去所有麻烦。这可能如下所示:

struct parsedString{
    std::string chunk1;
    std::string chunk2;
    std::string chunk3;
};

parsedString parseMe(const std::stirng & stringToParse) {
    parsedString result;

    // just an example - this assigns the first two characters of stringToParse 
    // to chunk1
    result.chunk1 = stringToParse.substr(0, 2); 
    // get the other chunks

    return result; // return the result
}

上面的代码应该说明用法。你可以在std::stringhere找到更多信息。

【讨论】:

  • 谢谢,我会调查并回复。
【解决方案3】:

这可能有几个原因。

  • 当您声明 parsedString ps; 时,最好初始化结构并确保您接收到干净的内存块以使用。parsedString ps = {0}; 某些平台不这样做,这取决于您使用前将内存归零。

  • char* 字符串必须以 \0 字符结尾。该字符表示 char* 的结束。这是强制性的!不在字符串末尾插入它很可能会使打印操作(例如)显示超出数组限制的内容,从而为您提供垃圾字符。正如我上面建议的那样,这可以通过将所有结构归零来自动实现。

【讨论】:

    猜你喜欢
    • 2021-11-18
    • 1970-01-01
    • 2023-02-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2011-09-04
    • 2016-11-08
    • 1970-01-01
    相关资源
    最近更新 更多