繁体   English   中英

如何读写非ASCII字符?

[英]How to read/write non ascii characters?

我正在尝试输入文件,并一次将每个字符打印出来,但是有些字符会被忽略。 我以为那是因为它们不是ascii字符,而fgets不知道该怎么办,因为缓冲区是由chars组成的。

int main() {
  while(1)
  {
    char str[50];
    if (fgets(str, 50, stdin) == NULL)
    {
      exit(0);
    }
    for(int i = 0; str[i] != '\n' ; i++)
    {
      printf("%lc", str[i]);
    }
  printf("\n");
  }
return 0;
}

我有一个文件

ALICE’SE’E’E’E’E’E’

但我的代码将其输出为

ALICESEEEEEE

您正在使用fgets,它处理char和char数组(char str [50])。

但是printf格式化程序%lc用于宽字符。

如果要输入宽字符,则需要使用fgetws和类型数组(wchar_t str [50])

如果使用fgets() ,则输入字符\\0可能会出现一些未定义的行为,因为字符串函数在内部使用它们来标记字符串中数据的结尾。

fgets()是一个面向文本的函数,它将读取输入,直到找到换行符\\n为止。 然后在其后放置\\0 ,这样您就知道字符串在哪里结束。

但是对于二进制数据,您可以在数据流的中间获取控制字符,甚至是空字符,有时会使字符在输出中消失(因为已经读取了这些字符,但是当遇到其中一些字符时,代码不会走得更远)稍后再写)。

如果要允许所有二进制字符 ,则在这里有几种方法:

  1. 使用来自stdio的二进制流副本: fread(3)fwrite(3)函数允许您读取二进制数据和文本:
#include <stdio.h>
#include <stdlib.h> /* for EXIT_* constants and exit() */
#define N    (8192)  /* buffer size (guessed, probably not optimum) */
int main()
{
    ssize_t n;
    char buffer[N];
    while((n = fread(buffer, sizeof buffer[0], N, stdin)) > 0) {
        ssize_t nout = fwrite(buffer, sizeof buffer[i], n, stdout);
        if (nout != n) { /* error */
            fprintf(stderr, "Error writing stdout\n");
            exit(EXIT_FAILURE);
        }
    }
    exit(EXIT_SUCCESS);
} /* main */
  1. 使用“ C编程语言”一书中简单的Kernighan&Ritchie的示例(我添加了一些错误处理代码):
#include <stdio.h>
#include <stdlib.h>  /* idem. */
int main()
{
    while((c = fgetc(stdin)) != EOF)
        if (fputc(stdout) == EOF) {
            fprintf("fputc error\n");
            exit(EXIT_FAILURE);
        }
    }
    if (ferror(stdin)) {
        fprintf("fgetc error\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
} /* main */
  1. 或使用标准的UNIX系统调用:
#include <unistd.h>  /* for prototypes for read()/write() syscalls */
#include <stdio.h>
#include <stdlib.h>
#define N    (8192)  /* guessed buffer size */
int main()
{
    char buffer[N];
    ssize_t n;
    while ((n = read(0, buffer, sizeof buffer)) > 0) {
        ssize_t nout;
        nout = write(1, buffer, sizeof buffer));
        if (nout != n) {
            fprintf(stderr, "write: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
    }
    if (n < 0) {
        fprintf(stderr, "read: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
} /* main */

但请注意,您可能会获得的最有效的代码可能是K&R书籍中面向字符的原始示例,因为stdio将选择最佳的缓冲区大小,尽管循环执行次数较多,但它会使运行速度更快。

注意

无论如何,您的输出将远远不是您想要的,因为某些控制字符不会输出到终端,而是被解释为控制字符(最流行的是\\n ,这会使终端在下一行继续)。处理这个。

即使您将多字节字符读取为单个字节,也可以使用给出的示例进行处理,因为使用两个字节的字符将被读取为两个,但是在打印时,这些将成为终端应显示的单个字符。 只要您不对数据流进行任何转换,在此之上的示例代码片段的输出就不会有差异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM