函数fscanf忽略.txt文件中的空格分隔符

时间:2015-04-05 04:56:24

标签: c struct malloc memcpy scanf

我正在尝试在C中扫描以下格式的文本文件:

key01 value01
key02 value02
key03 value03

我想获取键和值字符串并将它们分配给我创建的结构:

struct Mapping
{
  char  key[sizeof(char) * 5];
  char  value[sizeof(char) * 7];
} MapElement;

我的代码如下:

void initialize_server_map(struct Mapping serverMap[])
{
  char* fileName = "server1.txt";
  FILE *fp = fopen(fileName, "r");
  char *lineKey = (char*)malloc(sizeof(char) * 5);
  char *lineValue = (char*)malloc(sizeof(char) * 7);
  int i = 0;
  while (fscanf(fp, "%s %s", lineKey, lineValue) != EOF) {
    struct Mapping mapping;
    memcpy(mapping.key, lineKey, sizeof(char) * 5);
    memcpy(mapping.value, lineValue, sizeof(char) * 7);
    printf("key: %s value: %s\n", mapping.key, mapping.value);
    serverMap[i] = mapping;
    i++;
  }
  fclose(fp);
}

int main(void)
{
  int size = 4;
  struct Mapping serverMap[size];
  initialize_server_map(serverMap);
}

我的输出如下:

key: key01value01 value: value01
key: key02value02 value: value02
key: key03value03 value: value03
key: key04value04 value: value04

当然,我想要这个输出:

key: key01 value: value01
key: key02 value: value02
key: key03 value: value03
key: key04 value: value04

我确信它必须对我分配内存的方式做些什么。有人可以帮我解决这个问题吗?另外,有更有效的方法吗?

2 个答案:

答案 0 :(得分:1)

由于数组的超出限制访问,您遇到了未定义的行为。

为了存储"key01",您需要一个大小至少为6 - 5的字符数组,以及一个用于终止空字符的数组。

同样,您需要一个至少8的数组来存储"value01"

您分别声明大小为57的数组。因此,在

中使用时,您将修改数组越界
while (fscanf(fp, "%s %s", lineKey, lineValue) != EOF) {

答案 1 :(得分:1)

好吧,至少你已经忘记了在字符串中尾随'\ 0'的空间。因此,如果你有5个字符串,你应该分配6个字符。

但通常整个方法都非常脆弱。如果输入数据中的键长度超过5个字符怎么办?传统方法是对scanf使用“足够大”的缓冲区(比如几百个字节),使用格式中的长度限制器限制scanf中可能的字符串长度(例如“%20s”而不是“% s“)然后通过strdup分配获得的空间。

所以整个块看起来像:

struct Mapping {
   char* key;
   char* value;
};
...
char lineKey[51];
char lineValue[51];
while (fscanf(fp, "%50s %50s", lineKey, lineValue) != EOF) {
    struct Mapping* mp = (struct Mapping*)malloc(sizeof(struct Mapping));
    assert(mp);
    mp->key = strdup(lineKey);
    mp->value = strdup(lineValue);
    ...   
}