在C中使用strcat向字符串追加字符

Appending character to a string in C with strcat

本文关键字:字符串 追加 字符 strcat      更新时间:2023-10-16

大家好,我仍然对指针感到困惑,我想知道是否有办法在不使用sprintf的情况下完成以下操作:

char a[100], b[100], c[2];
//Some code that puts a string into a 
for(i = 0; i<strlen(a); i++)
{
    if(a[i] == 'C')
        strcat(b, "b");
    else if(a[i] == 'O')
        strcat(b, "a");
    else if(a[i] == 'D')
        strcat(b, "1");
    else
    {
        sprintf(c, "%s", a[i]);
        strcat(b, c);
    }
}

基本上是一个for循环,循环遍历字符串(数组),并根据字符是什么在另一个字符串中填充一个字符(或字符串),如果字符不是C, O或D,它只是将其添加到另一个字符串中。

  • 我似乎不能只做strcat(b, a[i]);,我知道它不会工作,因为它会尝试strcat(char *, char)而不是char*, const char*)
    我能把它变成一个指针吗?

  • 他们仍然让我很困惑,我对编程一般只是低级语言的新手…
  • 初始化char[] s的最佳方法是什么?将被字符串填充,我现在用的是:

    char ie[30] = ""
    
  • 也让我知道如果有什么更简单的方法来做

我想和抱歉,如果它是不清楚的,这显然是一个一次性的脚本,但在我的脚本中使用相同的概念。

提前感谢stackoverflow:X

(1)您的代码中可能存在一个bug:

你在评论一些代码将字符串放入,我认为你没有将任何字符串分配给b。所以默认情况下char b[100];有垃圾值(b中可能没有)。但是字符串连接函数要求b必须是字符串。所以

strcat(b, "b");   <--will Undefined Behavior 

(2)一种初始化空字符串的技术:

是的,你应该总是用默认值初始化你的变量(数组),如:

char a[100] = {0}, b[100] = {0}, c[2] = {0};

注意:半初始化数组的剩余元素将是0 (null),初始化变量假设是良好的实践

(3) Yes strcat(b, a[i]); is wrong:

a[i]中的字符串连接到b中,您可以这样做:

strcat(b, a + i);

是的,你是正确的strcat(b, a[i]);确实是无效的。

注意:a[i](a + i)不一样,a[i]是char类型,(a + i)是string类型,是a类型。

假设您有以下字符串数组a, i的值为2,则:

+----+----+----+---+---+----+----+----+---+
| 'u'| 's' |'e'|'r'|'5'| '6'| '7'|'8' | 0 |  
+----+----+----+---+---+----+----+----+---+
 201   202  203 204 205 206  207   208 209 210  211
  ^          ^  
  |          |
  a         (a+i) 
所以在上图中,a的值是201,类型是char [100](假设数组的大小是100)(a + i)也指向'e'地址 203的字符串。其中为a[i] = 'e'

所以你不能做strcat(b, a[i]);,但strcat(b, a + i);是有效的语法。

另外,从@BenVoigt到从ai的位置concat n字符,您可以这样做:

strncat(b, a+i, n);

its将n字符从a+i追加到b

既然你想取a的子字符串正好一个字符长:

strncat(b, a+i, 1);

初始化所有char数组为null,使代码中不存在垃圾值。

你正在添加一个垃圾字符数组。

char a[100]={0}, b[100]={0}, c[2]={0};

现在strcat()函数行为正常

您似乎对字符串感到困惑。字符串不仅仅是一个数组。你在读哪本书?

当你第一次调用strcatb进行操作时,b不能保证是字符串。结果是未定义的行为。这段代码在您的系统上似乎可以正常运行,但如果确实如此,那只是巧合。我在其他系统上看到过类似的代码以奇怪的方式失败。像这样修复:

char a[100], b[100];
//Some code that puts a string into a
a[x] = ''; // <--- Null terminator is required for a to contain a "string".
             //      Otherwise, you can't pass a to strlen.
for(i = 0; i<strlen(a); i++)
{
    if(a[i] == 'C')
        b[i] = 'b';
    else if(a[i] == 'O')
        b[i] = 'a';
    else if(a[i] == 'D')
        b[i] = '1';
    else
        b[i] = a[i];
}
b[i] = ''; // If you don't put a null character at the end, it isn't a string.

现在,什么是字符串?

有很多可能的方法来实现您的愿望。有一些方法可以避免同时使用strcat()sprintf()——见下文;你可以在继续使用strcat()的同时避免使用sprintf()

我可能这样做的方式是记录下一个字符要添加到目标字符串b的位置。这将更有效,因为重复使用strcat()涉及二次行为,因为您每次构建一个字符串。此外,出于同样的原因,通常最好避免在循环条件中使用strlen();它(可能)在每次迭代中求值,因此它也导致二次行为。

char a[100], b[100];
char *bp = b;
//Some code that puts a string into a 
size_t len = strlen(a);
for (int i = 0; i < len; i++, bp++)
{
    if (a[i] == 'C')
        *bp = 'b';
    else if(a[i] == 'O')
        *bp = 'a';
    else if(a[i] == 'D')
        *bp = '1';
    else
        *bp = a[i];
}
*bp = '';   // Null-terminate the string

您也可以通过使用索引变量i来分配给b而不使用指针(只要您为每个输入字符只添加一个字符到输出):

char a[100], b[100];
//Some code that puts a string into a 
size_t len = strlen(a);
for (int i = 0; i < len; i++)
{
    if (a[i] == 'C')
        b[i] = 'b';
    else if(a[i] == 'O')
        b[i] = 'a';
    else if(a[i] == 'D')
        b[i] = '1';
    else
        b[i] = a[i];
}
b[i] = '';   // Null-terminate the string

只要a中的字符串足够短,所显示的代码(无论是哪个版本)都不会溢出b。如果您有时在b中添加了几个字符,您可能需要索引(ij),或者您可以在每个循环中增加第一个版本中的指针bp多次,并且您需要确保不会溢出b的边界。