C语言 大小为 10 的字符数组在使用 %s 打印时显示 11 个字符



我试图解开这段代码中的谜团,但徒劳无功。以下程序用于打印输入中的长度和行。它的 MAX 限制为 10 个字符,对于超过 10 个字符的行,它会计算所有字符,但仅存储 10 个字符。

让我感到困惑的是,在输出中,当一行超过 10 个字符的行作为输入时,当我将行存储在 10 个字符大小的数组中时,它会打印输入的前 11 个字符。怎么可能?

我在Linux Mint中使用GCC编译器。

#include<stdio.h>
#define MAX 10
int Getline(char arr[], int lim);
void main(){
    int len=0;
    char c=0;
    char line[MAX]={};
    len=Getline(line,MAX);
    printf("%dn%s",len,line);
    printf("nDo you want to continue?t");
    while((c=getchar())=='y'){
        len=Getline(line,MAX);
        printf("n%dn%s",len,line);
        printf("nDo you want to continue?t");
    }
}
int Getline(char line[], int lim){
    int i=0;
    while((line[i]=getchar())!='n' && i<lim){
        i++;
    }
    if(line[i]=='n' && i<lim)   
    {
        line[i]=''; // This is line[lim+1]
        return i;
    }
    else if(i==lim){
    while(getchar()!='n')
    i++;
    return i+1;
    }
}

输入和输出如下所示,我在 linux mint 中使用 gcc 编译器。

输出:

Queen
5
Queen
Do you want to continue?        yQueenOfDragons
14
QueenOfDrag
Do you want to continue?        y123456789012345
15
12345678901
Do you want to continue?        yYouKnowNothingJonSnow
21
YouKnowNoth
Do you want to continue?        n

另外,当我在while循环中交换测试条件时,

如下所示
while(i<lim && (line[i]=getchar())!='n')

当行长度超过限制时,它在打印前 10 个字符后打印一个奇怪的"@"字符。输出如下

产出2:

Queen
5
Queen
Do you want to continue?        yQueenOfDragons
13
QueenOfDra@
Do you want to continue?        y12345678901
10
1234567890@
Do you want to continue?        yYouKnowNothingJonSnow
20
YouKnowNot@
Do you want to continue?        n

请解释一下奇怪的行为。提前感谢!

PS:这是Dennis M Ritchie和Brian Kernighan的"C编程语言"中的练习1-16。

我怀疑它正在打印第 11 个字符,因为这个 而表达:

while((line[i]=getchar())!='n' && i<lim){
  i++;
}

i < lim返回 false 时,您已经将getchar()的结果放在line[i]中。

此外,请记住始终使用 null 终止符为字符串留出空间并完成字符串。 Getline(line, lim)并不总是将以 null 结尾的字符串放在 line

程序通过访问line[i]在下一行调用长输入的未定义行为:

while((line[i]=getchar())!='n' && i<lim){

你可以在这里亲眼看到这一点。

由于line指向大小lim数组,因此您应该在写入line[i]之前简单地测试是否i<lim

while(i<lim && (line[i]=getchar())!='n'){

修复该问题会在几行后显示相同的问题(链接(:

if(line[i]=='n' && i<lim)   

修复此问题后,仍然存在一个问题,即您传递printf("%s",…未以零结尾的字符数组的地址(链接(。

我对你的代码做了一些更改

#include<stdio.h>
#define MAX 10
int Getline(char arr[], int lim);
void main(){
    int len=0;
    char c=0;
    char line[MAX]={};
    len=Getline(line,MAX);
    printf("%dn%s",len,line);
    printf("nDo you want to continue?t");
    while((c=getchar())=='y'){
        len=Getline(line,MAX);
        printf("n%dn%s",len,line);
        printf("nDo you want to continue?t");
    }
}
int Getline(char line[], int lim){
    int i=0;
    while((line[i]=getchar())!='n' && i<lim){
        i++;
    }
    if(line[i]=='n' && i<lim)   
    {
        line[i]=''; // This is line[lim+1]
        return i;
    }
    else if(i==lim){
    line[lim] = ''; //Change is being made here adding terminator to string
    while(getchar()!='n')
    i++;
    return i+1;
    }
}

解释: 在字符串中读取直到空指针,即"\0"。由于您在大小大于 10 的情况下以字符串形式声明它,因此它显示了这样的行为

尽管我建议声明大小为 max+1 的字符串,以便省略任何溢出的可能性

因为在大小为 10 的字符串中,应该有 9 个字符和 1 个空字符

最新更新