【问题标题】:C++ error trying to 'rewrite' char array尝试“重写”字符数组的 C++ 错误
【发布时间】:2012-05-24 02:45:12
【问题描述】:

我正在尝试使用代码将字符串转换为全部大写:

int client::get_upper(char*item_in)
{
    int k ;
    char * temp_str;
    int length = strlen(item_in);
    temp_str = new char [length+1];
    for(k = 0; k < length; ++k)
        temp_str[k] = toupper(item_in[k]);
    temp_str[k] = '\0';
    for(k = 0; k < length; ++k)
        item_in[k] = temp_str[k];
    return 0;
}

然而,当我尝试这样做时,我收到来自 Visual Studio 的访问冲突写入位置 xxxxxxxx。这是一个类,所以我被限制使用实际的字符串。

【问题讨论】:

  • 告诉我们你是如何调用这个函数的。
  • 为什么要分配第二个字符数组,而不是直接将大写字母写入原始数组? (顺便说一句,您正在泄漏内存,因为您从未在函数末尾执行 delete [] temp_str)
  • 主救我们脱离“C 班”老师!
  • @JerryCoffin 确实,但在我看来,他们会留下来(从我国的学校系统来看)。唯一的办法就是让主用火杀死他们。或者至少,将他们介绍给 C++、随附的标准库以及他们称之为字符串类的东西。
  • @DomagojPandža:我什至可以理解想要教授低级编程,但如果这是您的意图,请从 实现 (最小)字符串类开始,然后使用它(或扩展它)用于以后的课程。

标签: c++ string pointers toupper


【解决方案1】:

如果使用得当,你的代码可以工作(最简单的方法是像这样简单地传递一个本地 cstring):

char test[] = "stackoverflow.com";
client::get_upper(test); // client interpreted as a namespace

现在,您的函数充满了不好的方法,即未管理的冗余副本(内存泄漏)。

改写了一下:

int client::get_upper(char *item_in)
{
    unsigned int length = strlen(item_in);
    for(int i = 0; i < length; ++k)
        item_in[i] = toupper(item_in[i]);

    return 0;
}

如果你想尝试一下,这里给你一些东西,只是为了好玩:

int client::get_upper(char *item_in)
{
    int length = strlen(item_in);
    for(int i = 0; i < length; ++i)
        if((item_in[i] >= 97 && item_in[i] <= 122))
            item_in[i] = (int)item_in[i] - 32; 

    return 0;
}

您的错误很可能来自您试图推送一个您可能没有真正考虑过的动态字符数组。只需使用本地字符串,即简单的以空字符结尾的数组。你并没有真正付出太多,所以这只是猜测工作。我能做的就是帮你简化你的表达方式。由于返回值什么都不做,请考虑将其应用于某事或切换到void

希望对你有帮助。

【讨论】:

  • 无论出于何种原因,我只是假设 x = toupper(x) 不起作用,可能肯定是我对这样做时实际发生的情况缺乏了解。
  • 现在效果很好,从工作室切换到好的旧记事本和 g++,这本身就解决了很多问题。我敢肯定很多代码都是废话,但是我们似乎在这门课上没有学到很多关于语言的知识……这个函数只是用来接受用户输入并生成正确的哈希键,我想统一的情况是最简单的。
  • 而 int return 只是为了养成良好的习惯而推荐的,这样我们就可以利用函数退出的方式/位置......我猜?
  • @user1404053 通常在这种情况下返回一个整数值仅用于验证事情是否按计划进行。您可以将 1 定义为成功,将 0 定义为失败。可能有更复杂的用例,这取决于您的项目。
  • 是的,导师只是让我们养成使用 int 而不是 void 的习惯。 99% 的时间它只不过是一个我什至没有实现的成功/失败标志。但是,它经常可以告诉客户端哪个表是空的,或者找到了多少项并插入到客户端列表中。我确信有无数其他方法可以做我们用 C/C++ 做的事情,但我觉得目标是让我们采取尽可能多的步骤。
【解决方案2】:

假设您正确调用了该代码,我认为您的 temp_str[k] = '\0'; 存在一个错误的错误;

【讨论】:

  • K等于kength,他分配了length + 1,所以没关系
  • 嗯,还是没意义,因为他把它全部复制回原来的数组中,不是/错/,而是很诡异,还是一样的。
【解决方案3】:

在调用 get_upper 时,是否传递了字符串文字?例如,您的调用代码是这样的吗:

char *mystr = "stackoverflow.com";
client.get_upper(mystr)?

这很可能会在 Visual Studio 中触发访问冲突。

如果是这种情况,可以将mystr的定义改为:

char mystr[] = "stackoverflow.com";

【讨论】:

【解决方案4】:

如果不查看函数是如何被调用的,我们就无法判断为什么会出现错误。

我怀疑错误与调用上下文以及 item_in 实际指向的内容有关。

Jeremy Friesner 的 cmets 恰到好处 - 您有泄漏,如果目标是破坏性的,则无论如何都不需要中间缓冲区。

【讨论】:

    【解决方案5】:

    您不能使用标准字符串类这一事实并不意味着您必须将其编写为一个整体函数。

    我会编写一个简单的函数来就地进行转换。然后,如果您需要支持处理只读字符串,请编写另一个复制输入的函数(使用第三个函数),然后对副本进行就地转换。

    char *duplicate(char const *input);
    
    char *upper_str(char *input); // does in-place transformation
    
    char *upper_str(char const *input); // duplicates, then transforms the duplicate
    

    【讨论】:

      猜你喜欢
      • 2019-09-21
      • 1970-01-01
      • 2016-12-05
      • 2013-05-31
      • 1970-01-01
      • 2018-09-03
      • 2018-08-21
      • 2017-09-17
      • 1970-01-01
      相关资源
      最近更新 更多