当使用printf时,换行符会使字符串消失

时间:2016-01-10 10:30:48

标签: c

我正在编写一个程序,它接受一个输入文件,其中包含由主题标签(A,B,C ...)组成的字符图,从控制台读取字符串并通过绘制字符来打印出该字符串到输入文件。

注意:正如您将在下面看到的那样,输入文件包含“。”而不是空格。这些在我的代码中被替换为空格。

由于某些原因,当我在绘制一个角色后打印一个换行符时,该角色的部分会消失。

我知道这听起来很复杂,所以我将提供下面的所有文件和输出。

以下是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct{
    char znak[5][5 + 1];
} slovo;

void napuni(slovo *znakovi, FILE *ulaz);

int main(){
    int i,j;
    FILE *ulaz = fopen("ascii.in", "r");
    slovo *znakovi = calloc(27, sizeof(slovo));
    napuni(znakovi, ulaz);
    fclose(ulaz);
    FILE *izlaz = fopen("ascii.out", "w");
    char *tekst = calloc(50,sizeof(char));
    fgets(tekst,50,stdin);
    char *znak = strchr(tekst, '#');
    *znak = '\0';
    int duljina = strlen(tekst);
    for (j = 0; j < 5; j++){
        for (i = 0; i < duljina; i++){
                int znak2 = toupper(tekst[i]) - 65;
                fprintf(izlaz, "%s", znakovi[znak2].znak[j]);
        }
        fprintf(izlaz,"\n");
    }
    fclose(izlaz);
    return 0;
}

void napuni(slovo *znakovi, FILE *ulaz){
    char redak[6];
    int i,j;
    for (i = 0; i < 27; i++){

        for (j = 0; j < 7; j++){
            if (feof(ulaz)) break;
            fgets(redak,6,ulaz);
            if (redak[0] == '\n' || redak[0] == 32) continue;
            char *znak = strchr(redak, '.');
            while(znak != NULL){
                *znak = 32;
                znak = strchr(redak,'.');
            }
            strcpy(znakovi[i].znak[j], redak);
            printf("\n%s",znakovi[i].znak[j]); // this line prints the character to console for testing
        }
        printf("\n"); //when this line is uncommented pieces of the character disappear
    }
}

这是输入文件:

..#..
.#.#.
.###.
.#.#.
.#.#.

.##..
.#.#.
.##..
.#.#.
.##..

..#..
.#.#.
.#...
.#.#.
..#..

.##..
.#.#.
.#.#.
.#.#.
.##..

.###.
.#...
.##..
.#...
.###.

.###.
.#...
.##..
.#...
.#...

..#..
.#...
.#.##
.#..#
..##.

.#.#.
.#.#.
.###.
.#.#.
.#.#.

..#..
..#..
..#..
..#..
..#..

...#.
...#.
...#.
.#.#.
..#..

.#.#.
.#.#.
.##..
.#.#.
.#.#.

.#...
.#...
.#...
.#...
.###.

#...#
##.##
#.#.#
#...#
#...#

#..#.
##.#.
#.##.
#..#.
#..#.

..#..
.#.#.
.#.#.
.#.#.
..#..

.##..
.#.#.
.##..
.#...
.#...

..#..
.#.#.
.#.#.
.#.#.
..##.

.##..
.#.#.
.##..
.##..
.#.#.

..##.
.#...
.###.
...#.
.##..

.###.
..#..
..#..
..#..
..#..

.#.#.
.#.#.
.#.#.
.#.#.
.###.

.#.#.
.#.#.
.#.#.
.#.#.
..#..

#...#
#...#
#.#.#
#.#.#
.#.#.

#...#
.#.#.
..#..
.#.#.
#...#

.#.#.
.#.#.
.###.
...#.
..##.

.###.
...#.
..#..
.#...
.###.

..#..
.#.#.
...#.
..#..
..#..

当我不在其间插入换行符时,这是一个测试输出(只是一次打印出一个字符):

  #
 # #
 ###
 # #
 # #
 ##
 # #
 ##
 # #
 ##
  #
 # #
 #
 # #
  #
 ##
 # #
 # #
 # #
 ##
 ###
 #
 ##
 #
 ###
 ###
 #
 ##
 #
 #
  #
 #
 # ##
 #  #
  ##
 # #
 # #
 ###
 # #
 # #
  #
  #
  #
  #
  #
   #
   #
   #
 # #
  #
 # #
 # #
 ##
 # #
 # #
 #
 #
 #
 #
 ###
#   #
## ##
# # #
#   #
#   #
#  #
## #
# ##
#  #
#  #
  #
 # #
 # #
 # #
  #
 ##
 # #
 ##
 #
 #
  #
 # #
 # #
 # #
  ##
 ##

正如您所见,它的行为符合预期。但是,如果我在其间插入换行符,则字符会被破坏。见下文:

  #
 # #
 ###
 # #

 # #
 ##
 # #

 ##
 # #
 ##

  #
 # #
 #

 # #
  #
 ##

 # #
 # #
 # #
 ##

 ###
 #
 ##

 #
 ###
 ###

 #
 ##
 #

 #
  #
 #

 # ##
 #  #
  ##

 # #
 # #
 ###
 # #

 # #
  #
  #

  #
  #
  #

   #
   #
   #

 # #
  #
 # #

 # #
 ##
 # #
 # #

 #
 #
 #

 #
 ###
#   #

## ##
# # #
#   #

#   #
#  #
## #

# ##
#  #
#  #

  #
 # #
 # #
 # #

  #
 ##
 # #

 ##
 #
 #

  #
 # #
 # #

 # #
  ##
 ##

基本上就是这样。我是C的初学者,所以感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

您的代码中存在缓冲区溢出错误。您将redak声明为:

char redak[6];

然后用这一行覆盖内存的结尾:

redak[6] = '\0';

结果是未定义的行为。请注意,像valgrind这样的工具可以帮助您轻松捕获此类错误。

另一个问题是您的for循环:条件应该是j<6而不是7。

最后,redak的大小应为7,fgets()也会相应更改。否则fgets不会读取换行符,因此您开始阅读&#34; next&#34;从错误的位置排队。请记住,fgets最多只读取一个大小字符。

这也意味着char znak[5][5 + 1]应更改为char znak[6][7]