为什么有些字符不能在 C++ 中编辑?

Why some character can't be edited in C++?

提问人:Lợi Nguyễn 提问时间:11/12/2023 最后编辑:MureinikLợi Nguyễn 更新时间:11/13/2023 访问量:199

问:

我正在尝试用 C++ 编写自己的函数,但它有一些问题。
我的输入是两个字符和 ,我的函数将返回一个指向与 连接的字符的字符指针。
strcatcaca

例如,
Input: Expected Output: My function's Ouput:

'abc''xyz''xyzabc''xyza@▲∩'

我的函数返回一些与我的输入不同的特殊字符。

我调试了我的函数,发现:

  • 什么时候i=0destination[3] = source[0] = 'a'
  • 但是当 ,i=1destination[8] = source[1] = 'b'
  • 而当 ,i=2destination[9] = source[2] = 'c'
  • 最后destination[10] = '\0'
#include<iostream>
#include<string.h>
using namespace std;

char* mystrcat ( char * destination, const char *source){
    for (int i=0; i<strlen(source); i++) {
        destination[strlen(destination)+i] = source[i];
    }
    destination[strlen(destination)+strlen(source)]='\0';
    return destination;
}

int main() {
    char c[100];
    cin.getline(c, 99);
    char a[100];
    cin.getline(a,99);

    mystrcat(a,c);
    cout<<a;
    return 0;
}
C++ 字符串 strcat

评论

2赞 Retired Ninja 11/12/2023
将另一个字符串附加到它之后是什么?strlen(destination)
1赞 Wyck 11/12/2023
如果您正在编写自己的 strcat 函数,它应该采用一个参数,该参数是可以存储在目标缓冲区中的最大字符数,这样您就不会溢出缓冲区。一目了然:如果是 99 个字符并且是 99 个字符,哪个字符数组有足够的空间来存储 198 个字符的结果?destinationSizeac
0赞 user12002570 11/12/2023
虽然标题可以改进。
2赞 Chris 11/12/2023
@Wyck这将是重新实现,而不是愉快地超出缓冲区。strncatstrcat
0赞 Wyck 11/12/2023
@Chris 关于 strcat 的幸福,我的实际目的是让提问者考虑他们将如何在他们的 1 辆车的车库里停放 2 辆车,打个比方。如果它被声明,我不会提到它,因为考虑到代码的其他细节,strcat 将保证有足够的空间。需要执行以下三种情况之一:要么使用 strncat,要么使目标缓冲区变大,或者将 getline 字符的总和限制为小于目标缓冲区的大小(加上 NUL)char a[200]

答:

5赞 Mureinik 11/12/2023 #1

strlen返回从指针到它遇到的第一个指针的长度。在这里,在循环期间,您将覆盖指针中的此字符,因此后续调用 将返回到内存中恰好包含此字符的某个随机点的长度。\0destinationstrlen

一个简单的解决方法是在开始修改字符串之前提取结果:strlen

char* mystrcat (char *destination, const char *source) {
    int destLen = strlen(destination);
    int srcLen = strlen(source);
    for (int i = 0; i < srcLen; i++) {
        destination[destLen + i] = source[i];
    }
    destination[destLen + srcLen] = '\0';
    return destination;
}

评论

0赞 Chris 11/12/2023
由于在第一次迭代后不再是有效的以 null 结尾的字符串,因此在后续迭代中表现出未定义的行为destinationstrlen(destination)
0赞 CGi03 11/12/2023
@Chris 但是你在循环中看到什么。strlen(destination)
1赞 Remy Lebeau 11/12/2023
@CGi03 Chris 显然指的是 OP 的代码,而不是这个答案的代码。评论应该发布在问题上,而不是在这个答案上
1赞 Chris 11/12/2023
很抱歉造成混乱。建议在答案中包含“未定义行为”一词。你的回答很好,我放弃了自己的。恭喜你打败了我!
2赞 Mark Ransom 11/12/2023
@Chris你说得很对。“未定义行为”的重要性在于,它允许比仅仅返回随机长度更大的自由度。如果幸运的话,它可能会使程序崩溃。如果你运气不好,你可能会发现恶魔从你的鼻子里飞出来
-1赞 Ashna Mittal 11/13/2023 #2

下面给出的是代码的正确实现。

#include<bits/stdc++.h>
using namespace std;
void mystrcat ( char* destination, const char *source){
    int p;
    for(p=0; destination[p] != '\0'; p++);//pointing to the index of the last 
    character of x

    for(int q=0; source[q] != '\0'; q++,p++)
    {
    destination[p]=source[q];
    }
    destination[p]='\0';
    }
int main() {
   char c[100];
   cin.getline(c, 99);
   char a[100];
   cin.getline(a,99);
   mystrcat(a,c);
   cout<<a;
   return 0;
 }

由于源代码的长度将在代码中更新,因此它会提供特殊符号作为输出。

评论

1赞 Mark Ransom 11/13/2023
“特殊符号”是未定义行为的直接结果。他们当然不能保证。
3赞 Thomas Weller 11/13/2023
stackoverflow.com/questions/1452721/......stackoverflow.com/questions/31816095/...,您应该解释您对代码进行了哪些更改以及原因