在C语言中用空格逐字读取文件
在C语言中用空格逐字读取文件,c,file,C,File,文本文件中的输入数据如下: Mike 107 Europe 6798 Steve 023 New York 2588 Adam 057 South Town 1902 Adam 124 Asia 5555 用空格分隔的数据 C代码从文件中读取数据的方法是: char name[30]; int code; char l
文本
文件中的输入
数据如下:
Mike 107 Europe 6798
Steve 023 New York 2588
Adam 057 South Town 1902
Adam 124 Asia 5555
用空格分隔的数据
C代码
从文件中读取数据的方法是:
char name[30];
int code;
char local[30];
int id;
while (fscanf(fp, "%s %d %[^ ] %d", name, &code, local, &id) != EOF){
printf("%s-%d-%s-%d\n", name, code, local, id);
}
我的代码的问题是,对于local
,总是一次读取一个单词。我的打印输出是:
Mike 107 Europe 6798
Steve 023 New 2588
Adam 057 South 1902
Adam 124 Asia 5555
纽约
和南城
被截断。如何解决这个问题?您的数据似乎需要两种方式—使用空格作为分隔符和内容。这充其量只是一个模棱两可的设计决策,CSV可能是一个更好的解决方案。但是,您可以使用关于数据内容的假设,至少在示例输入中可以解决问题
假设local
列不能包含数字字符,则:
fscanf(fp, "%s %d %[^0123456789\t] %d", name, &code, local, &id)
我已经加入了\t
(选项卡),以确保不会绊倒它。然而,这样做的效果是local
包含所有尾随空格。你可以这样修剪它们:
for( int i = strlen(local) - 1; local[i] == ' '; i-- )
{
local[i] = 0 ;
}
或者,您可以读取整行并对其进行处理,以使单个空格不是分隔符,而是大于1的空格或制表符。或者,如果您不能保证没有选项卡,您可以按列号提取字段数据,但这一切都变得相当复杂:
while( fgets( line, sizeof(line), fp ) != NULL )
{
line[NAME_COL-1] = 0 ;
line[CODE_COL-1] = 0 ;
line[ID_COL-1] = 0 ;
sscanf(&s[NAME_COL], "%s", name) ;
sscanf(&s[CODE_COL], "%d", &code) ;
sscanf(&s[LOCAL_COL], "%s", local) ;
sscanf(&s[ID_COL], "%d", &id) ;
for( int i = strlen(local) - 1; local[i] == ' '; i-- )
{
local[i] = 0 ;
}
printf("%s-%d-%s-%d\n", name, code, local, id);
}
您的数据似乎需要两种方式—将空间用作分隔符和内容。这充其量只是一个模棱两可的设计决策,CSV可能是一个更好的解决方案。但是,您可以使用关于数据内容的假设,至少在示例输入中可以解决问题
假设local
列不能包含数字字符,则:
fscanf(fp, "%s %d %[^0123456789\t] %d", name, &code, local, &id)
我已经加入了\t
(选项卡),以确保不会绊倒它。然而,这样做的效果是local
包含所有尾随空格。你可以这样修剪它们:
for( int i = strlen(local) - 1; local[i] == ' '; i-- )
{
local[i] = 0 ;
}
或者,您可以读取整行并对其进行处理,以使单个空格不是分隔符,而是大于1的空格或制表符。或者,如果您不能保证没有选项卡,您可以按列号提取字段数据,但这一切都变得相当复杂:
while( fgets( line, sizeof(line), fp ) != NULL )
{
line[NAME_COL-1] = 0 ;
line[CODE_COL-1] = 0 ;
line[ID_COL-1] = 0 ;
sscanf(&s[NAME_COL], "%s", name) ;
sscanf(&s[CODE_COL], "%d", &code) ;
sscanf(&s[LOCAL_COL], "%s", local) ;
sscanf(&s[ID_COL], "%d", &id) ;
for( int i = strlen(local) - 1; local[i] == ' '; i-- )
{
local[i] = 0 ;
}
printf("%s-%d-%s-%d\n", name, code, local, id);
}
我该如何解决这个问题
你可以一直读到两个连续的空格。您必须自己实现这种逻辑,例如:
#include <stdio.h>
#include <string.h>
const char input[] =
"Mike 107 Europe 6798 \n"
"Steve 023 New York 2588\n"
"Adam 057 South Town 1902\n"
"Adam 124 Asia 5555\n"
;
int main() {
FILE *in = fmemopen((char*)input, sizeof(input) - 1, "r");
char name[30];
int code;
char local[30];
int id;
char line[250];
int localstart;
const char *localend;
while (fgets(line, sizeof(line), in) != NULL) {
if (sscanf(line, "%s%d %n", name, &code, &localstart) != 2) break;
localend = strstr(line + localstart, " ");
if (localend == NULL) break;
const size_t locallen = localend - (line + localstart);
memcpy(local, line + localstart, locallen);
local[locallen] = '\0';
if (sscanf(line + locallen, "%d", &id) != 1) break;
printf("%s-%d-%s-%d\n", name, code, local, id);
}
}
#包括
#包括
常量字符输入[]=
“Mike 107 Europe 6798\n”
“史蒂夫023纽约2588\n”
“Adam 057南部城镇1902\n”
“Adam 124亚洲5555\n”
;
int main(){
FILE*in=fmemopen((char*)输入,sizeof(input)-1,“r”);
字符名[30];
int代码;
char-local[30];
int-id;
字符行[250];
int localstart;
const char*localend;
while(fgets(line,sizeof(line),in)!=NULL){
如果(sscanf(第%s%d%n行)、名称、代码和本地启动)!=2)中断;
localend=strstrstr(行+localstart,“”);
如果(localend==NULL)中断;
const size\u t locallen=localend-(line+localstart);
memcpy(local,line+localstart,locallen);
本地[locallen]='\0';
如果(sscanf(line+locallen,“%d”,&id)!=1)中断;
printf(“%s-%d-%s-%d\n”,名称、代码、本地id);
}
}
或者,您可以例如:阅读整行内容并从后面检查是否存在。第3列从第2列之后的空格开始,第4列之前的空格开始
#include <stdio.h>
#include <string.h>
#include <ctype.h>
const char input[] =
"Mike 107 Europe 6798 \n"
"Steve 023 New York 2588\n"
"Adam 057 South Town 1902\n"
"Adam 124 Asia 5555\n"
;
int main() {
FILE *in = fmemopen((char*)input, sizeof(input) - 1, "r");
char name[30];
int code;
char local[30];
int id;
char line[250];
int localstart;
while (fgets(line, sizeof(line), in) != NULL) {
if (sscanf(line, "%s%d %n", name, &code, &localstart) != 2) break;
const char *end = line + strlen(line) - 1;
// ignore trailing spaces
while (end != line && isspace(*end)) end--;
// jump over last digit
while (end != line && isdigit(*end)) end--;
// scan the last digit
if (sscanf(end + 1, "%d", &id) != 1) break;
// rewind spaces
while (end != line && isspace(*end)) end--;
// at end + 1 ends 'local' column
const char *localend = end + 1;
const size_t locallen = localend - (line + localstart);
memcpy(local, line + localstart, locallen);
local[locallen] = '\0';
printf("%s-%d-%s-%d\n", name, code, local, id);
}
}
#包括
#包括
#包括
常量字符输入[]=
“Mike 107 Europe 6798\n”
“史蒂夫023纽约2588\n”
“Adam 057南部城镇1902\n”
“Adam 124亚洲5555\n”
;
int main(){
FILE*in=fmemopen((char*)输入,sizeof(input)-1,“r”);
字符名[30];
int代码;
char-local[30];
int-id;
字符行[250];
int localstart;
while(fgets(line,sizeof(line),in)!=NULL){
如果(sscanf(第%s%d%n行)、名称、代码和本地启动)!=2)中断;
常量字符*结束=行+字符串(行)-1;
//忽略尾随空格
而(end!=行和&isspace(*end))end--;
//跳过最后一位数
while(end!=行&&isdigit(*end))end--;
//扫描最后一个数字
如果(sscanf(结束+1、%d、&id)!=1)中断;
//倒带空间
而(end!=行和&isspace(*end))end--;
//在末尾+1结束“本地”列
const char*localend=end+1;
const size\u t locallen=localend-(line+localstart);
memcpy(local,line+localstart,locallen);
本地[locallen]='\0';
printf(“%s-%d-%s-%d\n”,名称、代码、本地id);
}
}
fmemopen
功能在我在这里测试的linux上可用-它可能在windows上不可用
我该如何解决这个问题
你可以一直读到两个连续的空格。您必须自己实现这种逻辑,例如:
#include <stdio.h>
#include <string.h>
const char input[] =
"Mike 107 Europe 6798 \n"
"Steve 023 New York 2588\n"
"Adam 057 South Town 1902\n"
"Adam 124 Asia 5555\n"
;
int main() {
FILE *in = fmemopen((char*)input, sizeof(input) - 1, "r");
char name[30];
int code;
char local[30];
int id;
char line[250];
int localstart;
const char *localend;
while (fgets(line, sizeof(line), in) != NULL) {
if (sscanf(line, "%s%d %n", name, &code, &localstart) != 2) break;
localend = strstr(line + localstart, " ");
if (localend == NULL) break;
const size_t locallen = localend - (line + localstart);
memcpy(local, line + localstart, locallen);
local[locallen] = '\0';
if (sscanf(line + locallen, "%d", &id) != 1) break;
printf("%s-%d-%s-%d\n", name, code, local, id);
}
}
#包括
#包括
常量字符输入[]=
“Mike 107 Europe 6798\n”
“史蒂夫023纽约2588\n”
“Adam 057南部城镇1902\n”
“Adam 124亚洲5555\n”
;
int main(){
FILE*in=fmemopen((char*)输入,sizeof(input)-1,“r”);
字符名[30];
int代码;
char-local[30];
int-id;
字符行[250];
int localstart;
const char*localend;
while(fgets(line,sizeof(line),in)!=NULL){
如果(sscanf(第%s%d%n行)、名称、代码和本地启动)!=2)中断;
localend=strstrstr(行+localstart,“”);
如果(localend==NULL)中断;
const size\u t locallen=localend-(line+localstart);
memcpy(local,line+localstart,locallen);
本地[locallen]='\0';
如果(sscanf(line+locallen,“%d”,&id)!=1)中断;
printf(“%s-%d-%s-%d\n”,名称、代码、本地id);
}
}
或者,您可以例如:阅读整行并检查是否从