【问题标题】:C program outputs weird charactersC程序输出奇怪的字符
【发布时间】:2021-07-13 13:20:02
【问题描述】:

尝试在 C 中打印反向输入:

#include <stdio.h>

#define MAX_SIZE 100
/* Reverses input */
void reverse(char string[], char reversed[]);

int main() {
    char input[MAX_SIZE], output[MAX_SIZE + 1];
    char c;
    int index = 0;

    while ((c = getchar()) != '\n')
    {
        input[index] = c;
        ++index;
    }

    reverse(input, output);
    printf("%s\n", output);

}

void reverse(char string[], char reversed[]) {  
    int rev;
    rev = 0;

    for (int str = MAX_SIZE - 1; str >= 0; --str) {
        if (string[str] != '\0') {
            reversed[rev] = string[str];
            ++rev;
        }
    }
}

但是有这个奇怪的结果:

输入:

abc

输出:

?:? ????:???:?cba?

输入和输出数组都包含\0,所以我猜有一些索引越界异常,但我无法找到确切的位置。谢谢。

【问题讨论】:

  • 您需要将index 传递给reverse,这样您才能使用实际大小而不是MAX_SIZE。
  • 在尝试反转字符串之前,您知道字符串的大小。为什么不在反向函数中使用它(void reverse(char string[], char reversed[], size_t len))?您正在反转 MAX_SIZE 字符,其中只有 index 字符需要反转。
  • 另外,显示的代码不能保证任何数组都包含'\0'
  • @500-InternalServerError 谢谢,现在可以工作了,但我仍然不明白为什么我会在输出中得到这些随机字符。
  • @pmg 也谢谢你,是的,你是对的 \0。我忘记了垃圾值

标签: c reverse c-strings function-definition


【解决方案1】:

对于原始字符串的长度,您不应该使用MAX_SIZE,因为这是容器的总​​大小,而不是字符串的大小。

另一个问题是输入字符串不是以 null 结尾的,因此无法知道它的长度,除非您跟踪从 stdin 读取的字符数并将其作为参数传递。

修复这两个主要问题(以及其他一些小问题 (cmets))将使您的代码正常工作:

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

#define MAX_SIZE 100

void reverse(const char string[], char reversed[]);
int main()
{
    char input[MAX_SIZE], output[MAX_SIZE]; // no need for the extra character
    char c;
    int index = 0;

    while ((c = getchar()) != '\n' && index < MAX_SIZE - 1) // avoid buffer overflow
    {
        input[index] = c;
        ++index;
    }
    input[index] = '\0'; // null terminate the original string

    reverse(input, output);
    printf("%s\n", output);
}
void reverse(const char string[], char reversed[])
{
    int rev;
    rev = 0;

    // stop condition with the length of the string
    for (int str = strlen(string) - 1; str >= 0; --str)
    {
        reversed[rev] = string[str];
        ++rev;
    }
    reversed[rev] = '\0'; // null terminate the reversed string
}

【讨论】:

  • 是否像 *string 和 *reversed 一样反转 [] 和 string[]?值是如何传回 main 的?
  • @EMS,是的,arguments like char string[] decay to char *string,因此作为指针,更改是永久性的,并且可以在函数外部访问。
  • 我在 string[] 中被教导 'string' 是一个指向字符数组的常量指针。那不是意味着字符串是一个常量地址吗?并且应该不可能向它传递另一个地址?
  • @EMS 如果数组是用[] 初始化的 ie char string[] = "some string" 数组将包含字符串文字的副本,因此它可以更改,但是如果将其初始化为指针 ie char *string = "some string" ,则它是指向字符串文字的指针,并且尝试更改它是未定义的行为。
  • 这就是我想知道的。谢谢:-)
【解决方案2】:

对于初学者来说,不清楚为什么数组 inputMAX_SZIE 元素

char input[MAX_SIZE], output[MAX_SIZE + 1];

而数组outputMAX_SIZE + 1 元素。

在这个循环之后(那是不安全的)

while ((c = getchar()) != '\n')
{
    input[index] = c;
    ++index;
}

数组input 不包含字符串。

函数revrese内这个循环中变量str的初始值

for (int str = MAX_SIZE - 1; str >= 0; --str) {

没有意义,因为用户可以在数组中输入少于MAX_SIZE - 1 个字符。

整个程序和函数reverse可以如下面的演示程序所示。

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

#define MAX_SIZE 100

char * reverse( const char src[], char dsn[] )
{
    char *p = dsn + strlen( src );

    *p = '\0';

    while (p != dsn) *--p = *src++;

    return dsn;
}

int main( void )
{
    char input[MAX_SIZE], output[MAX_SIZE];

    size_t i = 0;

    for (int c; i + 1 < MAX_SIZE && ( c = getchar() ) != EOF && c != '\n'; ++i)
    {
        input[i] = c;
    }

    input[i] = '\0';

    puts( reverse( input, output ) );
}

如果要输入例如文本

Hello World!

那么输出将是

!dlroW olleH

注意第一个函数参数应该有限定符const,因为传递的源字符串在函数内没有被改变。该函数应遵循标准字符串函数的通用约定,并返回一个指向目标字符串的指针。那就是函数返回类型void没有多大意义。

当你处理字符串时,使用无符号类型 size_t 的对象而不是有符号类型 int 作为索引。 size_t类型是函数strlen或运算符sizeof的返回值类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 2020-05-14
    • 2015-09-27
    • 1970-01-01
    相关资源
    最近更新 更多