【问题标题】:Splitting a long string拆分长字符串
【发布时间】:2018-06-07 16:02:20
【问题描述】:

我有一个存档results.csv,我需要阅读该存档的前两行,拆分第二行并在output.txt 上打印出来。不知怎的,它没有打印任何东西,但我不知道原因。

我没有添加我确定没问题的功能。

命令:a.c results.csv

第一行: date,home_team,away_team,home_score,away_score,tournament,city,country,neutral

第二行: 18721130,Scotland,England,0,0,Friendly,Glasgow,Scotland,FALSE

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

typedef struct
{
    char *line1;
    long int date;
    char *h_team;
    char *a_team;
    int gols_h_team;
    int gols_a_team;
    char *reason;
    char *city;
    char *country;
    char *neutral_field;

}Data;

void alloc_Data(Data *d, int size)
{
d->line1 = (char*)malloc(50*sizeof(char)); 
d->h_team = (char*)malloc(30*sizeof(char)); 
d->a_team = (char*)malloc(30*sizeof(char)); 
d->reason = (char*)malloc(30*sizeof(char)); 
d->city = (char*)malloc(30*sizeof(char)); 
d->country = (char*)malloc(30*sizeof(char)); 
d->neutral_field = (char*)malloc(9*sizeof(char)); 
}

void store(Data *d, FILE *input, FILE *output, int size)
{

    fscanf(input,  "%s", d[0].line1);
    fprintf(output,  "%s\n", d[0].line1);

    for(int i = 1; i < size; i++)
    {
        fscanf(input, "%li,%[^,]s%[^,]s%d,%d,%[^,]s%[^,]s%[^,]s%[^,]s", &d[i].date, d[i].h_team, d[i].a_team, &d[i].gols_h_team, &d[i].gols_a_team, d[i].reason, d[i].city, d[i].country, d[i].neutral_field );
        fprintf(output, "%li,%s,%s,%d,%d,%s,%s,%s,%s\n", d[i].date, d[i].h_team, d[i].a_team, d[i].gols_h_team, d[i].gols_a_team, d[i].reason, d[i].city, d[i].country, d[i].neutral_field );

    }

}

int main(int argc, char *argv[])
{
    FILE *input;
    FILE *output;
    char *string = "output.txt";
    int size = 2;

    open_input(argv, &input);   
    open_output(string, &output);   

    Data *d;
    d = (Data*)malloc(size*sizeof(Data)); 
    alloc_Data(d, size);

    store(d, input, output, size);

    free(d);

    return 0;
}

【问题讨论】:

  • 请不要省略有效的函数,因为它们可能不会。但更重要的是,存储 scanf 的结果并确保它是您期望的结果。并使用调试器。
  • 您是否希望%[^,]s 成为某种正则表达式解析器?因为 scanf 不是正则表达式。
  • d[0].line1 只有 50 个字节长,但文件的第一行是 78 个字符。
  • 如果你为你的字符串分配固定的数量,为什么不用数组呢?特别是因为你没有释放你分配的字符串。
  • "%li,%[^,]s%[^,]... 不会解析传递 "%li,%[^,]"。它总是无法匹配ss 从不关注非,

标签: c string split scanf archive


【解决方案1】:

OP 的fscanf() 格式与%[^,] 之后的s 混淆,并且缺少,@Gem Taylor

更好的选择是使用fgets() 读取所有 行。 (包括第一个)

// fscanf(input, "%li,%[^,]s%[^,]s%d,%d,%[^,]s%[^,]s%[^,]s%[^,]s",...d[i].neutral_field );

#define EXPECTED_MAX_BUFFER_SIZE 150
char buffer[EXPECTED_MAX_BUFFER_SIZE * 2];  // suggest using 2x expected max size
if (fgets(buffer, sizeof buffer, input)) {

然后使用sscanf() 解析团队结果。最后使用" %n" 是测试整个sscanf() 是否成功且没有多余垃圾的简单方法。 sscanf() 值得宽度限制和复杂的扫描受益于一些定义来管理说明符。注意"%29[^,]"之后没有s

    int n = 0;
    #define FDat "%li ,"
    #define FScr "%d ,"
    #define Ftxt " %29[^,],"
    #define Fneu " %8[^,]"
    sscanf(buffer, FDat Ftxt Ftxt FScr FScr Ftxt Ftxt Ftxt Fneu " %n", 
        &d[i].date, d[i].h_team, d[i].a_team, 
        &d[i].gols_h_team, &d[i].gols_a_team, 
        d[i].reason, d[i].city, d[i].country, d[i].neutral_field, &n);

    if (n > 0 && buffer[n] == '\0') {
      // success
      fprintf(output, ...
    } else {
      // bad input
    }

【讨论】:

    猜你喜欢
    • 2015-08-09
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    相关资源
    最近更新 更多