“SER_”或“_”字符出现在 C 中(字符串)输出的末尾

'SER_' or '_' character appearing in end of (string)output in c

提问人:Ghimire Suraj 提问时间:1/7/2023 更新时间:1/8/2023 访问量:45

问:

我正在尝试将每个单词打印在给定句子的一行中。它工作得很好,但行尾会出现一个“_”。请帮我写它,也请适当地写它。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
    char *s,i,check=0;
    s = malloc(1024 * sizeof(char));
    scanf("%[^\n]", s);
    s = realloc(s, strlen(s) + 1);
    
    for(i=0;i<1024;i++ ||check<=2)
    {
        if(*(s+i)!=' ')
        {
            printf("%c",*(s+i));
            check=0;
        }
        else
        {
            printf("\n");
            check++;
        }
//      fflush(stdin);
    }
    return 0;
}

输出: DKF FJA FJLAK D DKF公司 FJA公司 菲拉克 d SER_

输出2: -for(i=0;我<20;我++ ||检查<=2)- 你好,我是 suraj Ghimire 你好 我 是 苏拉杰 吉

数组 C 字符串 for-loop malloc

评论


答:

1赞 Jib 1/7/2023 #1

我不确定你的代码是否像你说的那样工作..

  • 的类型不是 ,所以它应该是 int。ichar *
  • 在处理输入字符串时,不考虑 NULL 终止字符,这会导致大量垃圾打印。
  • 您不会释放分配的内存。

我建议这个稍微修改的版本:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
    char *s, *p;

    /* Allocate a new string and verify the allocation has succeeded. */
    s = malloc(1024 * sizeof(char));
    if (!s) {
        printf("malloc failed\n");
        return 1;
    }

    /* Read from user. */
    scanf("%[^\n]", s);

    /* Work on a copy of `s` (must simpler and faster than a indexed access). */
    p = s;
    while (*p) {
        if (*p != ' ') {
            printf("%c",*p);
        }else{
            printf("\n");
        }

        p++;
    }
    free(s);
    return 0;
}

输出示例:

$ ./a.out                                                                                    
abc def gh i j kmlm opqrst
abc
def
gh
i
j
kmlm
opqrst

编辑:根据 OP 的要求,有关 NULL 终止字符的更多详细信息。

按照惯例,字符串(字符数组)以特定字符结尾,我们称之为 NULL 终止字符。此字符是并标记字符串数据的末尾。0

在您的示例中,存储字符串的缓冲区在 RAM 中动态分配。如果不检查字符串的 NULL 终止字符,则会继续处理数据,就好像它是字符串的一部分一样(但事实并非如此)。

超出此字符后,您可以访问以下内存数据(这是程序RAM数据的一部分)。由于这些数据可以是任何内容(范围从 0 到 255),因此打印它们可能会导致“乱码”,因为它们可能无法打印,并且绝对与您的字符串不一致。

在“最佳”情况下,程序会因“分段错误”而停止,因为您正在访问不允许访问的内存区域。在“最坏”的情况下,你会在崩溃之前打印很多东西。

这通常称为数据泄漏(无论是 RAM 还是 ROM),因为它会暴露程序的内部数据。在您的示例的特定情况下,没有敏感数据。但!想象一下,您泄露了存储在程序中的密码或私钥。这可能是一个严重的安全问题!

1赞 Assface 1/7/2023 #2

您的代码存在几个问题。

首先,您需要检查循环是否不超过字符串的边界。for

您的循环始终设置为 因为逻辑 OR 运算符的优先级高于逗号运算符。因此,循环将始终运行,除非它停止fortrue||break

最后,在达到值 2 后,u 永远不会重置为 0。check

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    char *s,i,check=0;
    s = malloc(1024 * sizeof(char));
    scanf("%[^\n]", s);
    s = realloc(s, strlen(s) + 1);

    for(i=0; i<strlen(s); i++) {
        if(*(s+i) != ' ') {
            printf("%c",*(s+i));
            check=0;
        } else {
            printf("\n");
            check++;
            if (check > 2) break;
        }
    }
    return 0;
}

输出:

Hello, this is a test
Hello,
this  
is    
a
test

评论

0赞 Ghimire Suraj 1/8/2023
谢谢,先生,这真的很有帮助,但你能详细说明一下“你的 for 循环始终设置为 true,因为逻辑 OR 运算符 ||具有比逗号运算符更高的优先级。"
1赞 komark06 1/7/2023 #3
for(i=0;i<1024;i++ ||check<=2)

有两个问题。一个是字符串的长度并不总是 1024,因此在打印字符串之前确定字符串的长度可能会很好。另一个是 ,它必须放入 for 循环的第二部分,因此将对测试进行评估。另外,最好计算一次字符串的长度。所以我将字符串的长度存储在 .check<=2len

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *s, i, check = 0;
    s = malloc(1024 * sizeof(char));
    scanf("%[^\n]", s);
    s = realloc(s, strlen(s) + 1);
    size_t len = strlen(s);
    for (i = 0; i < len || check <= 2; i++) {
        if (*(s + i) != ' ') {
            printf("%c", *(s + i));
            check = 0;
        } else {
            printf("\n");
            check++;
        }
        //      fflush(stdin);
    }
    return 0;
}