C 不同操作系统中可能出现的新行字符有哪些
我们有一个逐行读取文件的代码,每一行都存储为字符串。问题是Linux在行的末尾添加了“\n”;windows在行的末尾添加“\r\n”,ios在行的末尾添加“\r”。我们想用'\0'替换所有这些特殊字符,以便获得字符串 其他操作系统是否添加了其他字符?我们需要处理这个问题 为了回应下面的评论,我尝试使用文本文件模式C 不同操作系统中可能出现的新行字符有哪些,c,C,我们有一个逐行读取文件的代码,每一行都存储为字符串。问题是Linux在行的末尾添加了“\n”;windows在行的末尾添加“\r\n”,ios在行的末尾添加“\r”。我们想用'\0'替换所有这些特殊字符,以便获得字符串 其他操作系统是否添加了其他字符?我们需要处理这个问题 为了回应下面的评论,我尝试使用文本文件模式 file = fopen ( filename, "rt" ); while(fgets ( buf, sizeof buf, buf ) != NULL) { (*prop
file = fopen ( filename, "rt" );
while(fgets ( buf, sizeof buf, buf ) != NULL)
{
(*properties)->url= (char *) malloc(strlen(buf)+1);
strcpy( (*properties)->url, buf);
/////...................more code
}
//line x-->
strncpy(url,properties->url,strlen(properties->url));
在x行,gdb打印
“\r\n\0”用于属性->url
当我的url为“时,有三种相对常见的换行规则:
\r\n
、\n
和\r
,当编辑器对换行规则感到困惑时,可能会出现第四种换行规则,\n\r
。如果一种方法支持通用换行符,那么它将同时支持所有四个换行符,即使是固定的
使用通用换行符支持逐行读取文件很容易。唯一的问题是,来自行缓冲源的交互式输入看起来像是延迟了一行读取。为了避免这种情况,可以将行读取到动态缓冲区中,最多可达,但不包括换行符;并在阅读下一行时使用换行符。例如:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
ssize_t getline_universal(char **dataptr, size_t *sizeptr, FILE *in)
{
char *data = NULL;
size_t size = 0;
size_t used = 0;
int c;
if (!dataptr || !sizeptr || !in) {
errno = EINVAL;
return -1;
}
if (*sizeptr) {
data = *dataptr;
size = *sizeptr;
} else {
*dataptr = data;
*sizeptr = size;
}
/* Ensure there are at least 2 chars available. */
if (size < 2) {
size = 2;
data = malloc(size);
if (!data) {
errno = ENOMEM;
return -1;
}
*dataptr = data;
*sizeptr = size;
}
/* Consume leading newline. */
c = fgetc(in);
if (c == '\n') {
c = fgetc(in);
if (c == '\r')
c = fgetc(in);
} else
if (c == '\r') {
c = fgetc(in);
if (c == '\n')
c = fgetc(in);
}
/* No more data? */
if (c == EOF) {
data[used] = '\0';
errno = 0;
return -1;
}
while (c != '\n' && c != '\r' && c != EOF) {
if (used + 1 >= size) {
if (used < 7)
size = 8;
else
if (used < 1048576)
size = (3 * used) / 2;
else
size = (used | 1048575) + 1048577;
data = realloc(data, size);
if (!data) {
errno = ENOMEM;
return -1;
}
*dataptr = data;
*sizeptr = size;
}
data[used++] = c;
c = fgetc(in);
}
/* Terminate line. We know used < size. */
data[used] = '\0';
/* Do not consume the newline separator. */
if (c != EOF)
ungetc(c, in);
/* Done. */
errno = 0;
return used;
}
请注意,因为
free(NULL)
是安全的,所以在调用getline\u universal(&line\u buf,&line\u max,stream)之前,可以丢弃缓冲区(使用free(line\u buf);line\u buf=NULL;line\u max=0;
)。查看悬赏奖的答案。不幸的是,几乎没有办法涵盖所有未知的异国情调操作系统(那些由一些愚昧的狂人设计的)。您可能应该首先将范围限制在成熟的操作系统上。其他操作系统是否添加了其他字符?我们需要处理这个问题。为什么?C标准有一个明确定义的“文本”模式,用于将所有换行符转换为\n
字符的流,您的问题是您将其作为二进制文件读取。如果您将其作为文本文件读取或写入,那么您就不在乎操作系统如何解释“\n”。祝您好运,在一个文件上用NUL替换操作系统提供的记录(行)边界。您为什么不能简单地执行bool new\u line=false;if(isspace(ch)){while(ch='\n'| | ch='\r'{new_line=true;ch=fgetc(in);}}
?@Lundin:这也会跳过(消耗)空行。如果您检查提供的bool变量,则不会。@Lundin:the循环而(ch='\n'| ch='\r'{new u line=true;ch=fgetc(in)}
最肯定消耗空行。这就是为什么我没有使用它。如前所述,我的答案中的代码即使使用行缓冲的交互式输入也可以正常工作,并且不会跳过空行。它唯一的缺点是,它使用换行符时没有告诉调用方确切的换行符类型。“函数的工作原理很像…getline()”还有其他区别:它可以设置errno=0
——这是最意想不到的。它在流中保留行结束字符。如果最后一行是空行,则返回-1。
int main(void)
{
unsigned long linenum = 0u;
char *line_buf = NULL;
size_t line_max = 0;
ssize_t line_len;
while (1) {
line_len = getline_universal(&line_buf, &line_max, stdin);
if (line_len < 0)
break;
linenum++;
printf("%lu: \"%s\" (%zd chars)\n", linenum, line_buf, line_len);
fflush(stdout);
}
if (errno) {
fprintf(stderr, "Error reading from standard input: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
/* Not necessary before exiting, but here's how to
safely discard the line buffer: */
free(line_buf);
line_buf = NULL;
line_max = 0;
line_len = 0;
return EXIT_SUCCESS;
}