Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中用空格逐字读取文件_C_File - Fatal编程技术网

在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);
}
}
或者,您可以例如:阅读整行并检查是否从