为什么putchar(tolower(ch))打印掉每个角色中的两个?

时间:2017-01-29 23:22:05

标签: c tolower

这是我的代码,输出的每个字母都打印两次。它不是文本文件,只有在我插入putchar(tolower)语句时才会发生,但它的格式完全正确。该陈述有什么问题?

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

#define MAX_STRING_SIZE 20
#define MAX_LIST_SIZE 50

int readFile(char *filename); /* function declaration for readFile, defined below */
void punct();

/* main function */
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("%s: usage %s textFileName \n", argv[0], argv[0]);
        exit(1);
    }

    readFile(argv[1]);

    return 0;
}

int readFile(char *filename) {
    char ch;
    FILE *fPtr;

    fPtr = fopen(filename, "r"); /*open file filename, r is read only */
    if (!fPtr) {
        return 0;
    }

    while ((ch = fgetc(fPtr)) != EOF) {
        putchar(tolower(ch));
        printf("%c", ch);
    }

    fclose(fPtr);

    return 1; /* because success */
}

2 个答案:

答案 0 :(得分:5)

  

输出的每个字母都打印两次

这两行:

putchar(tolower(ch));
printf("%c", ch); 

打印两次相同的角色。

putchar将一个字符添加到标准输出中 printf将格式化文本放入标准输出。在您的情况下,格式化的文本是在上面的行上打印的相同字符。

  

只有当我在

中插入putchar(tolower)语句时才会发生这种情况

这是因为这样做实际上使输出加倍。

答案 1 :(得分:0)

您的代码中存在多个问题:

    必须使用ch类型定义
  • int,以适应fgetc()的所有可能返回值。这些都是unsigned char类型的值加上特殊值EOF。存储到char变量会带来多个问题:

    • 无法再准确测试值EOF。如果类型char未签名,则(ch = fgetc(fp)) == EOF始终为false。相反,如果类型char已签名,则(ch = fgetc(fp)) == EOF可能属于ch = '\377,这是一个有效的字节值。

    • 如果char已签名,则tolower(ch)对于否定值有未定义的行为。

  • 从文件读取的每个字节输出两次:首先是putchar(tolower(ch));,第二次是printf("%c", ch);

以下是更正后的版本:

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

char *progname;    

int readFile(const char *filename) {
    int ch;
    FILE *fPtr;

    fPtr = fopen(filename, "r"); /* open file filename for reading */
    if (!fPtr) {
        fprintf(stderr, "%s: cannot open %s: %s\n",
                progname, filename, strerror(errno));
        return 1;  /* failure */
    }

    while ((ch = fgetc(fPtr)) != EOF) {
        putchar(tolower(ch));
    }
    fclose(fPtr);

    return 0;  /* success */
}

int main(int argc, char *argv[]) {
    progname = argv[0];
    if (argc < 2) {
        fprintf(stderr, "usage: %s textFileName\n", progname);
        return 1;
    }
    return readFile(argv[1]);
}