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

时间:2018-04-29 19:58:48

标签: c arrays linux string

我试图在这段代码中解开谜团但是徒劳无功。以下程序用于打印输入的长度和行。它的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("%d\n%s",len,line);
    printf("\nDo you want to continue?\t");

    while((c=getchar())=='y'){
        len=Getline(line,MAX);
        printf("\n%d\n%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]='\0'; // 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。

3 个答案:

答案 0 :(得分:1)

我怀疑它因为表达而打印了第11个字符:

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

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

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

答案 1 :(得分:1)

您的程序通过访问line[i]

,在以下行调用长输入的未定义行为
while((line[i]=getchar())!='\n' && i<lim){

您可以自己查看here

由于line指向大小为lim的数组,您应该只测试i<lim 之前是否写入line[i]

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

修复该问题后几行显示相同的问题(link):

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

在修复之后,仍然存在一个问题,即您要将printf("%s",…传递给非零终止字符数组(link)的地址。

答案 2 :(得分:0)

我对您的代码进行了一些更改

#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("%d\n%s",len,line);
    printf("\nDo you want to continue?\t");

    while((c=getchar())=='y'){
        len=Getline(line,MAX);
        printf("\n%d\n%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]='\0'; // This is line[lim+1]
        return i;
    }
    else if(i==lim){
    line[lim] = '\0'; //Change is being made here adding terminator to string
    while(getchar()!='\n')
    i++;
    return i+1;
    }
}

说明: 在字符串中读取直到空指针,即&#39; \ 0&#39;。由于你在字符串中声明它大小超过10,它显示了这种行为

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

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